ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.278
Committed: Wed Sep 3 10:36:25 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-0_9976, rel-0_9977
Changes since 1.277: +1 -0 lines
Log Message:
more theme stuff, but i dislike it

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.170 # define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.157 # include <wininet.h>
7 root 1.75 # pragma warning(disable:4244)
8 root 1.162 # pragma warning(disable:4761)
9 root 1.48 #endif
10    
11 root 1.193 //#define DEBUG 1
12     #if DEBUG
13     # include <valgrind/memcheck.h>
14     #endif
15    
16 root 1.1 #include "EXTERN.h"
17     #include "perl.h"
18     #include "XSUB.h"
19    
20 root 1.131 #ifdef _WIN32
21     # undef pipe
22 root 1.222 // microsoft vs. C
23     # define sqrtf(x) sqrt(x)
24     # define roundf(x) (int)(x)
25     # define atan2f(x,y) atan2(x,y)
26     # define M_PI 3.14159265f
27 root 1.131 #endif
28    
29 root 1.168 #include <assert.h>
30 root 1.80 #include <math.h>
31 root 1.5 #include <string.h>
32 root 1.25 #include <stdio.h>
33 root 1.111 #include <stdlib.h>
34 root 1.5
35 root 1.212 #define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
36    
37 root 1.2 #include <SDL.h>
38 root 1.202 #include <SDL_thread.h>
39 root 1.76 #include <SDL_endian.h>
40 root 1.23 #include <SDL_image.h>
41 root 1.52 #include <SDL_mixer.h>
42 root 1.3 #include <SDL_opengl.h>
43 root 1.5
44 root 1.272 /* work around os x broken headers */
45     #ifdef __MACOSX__
46     typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
47     #endif
48    
49 root 1.124 #define PANGO_ENABLE_BACKEND
50     #define G_DISABLE_CAST_CHECKS
51    
52 root 1.30 #include <glib/gmacros.h>
53    
54 root 1.5 #include <pango/pango.h>
55    
56 root 1.254 #ifndef PANGO_VERSION_CHECK
57     # define PANGO_VERSION_CHECK(a,b,c) 0
58     #endif
59    
60     #if !PANGO_VERSION_CHECK (1, 15, 2)
61 root 1.255 # define pango_layout_get_line_readonly pango_layout_get_line
62     # define pango_layout_get_lines_readonly pango_layout_get_lines
63     # define pango_layout_iter_get_line_readonly pango_layout_iter_get_line
64     # define pango_layout_iter_get_run_readonly pango_layout_iter_get_run
65 root 1.249 #endif
66    
67 root 1.48 #ifndef _WIN32
68     # include <sys/types.h>
69     # include <sys/socket.h>
70     # include <netinet/in.h>
71     # include <netinet/tcp.h>
72     # include <inttypes.h>
73     #endif
74 root 1.28
75 root 1.261 #if __GNUC__ >= 4
76     # define expect(expr,value) __builtin_expect ((expr),(value))
77     #else
78     # define expect(expr,value) (expr)
79     #endif
80    
81     #define expect_false(expr) expect ((expr) != 0, 0)
82     #define expect_true(expr) expect ((expr) != 0, 1)
83    
84 root 1.162 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
85 root 1.121
86 root 1.29 #define FOW_DARKNESS 32
87    
88     #define MAP_EXTEND_X 32
89     #define MAP_EXTEND_Y 512
90    
91 root 1.63 #define MIN_FONT_HEIGHT 10
92 root 1.58
93 root 1.253 /* mask out modifiers we are not interested in */
94     #define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
95    
96 root 1.276 #define KMOD_LRAM 0x10000 // our extension
97    
98 root 1.188 static AV *texture_av;
99    
100 root 1.103 static struct
101     {
102     #define GL_FUNC(ptr,name) ptr name;
103     #include "glfunc.h"
104     #undef GL_FUNC
105     } gl;
106    
107 root 1.192 static void
108     gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
109 root 1.103 {
110     if (gl.BlendFuncSeparate)
111     gl.BlendFuncSeparate (sa, da, saa, daa);
112     else if (gl.BlendFuncSeparateEXT)
113     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
114     else
115     glBlendFunc (sa, da);
116     }
117 root 1.64
118 root 1.192 static GLuint
119     gen_texture ()
120     {
121     GLuint name;
122    
123     if (AvFILL (texture_av) >= 0)
124     name = (GLuint)(size_t)av_pop (texture_av);
125     else
126     glGenTextures (1, &name);
127    
128     return name;
129     }
130    
131     static void
132     del_texture (GLuint name)
133     {
134     /* make a half-assed attempt at returning the memory used by the texture */
135     /* textures are frequently being reused by cfplus anyway */
136     /*glBindTexture (GL_TEXTURE_2D, name);*/
137     /*glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);*/
138     av_push (texture_av, (SV *)(size_t)name);
139     glDeleteTextures (1, &name);
140     }
141    
142 root 1.124 #include "texcache.c"
143 root 1.223 #include "rendercache.c"
144 root 1.124
145     #include "pango-font.c"
146     #include "pango-fontmap.c"
147     #include "pango-render.c"
148    
149 root 1.242 typedef IV DC__Channel;
150     typedef SDL_RWops *DC__RW;
151     typedef Mix_Chunk *DC__MixChunk;
152     typedef Mix_Music *DC__MixMusic;
153 root 1.52
154 root 1.242 typedef PangoFontDescription *DC__Font;
155 root 1.2
156 root 1.121 static int
157     shape_attr_p (PangoLayoutRun *run)
158     {
159     GSList *attrs = run->item->analysis.extra_attrs;
160    
161     while (attrs)
162     {
163     PangoAttribute *attr = attrs->data;
164    
165     if (attr->klass->type == PANGO_ATTR_SHAPE)
166     return 1;
167    
168     attrs = attrs->next;
169     }
170    
171     return 0;
172     }
173    
174 root 1.14 typedef struct cf_layout {
175 root 1.124 PangoLayout *pl;
176 root 1.76 float r, g, b, a; // default color for rgba mode
177 root 1.14 int base_height;
178 root 1.242 DC__Font font;
179 root 1.225 rc_t *rc;
180 root 1.242 } *DC__Layout;
181 root 1.14
182 root 1.242 static DC__Font default_font;
183 root 1.124 static PangoContext *opengl_context;
184     static PangoFontMap *opengl_fontmap;
185 root 1.61
186 root 1.14 static void
187 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
188     {
189 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
190 root 1.110 #ifdef FC_HINT_STYLE
191 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
192 root 1.110 #endif
193 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
194 root 1.19 }
195    
196     static void
197 root 1.242 layout_update_font (DC__Layout self)
198 root 1.17 {
199 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
200 root 1.258 * reasonably well with dejavu/bistream fonts
201 root 1.19 */
202 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
203 root 1.46
204 root 1.61 pango_font_description_set_absolute_size (font,
205     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
206 root 1.58
207 root 1.61 pango_layout_set_font_description (self->pl, font);
208 root 1.17 }
209    
210     static void
211 root 1.242 layout_get_pixel_size (DC__Layout self, int *w, int *h)
212 root 1.14 {
213 root 1.139 PangoRectangle rect;
214 root 1.14
215 root 1.139 // get_pixel_* wrongly rounds down
216     pango_layout_get_extents (self->pl, 0, &rect);
217 root 1.76
218 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
219     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
220    
221     if (!rect.width) rect.width = 1;
222     if (!rect.height) rect.height = 1;
223    
224     *w = rect.width;
225     *h = rect.height;
226 root 1.14 }
227    
228 root 1.174 typedef uint16_t tileid;
229     typedef uint16_t faceid;
230 root 1.42
231 root 1.28 typedef struct {
232 root 1.228 GLuint name;
233 root 1.30 int w, h;
234     float s, t;
235 root 1.39 uint8_t r, g, b, a;
236 root 1.176 tileid smoothtile;
237     uint8_t smoothlevel;
238 root 1.42 } maptex;
239 root 1.30
240     typedef struct {
241 root 1.153 uint32_t player;
242 root 1.174 tileid tile[3];
243 root 1.142 uint16_t darkness;
244 root 1.176 uint8_t stat_width, stat_hp, flags, smoothmax;
245 root 1.28 } mapcell;
246    
247     typedef struct {
248 root 1.30 int32_t c0, c1;
249 root 1.28 mapcell *col;
250     } maprow;
251    
252     typedef struct map {
253     int x, y, w, h;
254 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
255 root 1.174 int faces; tileid *face2tile; // [faceid]
256     int texs; maptex *tex; // [tileid]
257 root 1.42
258 root 1.48 int32_t rows;
259 root 1.28 maprow *row;
260 root 1.242 } *DC__Map;
261 root 1.28
262 root 1.30 static char *
263     prepend (char *ptr, int sze, int inc)
264     {
265     char *p;
266    
267     New (0, p, sze + inc, char);
268     Zero (p, inc, char);
269     Move (ptr, p + inc, sze, char);
270     Safefree (ptr);
271    
272     return p;
273     }
274    
275     static char *
276     append (char *ptr, int sze, int inc)
277     {
278     Renew (ptr, sze + inc, char);
279     Zero (ptr + sze, inc, char);
280    
281     return ptr;
282     }
283    
284     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
285     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
286    
287 root 1.174 static void
288     need_facenum (struct map *self, faceid face)
289     {
290     while (self->faces <= face)
291     {
292     Append (tileid, self->face2tile, self->faces, self->faces);
293     self->faces *= 2;
294     }
295     }
296    
297     static void
298     need_texid (struct map *self, int texid)
299     {
300     while (self->texs <= texid)
301     {
302     Append (maptex, self->tex, self->texs, self->texs);
303     self->texs *= 2;
304     }
305     }
306    
307 root 1.42 static maprow *
308 root 1.242 map_get_row (DC__Map self, int y)
309 root 1.42 {
310     if (0 > y)
311     {
312     int extend = - y + MAP_EXTEND_Y;
313     Prepend (maprow, self->row, self->rows, extend);
314    
315     self->rows += extend;
316     self->y += extend;
317     y += extend;
318     }
319     else if (y >= self->rows)
320     {
321     int extend = y - self->rows + MAP_EXTEND_Y;
322     Append (maprow, self->row, self->rows, extend);
323     self->rows += extend;
324     }
325    
326     return self->row + y;
327     }
328    
329     static mapcell *
330     row_get_cell (maprow *row, int x)
331     {
332     if (!row->col)
333     {
334     Newz (0, row->col, MAP_EXTEND_X, mapcell);
335     row->c0 = x - MAP_EXTEND_X / 4;
336     row->c1 = row->c0 + MAP_EXTEND_X;
337     }
338    
339     if (row->c0 > x)
340     {
341     int extend = row->c0 - x + MAP_EXTEND_X;
342     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
343     row->c0 -= extend;
344     }
345     else if (x >= row->c1)
346     {
347     int extend = x - row->c1 + MAP_EXTEND_X;
348     Append (mapcell, row->col, row->c1 - row->c0, extend);
349     row->c1 += extend;
350     }
351    
352     return row->col + (x - row->c0);
353     }
354    
355     static mapcell *
356 root 1.242 map_get_cell (DC__Map self, int x, int y)
357 root 1.42 {
358     return row_get_cell (map_get_row (self, y), x);
359     }
360    
361 root 1.30 static void
362 root 1.242 map_clear (DC__Map self)
363 root 1.30 {
364     int r;
365    
366     for (r = 0; r < self->rows; r++)
367     Safefree (self->row[r].col);
368    
369     Safefree (self->row);
370    
371     self->x = 0;
372     self->y = 0;
373 root 1.42 self->ox = 0;
374     self->oy = 0;
375 root 1.30 self->row = 0;
376     self->rows = 0;
377     }
378    
379 root 1.267 #define CELL_CLEAR(cell) \
380     do { \
381 root 1.268 if ((cell)->player) \
382     (cell)->tile [2] = 0; \
383 root 1.267 (cell)->darkness = 0; \
384     (cell)->stat_hp = 0; \
385     (cell)->flags = 0; \
386     (cell)->player = 0; \
387     } while (0)
388    
389 root 1.29 static void
390 root 1.242 map_blank (DC__Map self, int x0, int y0, int w, int h)
391 root 1.29 {
392     int x, y;
393 root 1.48 maprow *row;
394 root 1.146 mapcell *cell;
395 root 1.29
396     for (y = y0; y < y0 + h; y++)
397 root 1.30 if (y >= 0)
398     {
399     if (y >= self->rows)
400     break;
401    
402 root 1.48 row = self->row + y;
403 root 1.30
404     for (x = x0; x < x0 + w; x++)
405     if (x >= row->c0)
406     {
407     if (x >= row->c1)
408     break;
409 root 1.29
410 root 1.146 cell = row->col + x - row->c0;
411    
412 root 1.267 CELL_CLEAR (cell);
413 root 1.30 }
414     }
415 root 1.29 }
416    
417 root 1.176 typedef struct {
418     tileid tile;
419     uint8_t x, y, level;
420     } smooth_key;
421    
422     static void
423     smooth_or_bits (HV *hv, smooth_key *key, IV bits)
424     {
425 root 1.181 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1);
426 root 1.176
427     if (SvIOK (*sv))
428     SvIV_set (*sv, SvIVX (*sv) | bits);
429     else
430     sv_setiv (*sv, bits);
431     }
432    
433 root 1.56 static void
434 root 1.75 music_finished (void)
435 root 1.56 {
436     SDL_UserEvent ev;
437    
438     ev.type = SDL_USEREVENT;
439     ev.code = 0;
440     ev.data1 = 0;
441     ev.data2 = 0;
442    
443 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
444 root 1.56 }
445    
446 root 1.71 static void
447     channel_finished (int channel)
448     {
449     SDL_UserEvent ev;
450    
451     ev.type = SDL_USEREVENT;
452     ev.code = 1;
453 root 1.74 ev.data1 = (void *)(long)channel;
454 root 1.71 ev.data2 = 0;
455    
456     SDL_PushEvent ((SDL_Event *)&ev);
457     }
458    
459 root 1.113 static unsigned int
460     minpot (unsigned int n)
461     {
462     if (!n)
463     return 0;
464    
465     --n;
466    
467     n |= n >> 1;
468     n |= n >> 2;
469     n |= n >> 4;
470     n |= n >> 8;
471     n |= n >> 16;
472    
473     return n + 1;
474     }
475    
476 root 1.235 static unsigned int
477     popcount (unsigned int n)
478     {
479     n -= (n >> 1) & 0x55555555U;
480     n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U);
481     n = ((n >> 4) + n) & 0x0f0f0f0fU;
482     n *= 0x01010101U;
483    
484     return n >> 24;
485     }
486    
487 root 1.167 /* SDL should provide this, really. */
488     #define SDLK_MODIFIER_MIN 300
489     #define SDLK_MODIFIER_MAX 314
490    
491 root 1.207 /******************************************************************************/
492    
493 root 1.209 static GV *draw_x_gv, *draw_y_gv, *draw_w_gv, *draw_h_gv;
494     static GV *hover_gv;
495    
496 root 1.207 static int
497     within_widget (SV *widget, NV x, NV y)
498     {
499     HV *self;
500     SV **svp;
501     NV wx, ww, wy, wh;
502    
503     if (!SvROK (widget))
504     return 0;
505    
506     self = (HV *)SvRV (widget);
507    
508     if (SvTYPE (self) != SVt_PVHV)
509     return 0;
510    
511     svp = hv_fetch (self, "y", 1, 0); wy = svp ? SvNV (*svp) : 0.;
512     if (y < wy)
513     return 0;
514    
515     svp = hv_fetch (self, "h", 1, 0); wh = svp ? SvNV (*svp) : 0.;
516     if (y >= wy + wh)
517     return 0;
518    
519     svp = hv_fetch (self, "x", 1, 0); wx = svp ? SvNV (*svp) : 0.;
520     if (x < wx)
521     return 0;
522    
523     svp = hv_fetch (self, "w", 1, 0); ww = svp ? SvNV (*svp) : 0.;
524     if (x >= wx + ww)
525     return 0;
526    
527     svp = hv_fetch (self, "can_events", sizeof ("can_events") - 1, 0);
528     if (!svp || !SvTRUE (*svp))
529     return 0;
530    
531     return 1;
532     }
533    
534 root 1.277 /******************************************************************************/
535    
536 root 1.276 /* process keyboard modifiers */
537     static int
538     mod_munge (int mod)
539     {
540     mod &= MOD_MASK;
541    
542     if (mod & (KMOD_META | KMOD_ALT))
543     mod |= KMOD_LRAM;
544    
545     return mod;
546     }
547    
548 root 1.272 static void
549     deliantra_main ()
550     {
551 root 1.273 char *argv[] = { 0 };
552     call_argv ("::main", G_DISCARD | G_VOID, argv);
553 root 1.272 }
554    
555     #ifdef __MACOSX__
556     /* to due surprising braindamage on the side of SDL design, we
557     * do some mind-boggling hack here: SDL requires a custom main()
558     * on OS X, so... we provide one and call the original main(), which,
559     * due to share dlibrary magic, calls -lSDLmain's main, not perl's main,
560     * and which calls our main (== SDL_main) back.
561     */
562     extern C_LINKAGE int
563     main (int argc, char *argv[])
564     {
565     deliantra_main ();
566     }
567    
568     #undef main
569    
570     extern C_LINKAGE int main (int argc, char *argv[]);
571    
572     static void
573     SDL_braino (void)
574     {
575     char *argv[] = { "deliantra client", 0 };
576     (main) (1, argv);
577     }
578     #else
579     static void
580     SDL_braino (void)
581     {
582     deliantra_main ();
583     }
584     #endif
585    
586 root 1.242 MODULE = Deliantra::Client PACKAGE = DC
587 root 1.1
588 root 1.11 PROTOTYPES: ENABLE
589    
590 root 1.5 BOOT:
591     {
592 root 1.242 HV *stash = gv_stashpv ("DC", 1);
593 root 1.51 static const struct {
594     const char *name;
595     IV iv;
596     } *civ, const_iv[] = {
597     # define const_iv(name) { # name, (IV)name }
598 root 1.167 const_iv (SDLK_MODIFIER_MIN),
599     const_iv (SDLK_MODIFIER_MAX),
600    
601 root 1.51 const_iv (SDL_ACTIVEEVENT),
602     const_iv (SDL_KEYDOWN),
603     const_iv (SDL_KEYUP),
604     const_iv (SDL_MOUSEMOTION),
605     const_iv (SDL_MOUSEBUTTONDOWN),
606     const_iv (SDL_MOUSEBUTTONUP),
607     const_iv (SDL_JOYAXISMOTION),
608     const_iv (SDL_JOYBALLMOTION),
609     const_iv (SDL_JOYHATMOTION),
610     const_iv (SDL_JOYBUTTONDOWN),
611     const_iv (SDL_JOYBUTTONUP),
612     const_iv (SDL_QUIT),
613     const_iv (SDL_SYSWMEVENT),
614     const_iv (SDL_EVENT_RESERVEDA),
615     const_iv (SDL_EVENT_RESERVEDB),
616     const_iv (SDL_VIDEORESIZE),
617     const_iv (SDL_VIDEOEXPOSE),
618     const_iv (SDL_USEREVENT),
619 root 1.167
620     const_iv (SDL_APPINPUTFOCUS),
621     const_iv (SDL_APPMOUSEFOCUS),
622     const_iv (SDL_APPACTIVE),
623    
624 root 1.275
625     const_iv (SDLK_UNKNOWN),
626     const_iv (SDLK_FIRST),
627     const_iv (SDLK_BACKSPACE),
628     const_iv (SDLK_TAB),
629     const_iv (SDLK_CLEAR),
630     const_iv (SDLK_RETURN),
631     const_iv (SDLK_PAUSE),
632     const_iv (SDLK_ESCAPE),
633     const_iv (SDLK_SPACE),
634     const_iv (SDLK_EXCLAIM),
635     const_iv (SDLK_QUOTEDBL),
636     const_iv (SDLK_HASH),
637     const_iv (SDLK_DOLLAR),
638     const_iv (SDLK_AMPERSAND),
639     const_iv (SDLK_QUOTE),
640     const_iv (SDLK_LEFTPAREN),
641     const_iv (SDLK_RIGHTPAREN),
642     const_iv (SDLK_ASTERISK),
643     const_iv (SDLK_PLUS),
644     const_iv (SDLK_COMMA),
645     const_iv (SDLK_MINUS),
646     const_iv (SDLK_PERIOD),
647     const_iv (SDLK_SLASH),
648     const_iv (SDLK_0),
649     const_iv (SDLK_1),
650     const_iv (SDLK_2),
651     const_iv (SDLK_3),
652     const_iv (SDLK_4),
653     const_iv (SDLK_5),
654     const_iv (SDLK_6),
655     const_iv (SDLK_7),
656     const_iv (SDLK_8),
657     const_iv (SDLK_9),
658     const_iv (SDLK_COLON),
659     const_iv (SDLK_SEMICOLON),
660     const_iv (SDLK_LESS),
661     const_iv (SDLK_EQUALS),
662     const_iv (SDLK_GREATER),
663     const_iv (SDLK_QUESTION),
664     const_iv (SDLK_AT),
665    
666     const_iv (SDLK_LEFTBRACKET),
667     const_iv (SDLK_BACKSLASH),
668     const_iv (SDLK_RIGHTBRACKET),
669     const_iv (SDLK_CARET),
670     const_iv (SDLK_UNDERSCORE),
671     const_iv (SDLK_BACKQUOTE),
672     const_iv (SDLK_DELETE),
673    
674 root 1.235 const_iv (SDLK_FIRST),
675     const_iv (SDLK_LAST),
676 root 1.51 const_iv (SDLK_KP0),
677     const_iv (SDLK_KP1),
678     const_iv (SDLK_KP2),
679     const_iv (SDLK_KP3),
680     const_iv (SDLK_KP4),
681     const_iv (SDLK_KP5),
682     const_iv (SDLK_KP6),
683     const_iv (SDLK_KP7),
684     const_iv (SDLK_KP8),
685     const_iv (SDLK_KP9),
686     const_iv (SDLK_KP_PERIOD),
687     const_iv (SDLK_KP_DIVIDE),
688     const_iv (SDLK_KP_MULTIPLY),
689     const_iv (SDLK_KP_MINUS),
690     const_iv (SDLK_KP_PLUS),
691     const_iv (SDLK_KP_ENTER),
692     const_iv (SDLK_KP_EQUALS),
693     const_iv (SDLK_UP),
694     const_iv (SDLK_DOWN),
695     const_iv (SDLK_RIGHT),
696     const_iv (SDLK_LEFT),
697     const_iv (SDLK_INSERT),
698     const_iv (SDLK_HOME),
699     const_iv (SDLK_END),
700     const_iv (SDLK_PAGEUP),
701     const_iv (SDLK_PAGEDOWN),
702     const_iv (SDLK_F1),
703     const_iv (SDLK_F2),
704     const_iv (SDLK_F3),
705     const_iv (SDLK_F4),
706     const_iv (SDLK_F5),
707     const_iv (SDLK_F6),
708     const_iv (SDLK_F7),
709     const_iv (SDLK_F8),
710     const_iv (SDLK_F9),
711     const_iv (SDLK_F10),
712     const_iv (SDLK_F11),
713     const_iv (SDLK_F12),
714     const_iv (SDLK_F13),
715     const_iv (SDLK_F14),
716     const_iv (SDLK_F15),
717     const_iv (SDLK_NUMLOCK),
718     const_iv (SDLK_CAPSLOCK),
719     const_iv (SDLK_SCROLLOCK),
720     const_iv (SDLK_RSHIFT),
721     const_iv (SDLK_LSHIFT),
722     const_iv (SDLK_RCTRL),
723     const_iv (SDLK_LCTRL),
724     const_iv (SDLK_RALT),
725     const_iv (SDLK_LALT),
726     const_iv (SDLK_RMETA),
727     const_iv (SDLK_LMETA),
728     const_iv (SDLK_LSUPER),
729     const_iv (SDLK_RSUPER),
730     const_iv (SDLK_MODE),
731     const_iv (SDLK_COMPOSE),
732     const_iv (SDLK_HELP),
733     const_iv (SDLK_PRINT),
734     const_iv (SDLK_SYSREQ),
735     const_iv (SDLK_BREAK),
736     const_iv (SDLK_MENU),
737     const_iv (SDLK_POWER),
738     const_iv (SDLK_EURO),
739     const_iv (SDLK_UNDO),
740 root 1.167
741 root 1.51 const_iv (KMOD_NONE),
742 root 1.167 const_iv (KMOD_SHIFT),
743 root 1.51 const_iv (KMOD_LSHIFT),
744     const_iv (KMOD_RSHIFT),
745 root 1.167 const_iv (KMOD_CTRL),
746 root 1.51 const_iv (KMOD_LCTRL),
747     const_iv (KMOD_RCTRL),
748 root 1.167 const_iv (KMOD_ALT),
749 root 1.51 const_iv (KMOD_LALT),
750     const_iv (KMOD_RALT),
751 root 1.167 const_iv (KMOD_META),
752 root 1.51 const_iv (KMOD_LMETA),
753     const_iv (KMOD_RMETA),
754     const_iv (KMOD_NUM),
755     const_iv (KMOD_CAPS),
756     const_iv (KMOD_MODE),
757 root 1.236
758 root 1.276 const_iv (KMOD_LRAM),
759    
760 root 1.236 const_iv (MIX_DEFAULT_FORMAT),
761 root 1.263
762     const_iv (SDL_INIT_TIMER),
763     const_iv (SDL_INIT_AUDIO),
764     const_iv (SDL_INIT_VIDEO),
765     const_iv (SDL_INIT_CDROM),
766     const_iv (SDL_INIT_JOYSTICK),
767     const_iv (SDL_INIT_EVERYTHING),
768     const_iv (SDL_INIT_NOPARACHUTE),
769     const_iv (SDL_INIT_EVENTTHREAD),
770 root 1.264
771     const_iv (SDL_GL_RED_SIZE),
772     const_iv (SDL_GL_GREEN_SIZE),
773     const_iv (SDL_GL_BLUE_SIZE),
774     const_iv (SDL_GL_ALPHA_SIZE),
775     const_iv (SDL_GL_DOUBLEBUFFER),
776     const_iv (SDL_GL_BUFFER_SIZE),
777     const_iv (SDL_GL_DEPTH_SIZE),
778     const_iv (SDL_GL_STENCIL_SIZE),
779     const_iv (SDL_GL_ACCUM_RED_SIZE),
780     const_iv (SDL_GL_ACCUM_GREEN_SIZE),
781     const_iv (SDL_GL_ACCUM_BLUE_SIZE),
782     const_iv (SDL_GL_ACCUM_ALPHA_SIZE),
783     const_iv (SDL_GL_STEREO),
784     const_iv (SDL_GL_MULTISAMPLEBUFFERS),
785     const_iv (SDL_GL_MULTISAMPLESAMPLES),
786     const_iv (SDL_GL_ACCELERATED_VISUAL),
787 root 1.269 const_iv (SDL_GL_SWAP_CONTROL),
788    
789     const_iv (FOW_DARKNESS)
790 root 1.51 # undef const_iv
791     };
792    
793     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
794     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
795 root 1.167
796     assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
797     assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
798 root 1.79 }
799 root 1.51
800 root 1.168 void
801     weaken (SV *rv)
802     PROTOTYPE: $
803     CODE:
804     sv_rvweaken (rv);
805    
806 root 1.129 int
807     in_destruct ()
808     CODE:
809     RETVAL = PL_main_cv == Nullcv;
810     OUTPUT:
811     RETVAL
812    
813 root 1.116 NV floor (NV x)
814    
815     NV ceil (NV x)
816    
817 root 1.235 IV minpot (UV n)
818    
819     IV popcount (UV n)
820    
821 root 1.79 void
822     pango_init ()
823     CODE:
824     {
825 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
826     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
827     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
828 root 1.257 /*pango_context_set_font_description (opengl_context, default_font);*/
829 root 1.254 #if PANGO_VERSION_CHECK (1, 15, 2)
830 root 1.249 pango_context_set_language (opengl_context, pango_language_from_string ("en"));
831 root 1.250 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/
832 root 1.249 #endif
833 root 1.5 }
834    
835 root 1.263 char *SDL_GetError ()
836    
837 root 1.272 void SDL_braino ()
838    
839 root 1.263 int SDL_Init (U32 flags)
840    
841     int SDL_InitSubSystem (U32 flags)
842 root 1.200
843 root 1.263 void SDL_QuitSubSystem (U32 flags)
844 root 1.51
845 root 1.263 void SDL_Quit ()
846 root 1.51
847 root 1.264 int SDL_GL_SetAttribute (int attr, int value)
848    
849     int SDL_GL_GetAttribute (int attr)
850     CODE:
851     if (SDL_GL_GetAttribute (attr, &RETVAL))
852     XSRETURN_UNDEF;
853     OUTPUT:
854     RETVAL
855    
856 root 1.51 void
857 root 1.200 SDL_ListModes (int rgb, int alpha)
858 root 1.51 PPCODE:
859     {
860     SDL_Rect **m;
861    
862 root 1.200 SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
863     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
864     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
865     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
866 root 1.51
867 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
868 root 1.200 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE , 0);
869 root 1.85
870 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE , 0);
871 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
872 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
873 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
874    
875     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
876 root 1.131 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
877 root 1.51
878     m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
879    
880     if (m && m != (SDL_Rect **)-1)
881     while (*m)
882     {
883 root 1.265 if ((*m)->w >= 400 && (*m)->h >= 300)
884     {
885     AV *av = newAV ();
886     av_push (av, newSViv ((*m)->w));
887     av_push (av, newSViv ((*m)->h));
888     av_push (av, newSViv (rgb));
889     av_push (av, newSViv (alpha));
890     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
891     }
892 root 1.51
893     ++m;
894     }
895     }
896    
897     int
898 root 1.200 SDL_SetVideoMode (int w, int h, int rgb, int alpha, int fullscreen)
899 root 1.51 CODE:
900 root 1.200 {
901     SDL_EnableUNICODE (1);
902     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
903    
904     SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
905     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
906     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
907     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
908    
909 root 1.51 RETVAL = !!SDL_SetVideoMode (
910     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
911     );
912 root 1.200
913 root 1.103 if (RETVAL)
914     {
915 root 1.188 av_clear (texture_av);
916    
917 root 1.237 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
918 root 1.200 #define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
919     #include "glfunc.h"
920     #undef GL_FUNC
921 root 1.103 }
922 root 1.200 }
923 root 1.51 OUTPUT:
924     RETVAL
925    
926 root 1.53 void
927 root 1.54 SDL_GL_SwapBuffers ()
928    
929 root 1.94 char *
930     SDL_GetKeyName (int sym)
931    
932 root 1.198 int
933     SDL_GetAppState ()
934    
935 root 1.256 int
936     SDL_GetModState ()
937    
938 root 1.54 void
939 root 1.197 poll_events ()
940 root 1.53 PPCODE:
941     {
942     SDL_Event ev;
943    
944 root 1.197 SDL_PumpEvents ();
945     while (SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0)
946 root 1.53 {
947     HV *hv = newHV ();
948     hv_store (hv, "type", 4, newSViv (ev.type), 0);
949 root 1.70
950 root 1.53 switch (ev.type)
951     {
952     case SDL_KEYDOWN:
953     case SDL_KEYUP:
954     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
955     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
956 root 1.276 hv_store (hv, "mod", 3, newSViv (mod_munge (ev.key.keysym.mod)), 0);
957     hv_store (hv, "cmod", 4, newSViv (mod_munge (SDL_GetModState ())), 0); /* current mode */
958 root 1.53 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
959     break;
960    
961     case SDL_ACTIVEEVENT:
962     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
963     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
964     break;
965    
966     case SDL_MOUSEMOTION:
967 root 1.196 {
968     int state = ev.motion.state;
969     int x = ev.motion.x;
970     int y = ev.motion.y;
971     int xrel = ev.motion.xrel;
972     int yrel = ev.motion.yrel;
973    
974     /* do simplistic event compression */
975     while (SDL_PeepEvents (&ev, 1, SDL_PEEKEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0
976     && state == ev.motion.state)
977     {
978     xrel += ev.motion.xrel;
979     yrel += ev.motion.yrel;
980     x = ev.motion.x;
981     y = ev.motion.y;
982     SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
983     }
984 root 1.93
985 root 1.276 hv_store (hv, "mod", 3, newSViv (mod_munge (SDL_GetModState ())), 0);
986 root 1.196 hv_store (hv, "state", 5, newSViv (state), 0);
987     hv_store (hv, "x", 1, newSViv (x), 0);
988     hv_store (hv, "y", 1, newSViv (y), 0);
989     hv_store (hv, "xrel", 4, newSViv (xrel), 0);
990     hv_store (hv, "yrel", 4, newSViv (yrel), 0);
991     }
992 root 1.53 break;
993    
994     case SDL_MOUSEBUTTONDOWN:
995     case SDL_MOUSEBUTTONUP:
996 root 1.253 hv_store (hv, "mod", 3, newSViv (SDL_GetModState () & MOD_MASK), 0);
997 root 1.93
998 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
999     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
1000     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
1001     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
1002 root 1.70 break;
1003 root 1.72
1004     case SDL_USEREVENT:
1005     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
1006     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
1007     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
1008     break;
1009 root 1.53 }
1010    
1011 root 1.242 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1012 root 1.53 }
1013     }
1014 root 1.52
1015     int
1016 root 1.236 Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1017 root 1.56 POSTCALL:
1018     Mix_HookMusicFinished (music_finished);
1019 root 1.71 Mix_ChannelFinished (channel_finished);
1020 root 1.52
1021     void
1022 root 1.236 Mix_QuerySpec ()
1023     PPCODE:
1024     {
1025     int freq, channels;
1026     Uint16 format;
1027    
1028     if (Mix_QuerySpec (&freq, &format, &channels))
1029     {
1030     EXTEND (SP, 3);
1031     PUSHs (sv_2mortal (newSViv (freq)));
1032     PUSHs (sv_2mortal (newSViv (format)));
1033     PUSHs (sv_2mortal (newSViv (channels)));
1034     }
1035     }
1036    
1037     void
1038 root 1.52 Mix_CloseAudio ()
1039    
1040     int
1041     Mix_AllocateChannels (int numchans = -1)
1042    
1043 root 1.214 const char *
1044     Mix_GetError ()
1045    
1046 root 1.10 void
1047     lowdelay (int fd, int val = 1)
1048     CODE:
1049 root 1.179 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
1050 root 1.10
1051 root 1.5 void
1052 root 1.157 win32_proxy_info ()
1053     PPCODE:
1054     {
1055     #ifdef _WIN32
1056     char buffer[2048];
1057     DWORD buflen;
1058    
1059     EXTEND (SP, 3);
1060    
1061     buflen = sizeof (buffer);
1062     if (InternetQueryOption (0, INTERNET_OPTION_PROXY, (void *)buffer, &buflen))
1063     if (((INTERNET_PROXY_INFO *)buffer)->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
1064     {
1065     PUSHs (newSVpv (((INTERNET_PROXY_INFO *)buffer)->lpszProxy, 0));
1066    
1067     buflen = sizeof (buffer);
1068     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_USERNAME, (void *)buffer, &buflen))
1069     {
1070     PUSHs (newSVpv (buffer, 0));
1071    
1072     buflen = sizeof (buffer);
1073     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_PASSWORD, (void *)buffer, &buflen))
1074     PUSHs (newSVpv (buffer, 0));
1075     }
1076     }
1077     #endif
1078     }
1079    
1080 root 1.257 int
1081 root 1.13 add_font (char *file)
1082     CODE:
1083 root 1.257 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1084     OUTPUT:
1085     RETVAL
1086 root 1.13
1087     void
1088 root 1.23 load_image_inline (SV *image_)
1089     ALIAS:
1090     load_image_file = 1
1091     PPCODE:
1092     {
1093     STRLEN image_len;
1094     char *image = (char *)SvPVbyte (image_, image_len);
1095     SDL_Surface *surface, *surface2;
1096     SDL_PixelFormat fmt;
1097     SDL_RWops *rw = ix
1098 root 1.212 ? SDL_RWFromFile (image, "rb")
1099 root 1.23 : SDL_RWFromConstMem (image, image_len);
1100    
1101     if (!rw)
1102 root 1.41 croak ("load_image: %s", SDL_GetError ());
1103 root 1.23
1104     surface = IMG_Load_RW (rw, 1);
1105     if (!surface)
1106 root 1.41 croak ("load_image: %s", SDL_GetError ());
1107 root 1.23
1108     fmt.palette = NULL;
1109     fmt.BitsPerPixel = 32;
1110     fmt.BytesPerPixel = 4;
1111 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1112 root 1.23 fmt.Rmask = 0x000000ff;
1113     fmt.Gmask = 0x0000ff00;
1114     fmt.Bmask = 0x00ff0000;
1115     fmt.Amask = 0xff000000;
1116 root 1.49 #else
1117     fmt.Rmask = 0xff000000;
1118     fmt.Gmask = 0x00ff0000;
1119     fmt.Bmask = 0x0000ff00;
1120     fmt.Amask = 0x000000ff;
1121     #endif
1122 root 1.23 fmt.Rloss = 0;
1123     fmt.Gloss = 0;
1124     fmt.Bloss = 0;
1125     fmt.Aloss = 0;
1126     fmt.Rshift = 0;
1127     fmt.Gshift = 8;
1128     fmt.Bshift = 16;
1129     fmt.Ashift = 24;
1130     fmt.colorkey = 0;
1131     fmt.alpha = 0;
1132    
1133     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
1134    
1135 root 1.39 assert (surface2->pitch == surface2->w * 4);
1136    
1137 root 1.129 SDL_LockSurface (surface2);
1138     EXTEND (SP, 6);
1139 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
1140     PUSHs (sv_2mortal (newSViv (surface2->h)));
1141     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
1142 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1143 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1144 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1145 root 1.129 SDL_UnlockSurface (surface2);
1146 root 1.23
1147     SDL_FreeSurface (surface);
1148     SDL_FreeSurface (surface2);
1149     }
1150    
1151 root 1.25 void
1152 root 1.39 average (int x, int y, uint32_t *data)
1153     PPCODE:
1154     {
1155     uint32_t r = 0, g = 0, b = 0, a = 0;
1156    
1157     x = y = x * y;
1158    
1159     while (x--)
1160     {
1161     uint32_t p = *data++;
1162    
1163     r += (p ) & 255;
1164     g += (p >> 8) & 255;
1165     b += (p >> 16) & 255;
1166     a += (p >> 24) & 255;
1167     }
1168    
1169     EXTEND (SP, 4);
1170 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
1171     PUSHs (sv_2mortal (newSViv (g / y)));
1172     PUSHs (sv_2mortal (newSViv (b / y)));
1173     PUSHs (sv_2mortal (newSViv (a / y)));
1174 root 1.39 }
1175    
1176     void
1177 root 1.66 error (char *message)
1178     CODE:
1179 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
1180 root 1.66 #ifdef _WIN32
1181 root 1.240 MessageBox (0, message, "Deliantra Client Error", MB_OK | MB_ICONERROR);
1182 root 1.66 #endif
1183    
1184     void
1185 root 1.25 fatal (char *message)
1186     CODE:
1187 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
1188 root 1.50 #ifdef _WIN32
1189 root 1.240 MessageBox (0, message, "Deliantra Client Fatal Error", MB_OK | MB_ICONERROR);
1190 root 1.25 #endif
1191 root 1.112 _exit (1);
1192 root 1.111
1193     void
1194 root 1.158 _exit (int retval = 0)
1195 root 1.111 CODE:
1196 root 1.161 #ifdef WIN32
1197     ExitThread (retval); // unclean, please beam me up
1198     #else
1199 root 1.112 _exit (retval);
1200 root 1.161 #endif
1201 root 1.25
1202 root 1.193 void
1203     debug ()
1204     CODE:
1205     {
1206     #if DEBUG
1207     VALGRIND_DO_LEAK_CHECK;
1208     #endif
1209     }
1210    
1211 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::Font
1212 root 1.61
1213 root 1.205 PROTOTYPES: DISABLE
1214    
1215 root 1.242 DC::Font
1216 root 1.70 new_from_file (SV *class, char *path, int id = 0)
1217 root 1.61 CODE:
1218     {
1219     int count;
1220 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1221 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1222     FcPatternDestroy (pattern);
1223     }
1224     OUTPUT:
1225     RETVAL
1226    
1227     void
1228 root 1.242 DESTROY (DC::Font self)
1229 root 1.61 CODE:
1230     pango_font_description_free (self);
1231    
1232     void
1233 root 1.242 make_default (DC::Font self)
1234 root 1.205 PROTOTYPE: $
1235 root 1.61 CODE:
1236     default_font = self;
1237    
1238 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::Layout
1239 root 1.14
1240 root 1.205 PROTOTYPES: DISABLE
1241    
1242 root 1.124 void
1243 root 1.239 glyph_cache_backup ()
1244 root 1.205 PROTOTYPE:
1245 root 1.124 CODE:
1246 root 1.239 tc_backup ();
1247    
1248     void
1249     glyph_cache_restore ()
1250     PROTOTYPE:
1251     CODE:
1252     tc_restore ();
1253 root 1.124
1254 root 1.242 DC::Layout
1255 root 1.128 new (SV *class)
1256 root 1.14 CODE:
1257     New (0, RETVAL, 1, struct cf_layout);
1258 root 1.76
1259 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
1260 root 1.76 RETVAL->r = 1.;
1261     RETVAL->g = 1.;
1262     RETVAL->b = 1.;
1263     RETVAL->a = 1.;
1264     RETVAL->base_height = MIN_FONT_HEIGHT;
1265     RETVAL->font = 0;
1266 root 1.225 RETVAL->rc = rc_alloc ();
1267 root 1.76
1268 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1269 root 1.76 layout_update_font (RETVAL);
1270 root 1.14 OUTPUT:
1271     RETVAL
1272    
1273     void
1274 root 1.242 DESTROY (DC::Layout self)
1275 root 1.14 CODE:
1276     g_object_unref (self->pl);
1277 root 1.225 rc_free (self->rc);
1278 root 1.14 Safefree (self);
1279 root 1.13
1280 root 1.8 void
1281 root 1.242 set_text (DC::Layout self, SV *text_)
1282 root 1.35 CODE:
1283     {
1284     STRLEN textlen;
1285     char *text = SvPVutf8 (text_, textlen);
1286    
1287     pango_layout_set_text (self->pl, text, textlen);
1288     }
1289    
1290     void
1291 root 1.242 set_markup (DC::Layout self, SV *text_)
1292 root 1.14 CODE:
1293 root 1.5 {
1294     STRLEN textlen;
1295     char *text = SvPVutf8 (text_, textlen);
1296 root 1.14
1297     pango_layout_set_markup (self->pl, text, textlen);
1298     }
1299    
1300 root 1.121 void
1301 root 1.242 set_shapes (DC::Layout self, ...)
1302 root 1.121 CODE:
1303     {
1304     PangoAttrList *attrs = 0;
1305     const char *text = pango_layout_get_text (self->pl);
1306     const char *pos = text;
1307 root 1.122 int arg = 4;
1308 root 1.121
1309     while (arg < items && (pos = strstr (pos, OBJ_STR)))
1310     {
1311 root 1.122 PangoRectangle inkrect, rect;
1312 root 1.121 PangoAttribute *attr;
1313    
1314 root 1.122 int x = SvIV (ST (arg - 3));
1315     int y = SvIV (ST (arg - 2));
1316 root 1.121 int w = SvIV (ST (arg - 1));
1317 root 1.122 int h = SvIV (ST (arg ));
1318 root 1.121
1319 root 1.122 inkrect.x = 0;
1320     inkrect.y = 0;
1321     inkrect.width = 0;
1322     inkrect.height = 0;
1323    
1324     rect.x = x * PANGO_SCALE;
1325     rect.y = y * PANGO_SCALE;
1326     rect.width = w * PANGO_SCALE;
1327 root 1.121 rect.height = h * PANGO_SCALE;
1328    
1329     if (!attrs)
1330     attrs = pango_layout_get_attributes (self->pl);
1331    
1332 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
1333 root 1.121 attr->start_index = pos - text;
1334     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
1335     pango_attr_list_insert (attrs, attr);
1336    
1337 root 1.122 arg += 4;
1338 root 1.121 pos += sizeof (OBJ_STR) - 1;
1339     }
1340    
1341     if (attrs)
1342     pango_layout_set_attributes (self->pl, attrs);
1343     }
1344    
1345     void
1346 root 1.242 get_shapes (DC::Layout self)
1347 root 1.121 PPCODE:
1348     {
1349     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
1350    
1351     do
1352     {
1353 root 1.249 PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter);
1354 root 1.121
1355     if (run && shape_attr_p (run))
1356     {
1357     PangoRectangle extents;
1358     pango_layout_iter_get_run_extents (iter, 0, &extents);
1359    
1360 root 1.129 EXTEND (SP, 2);
1361 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
1362     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
1363     }
1364     }
1365     while (pango_layout_iter_next_run (iter));
1366    
1367     pango_layout_iter_free (iter);
1368     }
1369    
1370     int
1371 root 1.242 has_wrapped (DC::Layout self)
1372 root 1.121 CODE:
1373     {
1374     int lines = 1;
1375     const char *text = pango_layout_get_text (self->pl);
1376    
1377     while (*text)
1378     lines += *text++ == '\n';
1379    
1380     RETVAL = lines < pango_layout_get_line_count (self->pl);
1381     }
1382     OUTPUT:
1383     RETVAL
1384    
1385 root 1.46 SV *
1386 root 1.242 get_text (DC::Layout self)
1387 root 1.46 CODE:
1388 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
1389 root 1.107 sv_utf8_decode (RETVAL);
1390 root 1.46 OUTPUT:
1391     RETVAL
1392    
1393 root 1.14 void
1394 root 1.242 set_foreground (DC::Layout self, float r, float g, float b, float a = 1.)
1395 root 1.76 CODE:
1396     self->r = r;
1397     self->g = g;
1398     self->b = b;
1399     self->a = a;
1400    
1401     void
1402 root 1.242 set_font (DC::Layout self, DC::Font font = 0)
1403 root 1.61 CODE:
1404     if (self->font != font)
1405     {
1406     self->font = font;
1407     layout_update_font (self);
1408     }
1409    
1410     void
1411 root 1.242 set_height (DC::Layout self, int base_height)
1412 root 1.16 CODE:
1413 root 1.61 if (self->base_height != base_height)
1414     {
1415     self->base_height = base_height;
1416     layout_update_font (self);
1417     }
1418 root 1.16
1419     void
1420 root 1.242 set_width (DC::Layout self, int max_width = -1)
1421 root 1.14 CODE:
1422     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
1423    
1424     void
1425 root 1.242 set_indent (DC::Layout self, int indent)
1426 root 1.84 CODE:
1427     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
1428    
1429     void
1430 root 1.242 set_spacing (DC::Layout self, int spacing)
1431 root 1.84 CODE:
1432     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
1433    
1434     void
1435 root 1.242 set_ellipsise (DC::Layout self, int ellipsise)
1436 root 1.84 CODE:
1437     pango_layout_set_ellipsize (self->pl,
1438     ellipsise == 1 ? PANGO_ELLIPSIZE_START
1439     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
1440     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
1441     : PANGO_ELLIPSIZE_NONE
1442     );
1443    
1444     void
1445 root 1.242 set_single_paragraph_mode (DC::Layout self, int spm)
1446 root 1.84 CODE:
1447     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
1448    
1449     void
1450 root 1.242 size (DC::Layout self)
1451 root 1.14 PPCODE:
1452     {
1453     int w, h;
1454    
1455     layout_get_pixel_size (self, &w, &h);
1456    
1457     EXTEND (SP, 2);
1458     PUSHs (sv_2mortal (newSViv (w)));
1459     PUSHs (sv_2mortal (newSViv (h)));
1460     }
1461    
1462 root 1.17 int
1463 root 1.242 descent (DC::Layout self)
1464 root 1.122 CODE:
1465     {
1466     PangoRectangle rect;
1467 root 1.249 PangoLayoutLine *line = pango_layout_get_line_readonly (self->pl, 0);
1468 root 1.122 pango_layout_line_get_pixel_extents (line, 0, &rect);
1469     RETVAL = PANGO_DESCENT (rect);
1470     }
1471     OUTPUT:
1472     RETVAL
1473    
1474     int
1475 root 1.242 xy_to_index (DC::Layout self, int x, int y)
1476 root 1.17 CODE:
1477     {
1478     int index, trailing;
1479     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1480 root 1.165 RETVAL = index + trailing;
1481 root 1.17 }
1482     OUTPUT:
1483     RETVAL
1484    
1485     void
1486 root 1.242 cursor_pos (DC::Layout self, int index)
1487 root 1.17 PPCODE:
1488     {
1489 root 1.251 PangoRectangle pos;
1490 root 1.252 pango_layout_get_cursor_pos (self->pl, index, &pos, 0);
1491 root 1.30
1492 root 1.17 EXTEND (SP, 3);
1493 root 1.251 PUSHs (sv_2mortal (newSViv (pos.x / PANGO_SCALE)));
1494     PUSHs (sv_2mortal (newSViv (pos.y / PANGO_SCALE)));
1495     PUSHs (sv_2mortal (newSViv (pos.height / PANGO_SCALE)));
1496 root 1.17 }
1497    
1498 root 1.14 void
1499 root 1.242 index_to_line_x (DC::Layout self, int index, int trailing = 0)
1500 root 1.165 PPCODE:
1501     {
1502     int line, x;
1503    
1504     pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x);
1505 root 1.254 #if !PANGO_VERSION_CHECK (1, 17, 3)
1506 root 1.165 /* pango bug: line is between 1..numlines, not 0..numlines-1 */
1507 root 1.245 --line;
1508     #endif
1509 root 1.165 EXTEND (SP, 2);
1510 root 1.245 PUSHs (sv_2mortal (newSViv (line)));
1511 root 1.165 PUSHs (sv_2mortal (newSViv (x / PANGO_SCALE)));
1512     }
1513    
1514     void
1515 root 1.242 line_x_to_index (DC::Layout self, int line, int x)
1516 root 1.165 PPCODE:
1517     {
1518     PangoLayoutLine *lp;
1519     int index, trailing;
1520    
1521     if (line < 0)
1522     XSRETURN_EMPTY;
1523    
1524 root 1.249 if (!(lp = pango_layout_get_line_readonly (self->pl, line)))
1525 root 1.165 XSRETURN_EMPTY; /* do better */
1526    
1527 root 1.166 pango_layout_line_x_to_index (lp, x * PANGO_SCALE, &index, &trailing);
1528 root 1.165
1529     EXTEND (SP, 2);
1530     if (GIMME_V == G_SCALAR)
1531     PUSHs (sv_2mortal (newSViv (index + trailing)));
1532     else
1533     {
1534     PUSHs (sv_2mortal (newSViv (index)));
1535     PUSHs (sv_2mortal (newSViv (trailing)));
1536     }
1537     }
1538    
1539     void
1540 root 1.242 render (DC::Layout self, float x, float y, int flags = 0)
1541 root 1.225 CODE:
1542     rc_clear (self->rc);
1543 root 1.124 pango_opengl_render_layout_subpixel (
1544     self->pl,
1545 root 1.225 self->rc,
1546 root 1.124 x * PANGO_SCALE, y * PANGO_SCALE,
1547 root 1.135 self->r, self->g, self->b, self->a,
1548     flags
1549 root 1.124 );
1550 root 1.225 // we assume that context_change actually clears/frees stuff
1551     // and does not do any recomputation...
1552     pango_layout_context_changed (self->pl);
1553    
1554     void
1555 root 1.242 draw (DC::Layout self)
1556 root 1.225 CODE:
1557     {
1558     glEnable (GL_TEXTURE_2D);
1559     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1560     glEnable (GL_BLEND);
1561     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1562     GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1563     glEnable (GL_ALPHA_TEST);
1564     glAlphaFunc (GL_GREATER, 7.f / 255.f);
1565    
1566     rc_draw (self->rc);
1567    
1568     glDisable (GL_ALPHA_TEST);
1569     glDisable (GL_BLEND);
1570     glDisable (GL_TEXTURE_2D);
1571     }
1572 root 1.11
1573 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::Texture
1574 root 1.11
1575 root 1.205 PROTOTYPES: ENABLE
1576    
1577 root 1.11 void
1578 root 1.203 pad (SV *data_, int ow, int oh, int nw, int nh)
1579 root 1.113 CODE:
1580     {
1581 root 1.203 if ((nw != ow || nh != oh) && SvOK (data_))
1582 root 1.113 {
1583 root 1.203 STRLEN datalen;
1584     char *data = SvPVbyte (data_, datalen);
1585     int bpp = datalen / (ow * oh);
1586     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1587    
1588     SvPOK_only (result_);
1589     SvCUR_set (result_, nw * nh * bpp);
1590    
1591     memset (SvPVX (result_), 0, nw * nh * bpp);
1592     while (oh--)
1593     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1594 root 1.113
1595 root 1.203 sv_setsv (data_, result_);
1596 root 1.113 }
1597     }
1598    
1599     void
1600 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1601 root 1.12 PROTOTYPE: $$$;$$
1602 root 1.76 ALIAS:
1603     draw_quad_alpha = 1
1604     draw_quad_alpha_premultiplied = 2
1605 root 1.11 CODE:
1606     {
1607 root 1.12 HV *hv = (HV *)SvRV (self);
1608 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1609     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1610 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1611    
1612 root 1.219 if (name <= 0)
1613     XSRETURN_EMPTY;
1614    
1615 root 1.12 if (items < 5)
1616     {
1617 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1618     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1619 root 1.12 }
1620    
1621 root 1.76 if (ix)
1622     {
1623     glEnable (GL_BLEND);
1624 root 1.103
1625     if (ix == 2)
1626     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1627     else
1628     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1629 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1630 root 1.103
1631 root 1.86 glEnable (GL_ALPHA_TEST);
1632     glAlphaFunc (GL_GREATER, 0.01f);
1633 root 1.76 }
1634    
1635 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1636 root 1.76
1637 root 1.12 glBegin (GL_QUADS);
1638 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1639     glTexCoord2f (0, t); glVertex2f (x , y + h);
1640     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1641     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1642 root 1.12 glEnd ();
1643 root 1.76
1644     if (ix)
1645 root 1.86 {
1646     glDisable (GL_ALPHA_TEST);
1647     glDisable (GL_BLEND);
1648     }
1649 root 1.11 }
1650 root 1.28
1651 root 1.199 IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1652     CODE:
1653     {
1654     GLint width;
1655     glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1656     glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
1657     RETVAL = width > 0;
1658     }
1659     OUTPUT:
1660     RETVAL
1661    
1662 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::Map
1663 root 1.28
1664 root 1.205 PROTOTYPES: DISABLE
1665    
1666 root 1.242 DC::Map
1667 root 1.164 new (SV *class)
1668 root 1.28 CODE:
1669     New (0, RETVAL, 1, struct map);
1670 root 1.42 RETVAL->x = 0;
1671     RETVAL->y = 0;
1672 root 1.164 RETVAL->w = 0;
1673     RETVAL->h = 0;
1674 root 1.42 RETVAL->ox = 0;
1675     RETVAL->oy = 0;
1676 root 1.174 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1677     RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1678 root 1.28 RETVAL->rows = 0;
1679     RETVAL->row = 0;
1680     OUTPUT:
1681     RETVAL
1682    
1683     void
1684 root 1.242 DESTROY (DC::Map self)
1685 root 1.28 CODE:
1686     {
1687 root 1.30 map_clear (self);
1688 root 1.174 Safefree (self->face2tile);
1689 root 1.111 Safefree (self->tex);
1690 root 1.29 Safefree (self);
1691     }
1692    
1693     void
1694 root 1.242 resize (DC::Map self, int map_width, int map_height)
1695 root 1.164 CODE:
1696     self->w = map_width;
1697     self->h = map_height;
1698    
1699     void
1700 root 1.242 clear (DC::Map self)
1701 root 1.30 CODE:
1702     map_clear (self);
1703    
1704     void
1705 root 1.242 set_tileid (DC::Map self, int face, int tile)
1706 root 1.29 CODE:
1707     {
1708 root 1.174 need_facenum (self, face); self->face2tile [face] = tile;
1709     need_texid (self, tile);
1710 root 1.42 }
1711    
1712     void
1713 root 1.242 set_smooth (DC::Map self, int face, int smooth, int level)
1714 root 1.176 CODE:
1715     {
1716     tileid texid;
1717     maptex *tex;
1718    
1719     if (face < 0 || face >= self->faces)
1720     return;
1721    
1722     if (smooth < 0 || smooth >= self->faces)
1723     return;
1724    
1725     texid = self->face2tile [face];
1726    
1727     if (!texid)
1728     return;
1729    
1730     tex = self->tex + texid;
1731     tex->smoothtile = self->face2tile [smooth];
1732     tex->smoothlevel = level;
1733     }
1734    
1735     void
1736 root 1.242 set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1737 root 1.42 CODE:
1738     {
1739 root 1.174 need_texid (self, texid);
1740 root 1.42
1741 root 1.48 {
1742     maptex *tex = self->tex + texid;
1743 root 1.39
1744 root 1.48 tex->name = name;
1745     tex->w = w;
1746     tex->h = h;
1747     tex->s = s;
1748     tex->t = t;
1749     tex->r = r;
1750     tex->g = g;
1751     tex->b = b;
1752     tex->a = a;
1753     }
1754 root 1.95
1755     // somewhat hackish, but for textures that require it, it really
1756     // improves the look, and most others don't suffer.
1757     glBindTexture (GL_TEXTURE_2D, name);
1758 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1759     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1760     // use uglier nearest interpolation because linear suffers
1761     // from transparent color bleeding and ugly wrapping effects.
1762     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1763 root 1.29 }
1764    
1765 root 1.42 int
1766 root 1.242 ox (DC::Map self)
1767 root 1.42 ALIAS:
1768     oy = 1
1769 root 1.101 x = 2
1770     y = 3
1771 root 1.102 w = 4
1772     h = 5
1773 root 1.42 CODE:
1774     switch (ix)
1775     {
1776     case 0: RETVAL = self->ox; break;
1777     case 1: RETVAL = self->oy; break;
1778 root 1.101 case 2: RETVAL = self->x; break;
1779     case 3: RETVAL = self->y; break;
1780 root 1.102 case 4: RETVAL = self->w; break;
1781     case 5: RETVAL = self->h; break;
1782 root 1.42 }
1783     OUTPUT:
1784     RETVAL
1785    
1786 root 1.29 void
1787 root 1.242 scroll (DC::Map self, int dx, int dy)
1788 root 1.43 CODE:
1789     {
1790 root 1.44 if (dx > 0)
1791 root 1.154 map_blank (self, self->x, self->y, dx, self->h);
1792 root 1.44 else if (dx < 0)
1793 root 1.187 map_blank (self, self->x + self->w + dx, self->y, -dx, self->h);
1794 root 1.44
1795     if (dy > 0)
1796 root 1.154 map_blank (self, self->x, self->y, self->w, dy);
1797 root 1.44 else if (dy < 0)
1798 root 1.187 map_blank (self, self->x, self->y + self->h + dy, self->w, -dy);
1799 root 1.43
1800 root 1.44 self->ox += dx; self->x += dx;
1801     self->oy += dy; self->y += dy;
1802 root 1.43
1803     while (self->y < 0)
1804     {
1805     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1806    
1807     self->rows += MAP_EXTEND_Y;
1808     self->y += MAP_EXTEND_Y;
1809     }
1810 root 1.44 }
1811 root 1.43
1812 root 1.221 SV *
1813 root 1.242 map1a_update (DC::Map self, SV *data_, int extmap)
1814 root 1.44 CODE:
1815     {
1816 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1817     uint8_t *data_end = (uint8_t *)SvEND (data_);
1818 root 1.48 mapcell *cell;
1819 root 1.221 int x, y, z, flags;
1820     AV *missing = newAV ();
1821     RETVAL = newRV_noinc ((SV *)missing);
1822 root 1.43
1823 root 1.150 while (data < data_end - 1)
1824 root 1.29 {
1825 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1826 root 1.30
1827 root 1.120 x = self->x + ((flags >> 10) & 63);
1828     y = self->y + ((flags >> 4) & 63);
1829 root 1.29
1830 root 1.48 cell = map_get_cell (self, x, y);
1831 root 1.29
1832     if (flags & 15)
1833     {
1834 root 1.142 if (!cell->darkness)
1835 root 1.29 {
1836 root 1.154 memset (cell, 0, sizeof (*cell));
1837 root 1.142 cell->darkness = 256;
1838 root 1.29 }
1839 root 1.45
1840 root 1.142 //TODO: don't trust server data to be in-range(!)
1841    
1842 root 1.141 if (flags & 8)
1843     {
1844     if (extmap)
1845     {
1846     uint8_t ext, cmd;
1847    
1848     do
1849     {
1850     ext = *data++;
1851 root 1.261 cmd = ext & 0x7f;
1852 root 1.141
1853 root 1.147 if (cmd < 4)
1854 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1855 root 1.147 else if (cmd == 5) // health
1856     {
1857     cell->stat_width = 1;
1858     cell->stat_hp = *data++;
1859     }
1860     else if (cmd == 6) // monster width
1861     cell->stat_width = *data++ + 1;
1862 root 1.169 else if (cmd == 0x47)
1863 root 1.153 {
1864 root 1.261 if (*data == 1) cell->player = data [1];
1865     else if (*data == 2) cell->player = data [2] + (data [1] << 8);
1866     else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
1867     else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1868 root 1.153
1869     data += *data + 1;
1870     }
1871     else if (cmd == 8) // cell flags
1872     cell->flags = *data++;
1873 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1874     data += *data + 1;
1875 root 1.147 else
1876     data++;
1877 root 1.141 }
1878 root 1.147 while (ext & 0x80);
1879 root 1.141 }
1880     else
1881 root 1.142 cell->darkness = *data++ + 1;
1882 root 1.141 }
1883 root 1.29
1884 root 1.221 for (z = 0; z <= 2; ++z)
1885     if (flags & (4 >> z))
1886     {
1887     faceid face = (data [0] << 8) + data [1]; data += 2;
1888     need_facenum (self, face);
1889     cell->tile [z] = self->face2tile [face];
1890 root 1.29
1891 root 1.221 if (cell->tile [z])
1892     {
1893     maptex *tex = self->tex + cell->tile [z];
1894     if (!tex->name)
1895     av_push (missing, newSViv (cell->tile [z]));
1896 root 1.29
1897 root 1.221 if (tex->smoothtile)
1898     {
1899     maptex *smooth = self->tex + tex->smoothtile;
1900     if (!smooth->name)
1901     av_push (missing, newSViv (tex->smoothtile));
1902     }
1903     }
1904     }
1905 root 1.29 }
1906     else
1907 root 1.267 CELL_CLEAR (cell);
1908 root 1.29 }
1909 root 1.28 }
1910 root 1.221 OUTPUT:
1911     RETVAL
1912 root 1.28
1913 root 1.40 SV *
1914 root 1.242 mapmap (DC::Map self, int x0, int y0, int w, int h)
1915 root 1.40 CODE:
1916     {
1917 root 1.55 int x1, x;
1918     int y1, y;
1919 root 1.40 int z;
1920     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1921     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1922    
1923     SvPOK_only (map_sv);
1924     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1925    
1926 root 1.55 x0 += self->x; x1 = x0 + w;
1927     y0 += self->y; y1 = y0 + h;
1928 root 1.40
1929     for (y = y0; y < y1; y++)
1930     {
1931     maprow *row = 0 <= y && y < self->rows
1932     ? self->row + y
1933     : 0;
1934    
1935     for (x = x0; x < x1; x++)
1936     {
1937     int r = 32, g = 32, b = 32, a = 192;
1938    
1939     if (row && row->c0 <= x && x < row->c1)
1940     {
1941     mapcell *cell = row->col + (x - row->c0);
1942    
1943     for (z = 0; z <= 0; z++)
1944     {
1945 root 1.174 maptex tex = self->tex [cell->tile [z]];
1946     int a0 = 255 - tex.a;
1947     int a1 = tex.a;
1948    
1949     r = (r * a0 + tex.r * a1) / 255;
1950     g = (g * a0 + tex.g * a1) / 255;
1951     b = (b * a0 + tex.b * a1) / 255;
1952     a = (a * a0 + tex.a * a1) / 255;
1953 root 1.40 }
1954     }
1955    
1956     *map++ = (r )
1957     | (g << 8)
1958     | (b << 16)
1959     | (a << 24);
1960     }
1961     }
1962    
1963     RETVAL = map_sv;
1964     }
1965     OUTPUT:
1966     RETVAL
1967    
1968 root 1.221 void
1969 root 1.266 draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
1970 root 1.116 CODE:
1971 root 1.30 {
1972 root 1.223 int x, y, z;
1973    
1974 root 1.176 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1975     uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1976 root 1.226 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k)
1977 root 1.176 smooth_key skey;
1978 root 1.261 int pl_x, pl_y;
1979     maptex pl_tex;
1980 root 1.223 rc_t *rc = rc_alloc ();
1981     rc_key_t key;
1982     rc_array_t *arr;
1983 root 1.48
1984 root 1.262 pl_tex.name = 0;
1985    
1986 root 1.176 // thats current max. sorry.
1987     if (sw > 255) sw = 255;
1988     if (sh > 255) sh = 255;
1989    
1990     // clear key, in case of extra padding
1991     memset (&skey, 0, sizeof (skey));
1992    
1993 root 1.223 memset (&key, 0, sizeof (key));
1994     key.r = 255;
1995     key.g = 255;
1996     key.b = 255;
1997     key.a = 255;
1998     key.mode = GL_QUADS;
1999     key.format = GL_T2F_V3F;
2000     key.texname = -1;
2001 root 1.30
2002 root 1.164 mx += self->x;
2003     my += self->y;
2004    
2005 root 1.176 // first pass: determine smooth_max
2006     // rather ugly, if you ask me
2007     // could also be stored inside mapcell and updated on change
2008     memset (smooth_max, 0, sizeof (smooth_max));
2009    
2010     for (y = 0; y < sh; y++)
2011     if (0 <= y + my && y + my < self->rows)
2012     {
2013     maprow *row = self->row + (y + my);
2014    
2015     for (x = 0; x < sw; x++)
2016     if (row->c0 <= x + mx && x + mx < row->c1)
2017     {
2018     mapcell *cell = row->col + (x + mx - row->c0);
2019    
2020 root 1.177 smooth_max[x + 1][y + 1] =
2021     MAX (self->tex [cell->tile [0]].smoothlevel,
2022     MAX (self->tex [cell->tile [1]].smoothlevel,
2023     self->tex [cell->tile [2]].smoothlevel));
2024 root 1.176 }
2025     }
2026    
2027 root 1.223 glEnable (GL_BLEND);
2028     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2029     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2030    
2031 root 1.176 for (z = 0; z <= 2; z++)
2032     {
2033 root 1.186 memset (smooth_level, 0, sizeof (smooth_level));
2034    
2035 root 1.176 for (y = 0; y < sh; y++)
2036     if (0 <= y + my && y + my < self->rows)
2037     {
2038     maprow *row = self->row + (y + my);
2039    
2040     for (x = 0; x < sw; x++)
2041     if (row->c0 <= x + mx && x + mx < row->c1)
2042     {
2043     mapcell *cell = row->col + (x + mx - row->c0);
2044     tileid tile = cell->tile [z];
2045    
2046     if (tile)
2047     {
2048     maptex tex = self->tex [tile];
2049 root 1.261 int px = (x + 1) * T - tex.w;
2050     int py = (y + 1) * T - tex.h;
2051 root 1.176
2052 root 1.223 if (key.texname != tex.name)
2053 root 1.176 {
2054     if (!tex.name)
2055 root 1.221 tex = self->tex [2]; /* missing, replace by noface */
2056 root 1.176
2057 root 1.223 key.texname = tex.name;
2058     arr = rc_array (rc, &key);
2059 root 1.176 }
2060    
2061 root 1.261 if (expect_false (cell->player == player) && expect_false (z == 2))
2062     {
2063     pl_x = px;
2064     pl_y = py;
2065     pl_tex = tex;
2066     continue;
2067     }
2068 root 1.219
2069 root 1.223 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2070     rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
2071     rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
2072     rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
2073 root 1.176
2074 root 1.261 if (expect_false (cell->flags) && expect_false (z == 2))
2075 root 1.176 {
2076 root 1.223 // overlays such as the speech bubble, probably more to come
2077 root 1.176 if (cell->flags & 1)
2078     {
2079     maptex tex = self->tex [1];
2080     int px = x * T + T * 2 / 32;
2081     int py = y * T - T * 6 / 32;
2082    
2083 root 1.223 if (tex.name)
2084     {
2085     if (key.texname != tex.name)
2086     {
2087     key.texname = tex.name;
2088     arr = rc_array (rc, &key);
2089     }
2090    
2091     rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2092     rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
2093     rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
2094     rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
2095     }
2096 root 1.176 }
2097     }
2098    
2099     // update smooth hash
2100     if (tex.smoothtile)
2101     {
2102     skey.tile = tex.smoothtile;
2103     skey.level = tex.smoothlevel;
2104    
2105     smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
2106 root 1.30
2107 root 1.176 // add bits to current tile and all neighbours. skey.x|y is
2108     // shifted +1|+1 so we always stay positive.
2109 root 1.30
2110 root 1.180 // bits is ___n cccc CCCC bbbb
2111     // n do not draw borders&corners
2112     // c draw these corners, but...
2113     // C ... not these
2114     // b draw these borders
2115    
2116     // borders: 1 ┃· 2 ━━ 4 ·┃ 8 ··
2117     // ┃· ·· ·┃ ━━
2118    
2119     // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2120     // ·· ·· ·┏ ┓·
2121    
2122 root 1.176 // full tile
2123     skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
2124    
2125     // borders
2126 root 1.180 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091);
2127     skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032);
2128 root 1.176 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
2129     skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
2130    
2131     // corners
2132     skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
2133     skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
2134     skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
2135     skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
2136     }
2137     }
2138     }
2139     }
2140 root 1.174
2141 root 1.224 rc_draw (rc);
2142     rc_clear (rc);
2143    
2144 root 1.186 // go through all smoothlevels, lowest to highest, then draw.
2145     // this is basically counting sort
2146 root 1.176 {
2147 root 1.186 int w, b;
2148 root 1.30
2149 root 1.226 glEnable (GL_TEXTURE_2D);
2150     glBegin (GL_QUADS);
2151 root 1.186 for (w = 0; w < 256 / 32; ++w)
2152     {
2153     uint32_t smask = smooth_level [w];
2154     if (smask)
2155     for (b = 0; b < 32; ++b)
2156     if (smask & (((uint32_t)1) << b))
2157 root 1.176 {
2158 root 1.186 int level = (w << 5) | b;
2159     HE *he;
2160 root 1.153
2161 root 1.186 hv_iterinit (smooth);
2162     while ((he = hv_iternext (smooth)))
2163 root 1.153 {
2164 root 1.186 smooth_key *skey = (smooth_key *)HeKEY (he);
2165     IV bits = SvIVX (HeVAL (he));
2166 root 1.176
2167 root 1.186 if (!(bits & 0x1000)
2168     && skey->level == level
2169 root 1.191 && level > smooth_max [skey->x][skey->y])
2170 root 1.174 {
2171 root 1.186 maptex tex = self->tex [skey->tile];
2172     int px = (((int)skey->x) - 1) * T;
2173     int py = (((int)skey->y) - 1) * T;
2174     int border = bits & 15;
2175     int corner = (bits >> 8) & ~(bits >> 4) & 15;
2176     float dx = tex.s * .0625f; // 16 images/row
2177     float dy = tex.t * .5f ; // 2 images/column
2178    
2179 root 1.223 if (tex.name)
2180 root 1.186 {
2181 root 1.223 // this time avoiding texture state changes
2182     // save gobs of state changes.
2183     if (key.texname != tex.name)
2184     {
2185 root 1.226 glEnd ();
2186     glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2187     glBegin (GL_QUADS);
2188 root 1.223 }
2189    
2190     if (border)
2191     {
2192     float ox = border * dx;
2193    
2194 root 1.226 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2195     glTexCoord2f (ox , dy ); glVertex2i (px , py + T);
2196     glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T);
2197     glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py );
2198 root 1.223 }
2199    
2200     if (corner)
2201     {
2202     float ox = corner * dx;
2203    
2204 root 1.226 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2205     glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T);
2206     glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T);
2207     glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py );
2208 root 1.223 }
2209 root 1.186 }
2210 root 1.174 }
2211 root 1.153 }
2212     }
2213 root 1.186 }
2214 root 1.226
2215     glEnd ();
2216     glDisable (GL_TEXTURE_2D);
2217     key.texname = -1;
2218 root 1.176 }
2219    
2220 root 1.186 hv_clear (smooth);
2221     }
2222 root 1.30
2223 root 1.261 if (pl_tex.name)
2224     {
2225     maptex tex = pl_tex;
2226 root 1.266 int px = pl_x + sdx;
2227     int py = pl_y + sdy;
2228 root 1.261
2229     key.texname = tex.name;
2230     arr = rc_array (rc, &key);
2231    
2232     rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2233     rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
2234     rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
2235     rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
2236    
2237     rc_draw (rc);
2238     }
2239    
2240 root 1.152 glDisable (GL_BLEND);
2241 root 1.223 rc_free (rc);
2242 root 1.143
2243 root 1.145 // top layer: overlays such as the health bar
2244 root 1.143 for (y = 0; y < sh; y++)
2245 root 1.164 if (0 <= y + my && y + my < self->rows)
2246 root 1.143 {
2247 root 1.164 maprow *row = self->row + (y + my);
2248 root 1.143
2249     for (x = 0; x < sw; x++)
2250 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
2251 root 1.143 {
2252 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
2253 root 1.143
2254 root 1.171 int px = x * T;
2255     int py = y * T;
2256 root 1.143
2257     if (cell->stat_hp)
2258     {
2259 root 1.171 int width = cell->stat_width * T;
2260 root 1.174 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width;
2261 root 1.143
2262 root 1.152 glColor3ub (0, 0, 0);
2263 root 1.151 glRectf (px + 1, py - thick - 2,
2264     px + width - 1, py);
2265 root 1.147
2266 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
2267 root 1.147 glRectf (px + 2,
2268 root 1.151 py - thick - 1,
2269     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
2270 root 1.143 }
2271     }
2272     }
2273 root 1.116 }
2274    
2275     void
2276 root 1.242 draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data)
2277 root 1.117 CODE:
2278     {
2279     static float color[16][3] = {
2280 root 1.123 { 0.00F, 0.00F, 0.00F },
2281     { 1.00F, 1.00F, 1.00F },
2282     { 0.00F, 0.00F, 0.55F },
2283     { 1.00F, 0.00F, 0.00F },
2284    
2285     { 1.00F, 0.54F, 0.00F },
2286     { 0.11F, 0.56F, 1.00F },
2287     { 0.93F, 0.46F, 0.00F },
2288     { 0.18F, 0.54F, 0.34F },
2289    
2290     { 0.56F, 0.73F, 0.56F },
2291     { 0.80F, 0.80F, 0.80F },
2292     { 0.55F, 0.41F, 0.13F },
2293     { 0.99F, 0.77F, 0.26F },
2294    
2295     { 0.74F, 0.65F, 0.41F },
2296    
2297     { 0.00F, 1.00F, 1.00F },
2298     { 1.00F, 0.00F, 1.00F },
2299     { 1.00F, 1.00F, 0.00F },
2300 root 1.117 };
2301    
2302     int x, y;
2303    
2304     glEnable (GL_TEXTURE_2D);
2305     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2306     glEnable (GL_BLEND);
2307     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2308     glBegin (GL_QUADS);
2309    
2310     for (y = 0; y < h; y++)
2311     for (x = 0; x < w; x++)
2312     {
2313     unsigned char m = data [x + y * w];
2314    
2315 root 1.118 if (m)
2316     {
2317     float *c = color [m & 15];
2318    
2319     float tx1 = m & 0x40 ? 0.5 : 0.;
2320     float tx2 = tx1 + 0.5;
2321    
2322     glColor4f (c[0], c[1], c[2], 0.75);
2323     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2324     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2325     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2326     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2327     }
2328 root 1.117 }
2329    
2330     glEnd ();
2331     glDisable (GL_BLEND);
2332     glDisable (GL_TEXTURE_2D);
2333     }
2334    
2335     void
2336 root 1.242 fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2337 root 1.116 PPCODE:
2338     {
2339     int x, y;
2340 root 1.204 int sw1 = sw + 2;
2341     int sh1 = sh + 2;
2342     int sh3 = sh * 3;
2343     int sw34 = (sw * 3 + 3) & ~3;
2344     uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2345     SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3));
2346     uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2347    
2348     SvPOK_only (darkness3_sv);
2349     SvCUR_set (darkness3_sv, sw34 * sh3);
2350 root 1.116
2351 root 1.204 mx += self->x - 1;
2352     my += self->y - 1;
2353 root 1.116
2354 root 1.269 memset (darkness1, 255 - FOW_DARKNESS, sw1 * sh1);
2355 root 1.204
2356     for (y = 0; y < sh1; y++)
2357 root 1.164 if (0 <= y + my && y + my < self->rows)
2358 root 1.116 {
2359 root 1.164 maprow *row = self->row + (y + my);
2360 root 1.116
2361 root 1.204 for (x = 0; x < sw1; x++)
2362 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
2363 root 1.116 {
2364 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
2365 root 1.116
2366 root 1.204 darkness1 [y * sw1 + x] = cell->darkness
2367 root 1.143 ? 255 - (cell->darkness - 1)
2368 root 1.142 : 255 - FOW_DARKNESS;
2369 root 1.116 }
2370     }
2371 root 1.34
2372 root 1.204 for (y = 0; y < sh; ++y)
2373     for (x = 0; x < sw; ++x)
2374     {
2375     uint8_t d11 = darkness1 [(y ) * sw1 + x ];
2376     uint8_t d21 = darkness1 [(y ) * sw1 + x + 1];
2377     uint8_t d31 = darkness1 [(y ) * sw1 + x + 2];
2378     uint8_t d12 = darkness1 [(y + 1) * sw1 + x ];
2379     uint8_t d22 = darkness1 [(y + 1) * sw1 + x + 1];
2380     uint8_t d32 = darkness1 [(y + 1) * sw1 + x + 2];
2381     uint8_t d13 = darkness1 [(y + 2) * sw1 + x ];
2382     uint8_t d23 = darkness1 [(y + 2) * sw1 + x + 1];
2383     uint8_t d33 = darkness1 [(y + 2) * sw1 + x + 2];
2384    
2385     uint8_t r11 = (d11 + d21 + d12) / 3;
2386     uint8_t r21 = d21;
2387     uint8_t r31 = (d21 + d31 + d32) / 3;
2388    
2389     uint8_t r12 = d12;
2390     uint8_t r22 = d22;
2391     uint8_t r32 = d32;
2392    
2393     uint8_t r13 = (d13 + d23 + d12) / 3;
2394     uint8_t r23 = d23;
2395     uint8_t r33 = (d23 + d33 + d32) / 3;
2396    
2397     darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11);
2398     darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21);
2399     darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31);
2400     darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12);
2401     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22);
2402     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32);
2403     darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13);
2404     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23);
2405     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33);
2406     }
2407 root 1.201
2408 root 1.204 free (darkness1);
2409 root 1.201
2410 root 1.32 EXTEND (SP, 3);
2411 root 1.204 PUSHs (sv_2mortal (newSViv (sw34)));
2412     PUSHs (sv_2mortal (newSViv (sh3)));
2413     PUSHs (darkness3_sv);
2414 root 1.30 }
2415    
2416 root 1.42 SV *
2417 root 1.242 get_rect (DC::Map self, int x0, int y0, int w, int h)
2418 root 1.42 CODE:
2419     {
2420     int x, y, x1, y1;
2421     SV *data_sv = newSV (w * h * 7 + 5);
2422     uint8_t *data = (uint8_t *)SvPVX (data_sv);
2423    
2424     *data++ = 0; /* version 0 format */
2425     *data++ = w >> 8; *data++ = w;
2426     *data++ = h >> 8; *data++ = h;
2427    
2428     // we need to do this 'cause we don't keep an absolute coord system for rows
2429 root 1.55 // TODO: treat rows as we treat columns
2430 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2431     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2432    
2433     x0 += self->x - self->ox;
2434     y0 += self->y - self->oy;
2435    
2436     x1 = x0 + w;
2437     y1 = y0 + h;
2438    
2439     for (y = y0; y < y1; y++)
2440     {
2441     maprow *row = 0 <= y && y < self->rows
2442     ? self->row + y
2443     : 0;
2444    
2445     for (x = x0; x < x1; x++)
2446     {
2447     if (row && row->c0 <= x && x < row->c1)
2448     {
2449     mapcell *cell = row->col + (x - row->c0);
2450     uint8_t flags = 0;
2451    
2452 root 1.174 if (cell->tile [0]) flags |= 1;
2453     if (cell->tile [1]) flags |= 2;
2454     if (cell->tile [2]) flags |= 4;
2455 root 1.42
2456     *data++ = flags;
2457    
2458     if (flags & 1)
2459     {
2460 root 1.174 tileid tile = cell->tile [0];
2461     *data++ = tile >> 8;
2462     *data++ = tile;
2463 root 1.42 }
2464    
2465     if (flags & 2)
2466     {
2467 root 1.174 tileid tile = cell->tile [1];
2468     *data++ = tile >> 8;
2469     *data++ = tile;
2470 root 1.42 }
2471    
2472     if (flags & 4)
2473     {
2474 root 1.174 tileid tile = cell->tile [2];
2475     *data++ = tile >> 8;
2476     *data++ = tile;
2477 root 1.42 }
2478     }
2479     else
2480     *data++ = 0;
2481     }
2482     }
2483    
2484 root 1.260 /* if size is w*h + 5 then no data has been found */
2485     if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2486 root 1.259 {
2487     SvPOK_only (data_sv);
2488     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2489     }
2490 root 1.260
2491     RETVAL = data_sv;
2492 root 1.42 }
2493     OUTPUT:
2494     RETVAL
2495    
2496     void
2497 root 1.259 set_rect (DC::Map self, int x0, int y0, SV *data_sv)
2498 root 1.42 PPCODE:
2499     {
2500     int x, y, z;
2501 root 1.48 int w, h;
2502 root 1.42 int x1, y1;
2503 root 1.259 STRLEN len;
2504     uint8_t *data, *end;
2505    
2506     len = SvLEN (data_sv);
2507 root 1.260 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2508 root 1.259 data = SvPVbyte_nolen (data_sv);
2509 root 1.260 end = data + len + 8;
2510 root 1.259
2511     if (len < 5)
2512     XSRETURN_EMPTY;
2513 root 1.42
2514     if (*data++ != 0)
2515 root 1.227 XSRETURN_EMPTY; /* version mismatch */
2516 root 1.42
2517 root 1.48 w = *data++ << 8; w |= *data++;
2518     h = *data++ << 8; h |= *data++;
2519 root 1.42
2520     // we need to do this 'cause we don't keep an absolute coord system for rows
2521 root 1.55 // TODO: treat rows as we treat columns
2522 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2523     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2524    
2525     x0 += self->x - self->ox;
2526     y0 += self->y - self->oy;
2527    
2528     x1 = x0 + w;
2529     y1 = y0 + h;
2530    
2531     for (y = y0; y < y1; y++)
2532     {
2533     maprow *row = map_get_row (self, y);
2534    
2535     for (x = x0; x < x1; x++)
2536     {
2537 root 1.259 uint8_t flags;
2538    
2539     if (data + 7 >= end)
2540     XSRETURN_EMPTY;
2541    
2542     flags = *data++;
2543 root 1.42
2544     if (flags)
2545     {
2546     mapcell *cell = row_get_cell (row, x);
2547 root 1.174 tileid tile[3] = { 0, 0, 0 };
2548 root 1.42
2549 root 1.174 if (flags & 1) { tile[0] = *data++ << 8; tile[0] |= *data++; }
2550     if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2551     if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2552 root 1.42
2553 root 1.143 if (cell->darkness == 0)
2554 root 1.42 {
2555 root 1.260 /*cell->darkness = 0;*/
2556     EXTEND (SP, 3);
2557 root 1.42
2558     for (z = 0; z <= 2; z++)
2559     {
2560 root 1.174 tileid t = tile [z];
2561    
2562 root 1.175 if (t >= self->texs || (t && !self->tex [t].name))
2563 root 1.174 {
2564 root 1.260 PUSHs (sv_2mortal (newSViv (t)));
2565 root 1.174 need_texid (self, t);
2566     }
2567 root 1.42
2568 root 1.174 cell->tile [z] = t;
2569 root 1.42 }
2570     }
2571     }
2572     }
2573     }
2574     }
2575    
2576 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::RW
2577 root 1.205
2578 root 1.242 DC::RW
2579 root 1.211 new (SV *class, SV *data_sv)
2580     CODE:
2581     {
2582     STRLEN datalen;
2583     char *data = SvPVbyte (data_sv, datalen);
2584    
2585 root 1.212 RETVAL = SDL_RWFromConstMem (data, datalen);
2586 root 1.211 }
2587     OUTPUT:
2588     RETVAL
2589    
2590 root 1.242 DC::RW
2591 root 1.212 new_from_file (SV *class, const char *path, const char *mode = "rb")
2592     CODE:
2593     RETVAL = SDL_RWFromFile (path, mode);
2594     OUTPUT:
2595     RETVAL
2596    
2597 root 1.218 # fails on win32:
2598 root 1.241 # dc.xs(2268) : error C2059: syntax error : '('
2599 root 1.218 #void
2600 root 1.242 #close (DC::RW self)
2601 root 1.218 # CODE:
2602     # (self->(close)) (self);
2603 root 1.212
2604 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::Channel
2605 root 1.212
2606     PROTOTYPES: DISABLE
2607    
2608 root 1.242 DC::Channel
2609 root 1.215 find ()
2610     CODE:
2611     {
2612     RETVAL = Mix_GroupAvailable (-1);
2613    
2614     if (RETVAL < 0)
2615     {
2616     RETVAL = Mix_GroupOldest (-1);
2617    
2618     if (RETVAL < 0)
2619     XSRETURN_UNDEF;
2620    
2621     Mix_HaltChannel (RETVAL);
2622     }
2623    
2624     Mix_UnregisterAllEffects (RETVAL);
2625     Mix_Volume (RETVAL, 128);
2626     }
2627     OUTPUT:
2628     RETVAL
2629    
2630 root 1.213 void
2631 root 1.242 halt (DC::Channel self)
2632 root 1.213 CODE:
2633     Mix_HaltChannel (self);
2634    
2635     void
2636 root 1.242 expire (DC::Channel self, int ticks = -1)
2637 root 1.213 CODE:
2638     Mix_ExpireChannel (self, ticks);
2639    
2640     void
2641 root 1.242 fade_out (DC::Channel self, int ticks = -1)
2642 root 1.213 CODE:
2643     Mix_FadeOutChannel (self, ticks);
2644    
2645 root 1.212 int
2646 root 1.242 volume (DC::Channel self, int volume)
2647 root 1.212 CODE:
2648 root 1.216 RETVAL = Mix_Volume (self, CLAMP (volume, 0, 128));
2649 root 1.212 OUTPUT:
2650     RETVAL
2651    
2652 root 1.213 void
2653 root 1.242 unregister_all_effects (DC::Channel self)
2654 root 1.212 CODE:
2655 root 1.213 Mix_UnregisterAllEffects (self);
2656 root 1.212
2657 root 1.213 void
2658 root 1.242 set_panning (DC::Channel self, int left, int right)
2659 root 1.212 CODE:
2660 root 1.216 left = CLAMP (left , 0, 255);
2661     right = CLAMP (right, 0, 255);
2662 root 1.213 Mix_SetPanning (self, left, right);
2663 root 1.212
2664 root 1.213 void
2665 root 1.242 set_distance (DC::Channel self, int distance)
2666 root 1.212 CODE:
2667 root 1.216 Mix_SetDistance (self, CLAMP (distance, 0, 255));
2668 root 1.212
2669 root 1.213 void
2670 root 1.242 set_position (DC::Channel self, int angle, int distance)
2671 root 1.212 CODE:
2672 root 1.220
2673     void
2674 root 1.242 set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2675 root 1.220 CODE:
2676     {
2677     int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2678     int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI);
2679 root 1.216 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2680 root 1.220 }
2681 root 1.212
2682 root 1.213 void
2683 root 1.242 set_reverse_stereo (DC::Channel self, int flip)
2684 root 1.212 CODE:
2685 root 1.213 Mix_SetReverseStereo (self, flip);
2686 root 1.212
2687 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2688 root 1.212
2689     PROTOTYPES: DISABLE
2690    
2691 root 1.242 DC::MixChunk
2692     new (SV *class, DC::RW rwops)
2693 root 1.52 CODE:
2694 root 1.212 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2695 root 1.52 OUTPUT:
2696     RETVAL
2697    
2698     void
2699 root 1.242 DESTROY (DC::MixChunk self)
2700 root 1.52 CODE:
2701     Mix_FreeChunk (self);
2702    
2703     int
2704 root 1.242 volume (DC::MixChunk self, int volume = -1)
2705 root 1.52 CODE:
2706 root 1.216 if (items > 1)
2707     volume = CLAMP (volume, 0, 128);
2708 root 1.52 RETVAL = Mix_VolumeChunk (self, volume);
2709     OUTPUT:
2710     RETVAL
2711    
2712 root 1.242 DC::Channel
2713     play (DC::MixChunk self, DC::Channel channel = -1, int loops = 0, int ticks = -1)
2714 root 1.52 CODE:
2715 root 1.215 {
2716 root 1.52 RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
2717 root 1.215
2718     if (RETVAL < 0)
2719     XSRETURN_UNDEF;
2720    
2721     if (channel < 0)
2722     {
2723     Mix_UnregisterAllEffects (RETVAL);
2724     Mix_Volume (RETVAL, 128);
2725     }
2726     }
2727 root 1.52 OUTPUT:
2728     RETVAL
2729    
2730 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2731 root 1.52
2732     int
2733     volume (int volume = -1)
2734 root 1.205 PROTOTYPE: ;$
2735 root 1.52 CODE:
2736 root 1.216 if (items > 0)
2737     volume = CLAMP (volume, 0, 128);
2738 root 1.52 RETVAL = Mix_VolumeMusic (volume);
2739     OUTPUT:
2740     RETVAL
2741    
2742 root 1.213 void
2743 root 1.194 fade_out (int ms)
2744     CODE:
2745 root 1.213 Mix_FadeOutMusic (ms);
2746 root 1.194
2747 root 1.212 void
2748     halt ()
2749     CODE:
2750     Mix_HaltMusic ();
2751    
2752 root 1.242 DC::MixMusic
2753     new (SV *class, DC::RW rwops)
2754 root 1.52 CODE:
2755 root 1.212 RETVAL = Mix_LoadMUS_RW (rwops);
2756 root 1.52 OUTPUT:
2757     RETVAL
2758    
2759     void
2760 root 1.242 DESTROY (DC::MixMusic self)
2761 root 1.52 CODE:
2762     Mix_FreeMusic (self);
2763    
2764     int
2765 root 1.242 play (DC::MixMusic self, int loops = -1)
2766 root 1.52 CODE:
2767     RETVAL = Mix_PlayMusic (self, loops);
2768     OUTPUT:
2769     RETVAL
2770    
2771 root 1.213 void
2772 root 1.242 fade_in_pos (DC::MixMusic self, int loops, int ms, double position)
2773 root 1.195 CODE:
2774 root 1.213 Mix_FadeInMusicPos (self, loops, ms, position);
2775 root 1.195
2776 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::OpenGL
2777 root 1.54
2778 root 1.205 PROTOTYPES: ENABLE
2779    
2780 root 1.54 BOOT:
2781     {
2782 root 1.242 HV *stash = gv_stashpv ("DC::OpenGL", 1);
2783 root 1.54 static const struct {
2784     const char *name;
2785     IV iv;
2786     } *civ, const_iv[] = {
2787     # define const_iv(name) { # name, (IV)name }
2788 root 1.199 const_iv (GL_VENDOR),
2789     const_iv (GL_VERSION),
2790     const_iv (GL_EXTENSIONS),
2791 root 1.54 const_iv (GL_COLOR_MATERIAL),
2792     const_iv (GL_SMOOTH),
2793     const_iv (GL_FLAT),
2794 root 1.69 const_iv (GL_DITHER),
2795 root 1.54 const_iv (GL_BLEND),
2796 root 1.89 const_iv (GL_CULL_FACE),
2797 root 1.69 const_iv (GL_SCISSOR_TEST),
2798 root 1.89 const_iv (GL_DEPTH_TEST),
2799     const_iv (GL_ALPHA_TEST),
2800     const_iv (GL_NORMALIZE),
2801     const_iv (GL_RESCALE_NORMAL),
2802 root 1.119 const_iv (GL_FRONT),
2803     const_iv (GL_BACK),
2804 root 1.206 const_iv (GL_AUX0),
2805 root 1.54 const_iv (GL_AND),
2806 root 1.67 const_iv (GL_ONE),
2807     const_iv (GL_ZERO),
2808 root 1.54 const_iv (GL_SRC_ALPHA),
2809 root 1.104 const_iv (GL_DST_ALPHA),
2810 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2811 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
2812 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
2813 root 1.54 const_iv (GL_RGB),
2814     const_iv (GL_RGBA),
2815 root 1.115 const_iv (GL_RGBA4),
2816     const_iv (GL_RGBA8),
2817     const_iv (GL_RGB5_A1),
2818 root 1.54 const_iv (GL_UNSIGNED_BYTE),
2819 root 1.89 const_iv (GL_UNSIGNED_SHORT),
2820     const_iv (GL_UNSIGNED_INT),
2821 root 1.54 const_iv (GL_ALPHA),
2822 root 1.86 const_iv (GL_INTENSITY),
2823 root 1.76 const_iv (GL_LUMINANCE),
2824 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
2825 root 1.54 const_iv (GL_FLOAT),
2826     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
2827 root 1.230 const_iv (GL_COMPRESSED_ALPHA_ARB),
2828     const_iv (GL_COMPRESSED_LUMINANCE_ARB),
2829     const_iv (GL_COMPRESSED_LUMINANCE_ALPHA_ARB),
2830     const_iv (GL_COMPRESSED_INTENSITY_ARB),
2831     const_iv (GL_COMPRESSED_RGB_ARB),
2832     const_iv (GL_COMPRESSED_RGBA_ARB),
2833 root 1.54 const_iv (GL_COMPILE),
2834 root 1.199 const_iv (GL_PROXY_TEXTURE_1D),
2835     const_iv (GL_PROXY_TEXTURE_2D),
2836 root 1.54 const_iv (GL_TEXTURE_1D),
2837     const_iv (GL_TEXTURE_2D),
2838     const_iv (GL_TEXTURE_ENV),
2839     const_iv (GL_TEXTURE_MAG_FILTER),
2840     const_iv (GL_TEXTURE_MIN_FILTER),
2841     const_iv (GL_TEXTURE_ENV_MODE),
2842     const_iv (GL_TEXTURE_WRAP_S),
2843     const_iv (GL_TEXTURE_WRAP_T),
2844 root 1.98 const_iv (GL_REPEAT),
2845 root 1.54 const_iv (GL_CLAMP),
2846 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
2847 root 1.54 const_iv (GL_NEAREST),
2848     const_iv (GL_LINEAR),
2849 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
2850     const_iv (GL_LINEAR_MIPMAP_NEAREST),
2851     const_iv (GL_NEAREST_MIPMAP_LINEAR),
2852     const_iv (GL_LINEAR_MIPMAP_LINEAR),
2853     const_iv (GL_GENERATE_MIPMAP),
2854 root 1.54 const_iv (GL_MODULATE),
2855 root 1.69 const_iv (GL_DECAL),
2856 root 1.54 const_iv (GL_REPLACE),
2857 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
2858 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
2859     const_iv (GL_PROJECTION),
2860     const_iv (GL_MODELVIEW),
2861     const_iv (GL_COLOR_LOGIC_OP),
2862 root 1.69 const_iv (GL_SEPARABLE_2D),
2863 root 1.54 const_iv (GL_CONVOLUTION_2D),
2864     const_iv (GL_CONVOLUTION_BORDER_MODE),
2865     const_iv (GL_CONSTANT_BORDER),
2866 root 1.208 const_iv (GL_POINTS),
2867 root 1.54 const_iv (GL_LINES),
2868 root 1.138 const_iv (GL_LINE_STRIP),
2869 root 1.89 const_iv (GL_LINE_LOOP),
2870 root 1.54 const_iv (GL_QUADS),
2871 root 1.89 const_iv (GL_QUAD_STRIP),
2872     const_iv (GL_TRIANGLES),
2873     const_iv (GL_TRIANGLE_STRIP),
2874     const_iv (GL_TRIANGLE_FAN),
2875 root 1.208 const_iv (GL_POLYGON),
2876 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
2877 root 1.206 const_iv (GL_POINT_SMOOTH_HINT),
2878     const_iv (GL_LINE_SMOOTH_HINT),
2879     const_iv (GL_POLYGON_SMOOTH_HINT),
2880     const_iv (GL_GENERATE_MIPMAP_HINT),
2881 root 1.232 const_iv (GL_TEXTURE_COMPRESSION_HINT),
2882 root 1.54 const_iv (GL_FASTEST),
2883 root 1.206 const_iv (GL_DONT_CARE),
2884     const_iv (GL_NICEST),
2885 root 1.89 const_iv (GL_V2F),
2886     const_iv (GL_V3F),
2887     const_iv (GL_T2F_V3F),
2888     const_iv (GL_T2F_N3F_V3F),
2889 root 1.54 # undef const_iv
2890     };
2891    
2892     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
2893     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
2894 root 1.188
2895     texture_av = newAV ();
2896     AvREAL_off (texture_av);
2897 root 1.54 }
2898    
2899 root 1.231 void
2900     disable_GL_EXT_blend_func_separate ()
2901     CODE:
2902     gl.BlendFuncSeparate = 0;
2903     gl.BlendFuncSeparateEXT = 0;
2904    
2905 root 1.97 char *
2906     gl_vendor ()
2907     CODE:
2908     RETVAL = (char *)glGetString (GL_VENDOR);
2909     OUTPUT:
2910     RETVAL
2911    
2912     char *
2913     gl_version ()
2914     CODE:
2915     RETVAL = (char *)glGetString (GL_VERSION);
2916     OUTPUT:
2917     RETVAL
2918    
2919     char *
2920     gl_extensions ()
2921     CODE:
2922     RETVAL = (char *)glGetString (GL_EXTENSIONS);
2923     OUTPUT:
2924     RETVAL
2925    
2926 root 1.201 const char *glGetString (GLenum pname)
2927 root 1.199
2928     GLint glGetInteger (GLenum pname)
2929     CODE:
2930     glGetIntegerv (pname, &RETVAL);
2931     OUTPUT:
2932     RETVAL
2933    
2934     GLdouble glGetDouble (GLenum pname)
2935     CODE:
2936     glGetDoublev (pname, &RETVAL);
2937     OUTPUT:
2938     RETVAL
2939    
2940 root 1.54 int glGetError ()
2941    
2942 root 1.114 void glFinish ()
2943    
2944 root 1.54 void glClear (int mask)
2945    
2946     void glClearColor (float r, float g, float b, float a = 1.0)
2947     PROTOTYPE: @
2948    
2949     void glEnable (int cap)
2950    
2951     void glDisable (int cap)
2952    
2953     void glShadeModel (int mode)
2954    
2955     void glHint (int target, int mode)
2956    
2957     void glBlendFunc (int sfactor, int dfactor)
2958    
2959 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2960     CODE:
2961     gl_BlendFuncSeparate (sa, da, saa, daa);
2962    
2963 root 1.89 void glDepthMask (int flag)
2964    
2965 root 1.54 void glLogicOp (int opcode)
2966    
2967 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
2968    
2969 root 1.54 void glMatrixMode (int mode)
2970    
2971     void glPushMatrix ()
2972    
2973     void glPopMatrix ()
2974    
2975     void glLoadIdentity ()
2976    
2977 root 1.119 void glDrawBuffer (int buffer)
2978    
2979     void glReadBuffer (int buffer)
2980    
2981 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
2982     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2983    
2984     # near_ and far_ are due to microsofts buggy "c" compiler
2985 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2986 root 1.54
2987 root 1.208 PROTOTYPES: DISABLE
2988    
2989 root 1.54 void glViewport (int x, int y, int width, int height)
2990    
2991 root 1.69 void glScissor (int x, int y, int width, int height)
2992    
2993 root 1.54 void glTranslate (float x, float y, float z = 0.)
2994     CODE:
2995     glTranslatef (x, y, z);
2996    
2997 root 1.62 void glScale (float x, float y, float z = 1.)
2998 root 1.54 CODE:
2999     glScalef (x, y, z);
3000    
3001     void glRotate (float angle, float x, float y, float z)
3002     CODE:
3003     glRotatef (angle, x, y, z);
3004    
3005     void glColor (float r, float g, float b, float a = 1.0)
3006 root 1.278 PROTOTYPE: @
3007 root 1.103 ALIAS:
3008     glColor_premultiply = 1
3009 root 1.54 CODE:
3010 root 1.103 if (ix)
3011     {
3012     r *= a;
3013     g *= a;
3014     b *= a;
3015     }
3016 root 1.90 // microsoft visual "c" rounds instead of truncating...
3017 root 1.130 glColor4f (r, g, b, a);
3018 root 1.54
3019 root 1.91 void glRasterPos (float x, float y, float z = 0.)
3020     CODE:
3021     glRasterPos3f (0, 0, z);
3022     glBitmap (0, 0, 0, 0, x, y, 0);
3023    
3024 root 1.54 void glVertex (float x, float y, float z = 0.)
3025     CODE:
3026     glVertex3f (x, y, z);
3027    
3028     void glTexCoord (float s, float t)
3029     CODE:
3030     glTexCoord2f (s, t);
3031    
3032 root 1.210 void glRect (float x1, float y1, float x2, float y2)
3033     CODE:
3034     glRectf (x1, y1, x2, y2);
3035    
3036 root 1.233 void glRect_lineloop (float x1, float y1, float x2, float y2)
3037     CODE:
3038     glBegin (GL_LINE_LOOP);
3039     glVertex2f (x1, y1);
3040     glVertex2f (x2, y1);
3041     glVertex2f (x2, y2);
3042     glVertex2f (x1, y2);
3043     glEnd ();
3044    
3045 root 1.208 PROTOTYPES: ENABLE
3046    
3047     void glBegin (int mode)
3048    
3049     void glEnd ()
3050    
3051     void glPointSize (GLfloat size)
3052    
3053     void glLineWidth (GLfloat width)
3054    
3055     void glInterleavedArrays (int format, int stride, char *data)
3056    
3057     void glDrawElements (int mode, int count, int type, char *indices)
3058    
3059     # 1.2 void glDrawRangeElements (int mode, int start, int end
3060    
3061 root 1.54 void glTexEnv (int target, int pname, float param)
3062     CODE:
3063     glTexEnvf (target, pname, param);
3064    
3065     void glTexParameter (int target, int pname, float param)
3066     CODE:
3067     glTexParameterf (target, pname, param);
3068    
3069     void glBindTexture (int target, int name)
3070    
3071     void glConvolutionParameter (int target, int pname, float params)
3072     CODE:
3073 root 1.103 if (gl.ConvolutionParameterf)
3074     gl.ConvolutionParameterf (target, pname, params);
3075 root 1.54
3076     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
3077 root 1.64 CODE:
3078 root 1.103 if (gl.ConvolutionFilter2D)
3079     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
3080 root 1.54
3081 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
3082     CODE:
3083 root 1.103 if (gl.SeparableFilter2D)
3084     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
3085 root 1.69
3086 root 1.244 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data = 0)
3087 root 1.54
3088     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
3089    
3090 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
3091 root 1.68
3092 root 1.199 void glPixelZoom (float x, float y)
3093    
3094 root 1.68 void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
3095    
3096 root 1.54 int glGenTexture ()
3097     CODE:
3098 root 1.192 RETVAL = gen_texture ();
3099 root 1.54 OUTPUT:
3100     RETVAL
3101    
3102     void glDeleteTexture (int name)
3103     CODE:
3104 root 1.192 del_texture (name);
3105    
3106 root 1.54 int glGenList ()
3107     CODE:
3108     RETVAL = glGenLists (1);
3109     OUTPUT:
3110     RETVAL
3111    
3112     void glDeleteList (int list)
3113     CODE:
3114     glDeleteLists (list, 1);
3115    
3116     void glNewList (int list, int mode = GL_COMPILE)
3117    
3118     void glEndList ()
3119    
3120     void glCallList (int list)
3121    
3122 root 1.242 MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3123 root 1.207
3124     PROTOTYPES: DISABLE
3125    
3126     void
3127 root 1.209 find_widget (SV *self, NV x, NV y)
3128 root 1.207 PPCODE:
3129     {
3130 root 1.209 if (within_widget (self, x, y))
3131     XPUSHs (self);
3132     }
3133    
3134     BOOT:
3135     {
3136 root 1.242 hover_gv = gv_fetchpv ("DC::UI::HOVER", 1, SVt_NV);
3137 root 1.209
3138 root 1.242 draw_x_gv = gv_fetchpv ("DC::UI::Base::draw_x", 1, SVt_NV);
3139     draw_y_gv = gv_fetchpv ("DC::UI::Base::draw_y", 1, SVt_NV);
3140     draw_w_gv = gv_fetchpv ("DC::UI::Base::draw_w", 1, SVt_NV);
3141     draw_h_gv = gv_fetchpv ("DC::UI::Base::draw_h", 1, SVt_NV);
3142 root 1.209 }
3143    
3144     void
3145     draw (SV *self)
3146     CODE:
3147     {
3148     HV *hv;
3149     SV **svp;
3150     NV x, y, w, h;
3151     SV *draw_x_sv = GvSV (draw_x_gv);
3152     SV *draw_y_sv = GvSV (draw_y_gv);
3153     SV *draw_w_sv = GvSV (draw_w_gv);
3154     SV *draw_h_sv = GvSV (draw_h_gv);
3155 root 1.228 double draw_x, draw_y;
3156 root 1.209
3157     if (!SvROK (self))
3158 root 1.242 croak ("DC::Base::draw: %s not a reference", SvPV_nolen (self));
3159 root 1.209
3160     hv = (HV *)SvRV (self);
3161    
3162     if (SvTYPE (hv) != SVt_PVHV)
3163 root 1.242 croak ("DC::Base::draw: %s not a hashref", SvPV_nolen (self));
3164 root 1.209
3165     svp = hv_fetch (hv, "w", 1, 0); w = svp ? SvNV (*svp) : 0.;
3166     svp = hv_fetch (hv, "h", 1, 0); h = svp ? SvNV (*svp) : 0.;
3167    
3168     if (!h || !w)
3169     XSRETURN_EMPTY;
3170    
3171     svp = hv_fetch (hv, "x", 1, 0); x = svp ? SvNV (*svp) : 0.;
3172     svp = hv_fetch (hv, "y", 1, 0); y = svp ? SvNV (*svp) : 0.;
3173    
3174     draw_x = SvNV (draw_x_sv) + x;
3175     draw_y = SvNV (draw_y_sv) + y;
3176    
3177     if (draw_x + w < 0 || draw_x >= SvNV (draw_w_sv)
3178     || draw_y + h < 0 || draw_y >= SvNV (draw_h_sv))
3179     XSRETURN_EMPTY;
3180    
3181     sv_setnv (draw_x_sv, draw_x);
3182     sv_setnv (draw_y_sv, draw_y);
3183    
3184     glPushMatrix ();
3185     glTranslated (x, y, 0);
3186    
3187     if (SvROK (GvSV (hover_gv)) && SvRV (GvSV (hover_gv)) == (SV *)hv)
3188     {
3189     svp = hv_fetch (hv, "can_hover", sizeof ("can_hover") - 1, 0);
3190    
3191     if (svp && SvTRUE (*svp))
3192     {
3193 root 1.228 glColor4f (1.0f * 0.2f, 0.8f * 0.2f, 0.5f * 0.2f, 0.2f);
3194 root 1.209 glEnable (GL_BLEND);
3195     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
3196     glBegin (GL_QUADS);
3197     glVertex2f (0, 0);
3198     glVertex2f (w, 0);
3199     glVertex2f (w, h);
3200     glVertex2f (0, h);
3201     glEnd ();
3202     glDisable (GL_BLEND);
3203     }
3204     }
3205     #if 0
3206 root 1.234 // draw borders, for debugging
3207     glPushMatrix ();
3208     glColor4f (1., 1., 0., 1.);
3209     glTranslatef (.5, .5, 0.);
3210     glBegin (GL_LINE_LOOP);
3211     glVertex2f (0 , 0);
3212     glVertex2f (w - 1, 0);
3213     glVertex2f (w - 1, h - 1);
3214     glVertex2f (0 , h - 1);
3215     glEnd ();
3216     glPopMatrix ();
3217 root 1.209 #endif
3218     PUSHMARK (SP);
3219     XPUSHs (self);
3220     PUTBACK;
3221     call_method ("_draw", G_VOID | G_DISCARD);
3222     SPAGAIN;
3223    
3224     glPopMatrix ();
3225    
3226     draw_x = draw_x - x; sv_setnv (draw_x_sv, draw_x);
3227     draw_y = draw_y - y; sv_setnv (draw_y_sv, draw_y);
3228 root 1.207 }
3229