ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.293
Committed: Thu Dec 17 02:49:38 2009 UTC (14 years, 4 months ago) by root
Branch: MAIN
Changes since 1.292: +34 -0 lines
Log Message:
move draw_fow_texture to C

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