ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.153
Committed: Tue Sep 19 22:02:38 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.152: +32 -5 lines
Log Message:
add dialogue indicator support

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.79 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.75 # pragma warning(disable:4244)
7 root 1.48 #endif
8    
9 root 1.1 #include "EXTERN.h"
10     #include "perl.h"
11     #include "XSUB.h"
12    
13 root 1.131 #ifdef _WIN32
14     # undef pipe
15     #endif
16    
17 root 1.80 #include <math.h>
18 root 1.5 #include <string.h>
19 root 1.25 #include <stdio.h>
20 root 1.111 #include <stdlib.h>
21 root 1.5
22 root 1.2 #include <SDL.h>
23 root 1.76 #include <SDL_endian.h>
24 root 1.23 #include <SDL_image.h>
25 root 1.52 #include <SDL_mixer.h>
26 root 1.3 #include <SDL_opengl.h>
27 root 1.5
28 root 1.124 #define PANGO_ENABLE_BACKEND
29     #define G_DISABLE_CAST_CHECKS
30    
31 root 1.30 #include <glib/gmacros.h>
32    
33 root 1.5 #include <pango/pango.h>
34    
35 root 1.48 #ifndef _WIN32
36     # include <sys/types.h>
37     # include <sys/socket.h>
38     # include <netinet/in.h>
39     # include <netinet/tcp.h>
40     # include <inttypes.h>
41     #else
42     typedef unsigned char uint8_t;
43     typedef unsigned short uint16_t;
44     typedef unsigned int uint32_t;
45     typedef signed char int8_t;
46     typedef signed short int16_t;
47     typedef signed int int32_t;
48     #endif
49 root 1.28
50 root 1.121 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, objetc replacement character */
51    
52 root 1.29 #define FOW_DARKNESS 32
53    
54     #define MAP_EXTEND_X 32
55     #define MAP_EXTEND_Y 512
56    
57 root 1.63 #define MIN_FONT_HEIGHT 10
58 root 1.58
59 root 1.127 #if 0
60 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
61     #else
62     # define PARACHUTE 0
63     #endif
64    
65 root 1.103 static struct
66     {
67     #define GL_FUNC(ptr,name) ptr name;
68     #include "glfunc.h"
69     #undef GL_FUNC
70     } gl;
71    
72     static void gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
73     {
74     if (gl.BlendFuncSeparate)
75     gl.BlendFuncSeparate (sa, da, saa, daa);
76     else if (gl.BlendFuncSeparateEXT)
77     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
78     else
79     glBlendFunc (sa, da);
80     }
81 root 1.64
82 root 1.124 #include "texcache.c"
83    
84     #include "pango-font.c"
85     #include "pango-fontmap.c"
86     #include "pango-render.c"
87    
88 root 1.133 typedef Mix_Chunk *CFPlus__MixChunk;
89     typedef Mix_Music *CFPlus__MixMusic;
90 root 1.52
91 root 1.133 typedef PangoFontDescription *CFPlus__Font;
92 root 1.2
93 root 1.121 static int
94     shape_attr_p (PangoLayoutRun *run)
95     {
96     GSList *attrs = run->item->analysis.extra_attrs;
97    
98     while (attrs)
99     {
100     PangoAttribute *attr = attrs->data;
101    
102     if (attr->klass->type == PANGO_ATTR_SHAPE)
103     return 1;
104    
105     attrs = attrs->next;
106     }
107    
108     return 0;
109     }
110    
111 root 1.14 typedef struct cf_layout {
112 root 1.124 PangoLayout *pl;
113 root 1.76 float r, g, b, a; // default color for rgba mode
114 root 1.14 int base_height;
115 root 1.133 CFPlus__Font font;
116     } *CFPlus__Layout;
117 root 1.14
118 root 1.133 static CFPlus__Font default_font;
119 root 1.124 static PangoContext *opengl_context;
120     static PangoFontMap *opengl_fontmap;
121 root 1.61
122 root 1.14 static void
123 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
124     {
125 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
126 root 1.110 #ifdef FC_HINT_STYLE
127 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
128 root 1.110 #endif
129 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
130 root 1.19 }
131    
132     static void
133 root 1.133 layout_update_font (CFPlus__Layout self)
134 root 1.17 {
135 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
136     * reasonably well with bitstream vera
137     */
138 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
139 root 1.46
140 root 1.61 pango_font_description_set_absolute_size (font,
141     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
142 root 1.58
143 root 1.61 pango_layout_set_font_description (self->pl, font);
144 root 1.17 }
145    
146     static void
147 root 1.133 layout_get_pixel_size (CFPlus__Layout self, int *w, int *h)
148 root 1.14 {
149 root 1.139 PangoRectangle rect;
150 root 1.14
151 root 1.139 // get_pixel_* wrongly rounds down
152     pango_layout_get_extents (self->pl, 0, &rect);
153 root 1.76
154 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
155     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
156    
157     if (!rect.width) rect.width = 1;
158     if (!rect.height) rect.height = 1;
159    
160     *w = rect.width;
161     *h = rect.height;
162 root 1.14 }
163    
164 root 1.42 typedef uint16_t mapface;
165    
166 root 1.28 typedef struct {
167 root 1.30 GLint name;
168     int w, h;
169     float s, t;
170 root 1.39 uint8_t r, g, b, a;
171 root 1.42 } maptex;
172 root 1.30
173     typedef struct {
174 root 1.153 uint32_t player;
175     mapface face[3];
176 root 1.142 uint16_t darkness;
177 root 1.153 uint8_t stat_width, stat_hp, flags;
178 root 1.28 } mapcell;
179    
180     typedef struct {
181 root 1.30 int32_t c0, c1;
182 root 1.28 mapcell *col;
183     } maprow;
184    
185     typedef struct map {
186     int x, y, w, h;
187 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
188 root 1.28 int faces;
189 root 1.30 mapface *face;
190 root 1.28
191 root 1.42 int texs;
192     maptex *tex;
193    
194 root 1.48 int32_t rows;
195 root 1.28 maprow *row;
196 root 1.133 } *CFPlus__Map;
197 root 1.28
198 root 1.30 static char *
199     prepend (char *ptr, int sze, int inc)
200     {
201     char *p;
202    
203     New (0, p, sze + inc, char);
204     Zero (p, inc, char);
205     Move (ptr, p + inc, sze, char);
206     Safefree (ptr);
207    
208     return p;
209     }
210    
211     static char *
212     append (char *ptr, int sze, int inc)
213     {
214     Renew (ptr, sze + inc, char);
215     Zero (ptr + sze, inc, char);
216    
217     return ptr;
218     }
219    
220     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
221     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
222    
223 root 1.42 static maprow *
224 root 1.133 map_get_row (CFPlus__Map self, int y)
225 root 1.42 {
226     if (0 > y)
227     {
228     int extend = - y + MAP_EXTEND_Y;
229     Prepend (maprow, self->row, self->rows, extend);
230    
231     self->rows += extend;
232     self->y += extend;
233     y += extend;
234     }
235     else if (y >= self->rows)
236     {
237     int extend = y - self->rows + MAP_EXTEND_Y;
238     Append (maprow, self->row, self->rows, extend);
239     self->rows += extend;
240     }
241    
242     return self->row + y;
243     }
244    
245     static mapcell *
246     row_get_cell (maprow *row, int x)
247     {
248     if (!row->col)
249     {
250     Newz (0, row->col, MAP_EXTEND_X, mapcell);
251     row->c0 = x - MAP_EXTEND_X / 4;
252     row->c1 = row->c0 + MAP_EXTEND_X;
253     }
254    
255     if (row->c0 > x)
256     {
257     int extend = row->c0 - x + MAP_EXTEND_X;
258     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
259     row->c0 -= extend;
260     }
261     else if (x >= row->c1)
262     {
263     int extend = x - row->c1 + MAP_EXTEND_X;
264     Append (mapcell, row->col, row->c1 - row->c0, extend);
265     row->c1 += extend;
266     }
267    
268     return row->col + (x - row->c0);
269     }
270    
271     static mapcell *
272 root 1.133 map_get_cell (CFPlus__Map self, int x, int y)
273 root 1.42 {
274     return row_get_cell (map_get_row (self, y), x);
275     }
276    
277 root 1.30 static void
278 root 1.133 map_clear (CFPlus__Map self)
279 root 1.30 {
280     int r;
281    
282     for (r = 0; r < self->rows; r++)
283     Safefree (self->row[r].col);
284    
285     Safefree (self->row);
286    
287     self->x = 0;
288     self->y = 0;
289 root 1.42 self->ox = 0;
290     self->oy = 0;
291 root 1.30 self->row = 0;
292     self->rows = 0;
293     }
294    
295 root 1.29 static void
296 root 1.133 map_blank (CFPlus__Map self, int x0, int y0, int w, int h)
297 root 1.29 {
298     int x, y;
299 root 1.48 maprow *row;
300 root 1.146 mapcell *cell;
301 root 1.29
302     for (y = y0; y < y0 + h; y++)
303 root 1.30 if (y >= 0)
304     {
305     if (y >= self->rows)
306     break;
307    
308 root 1.48 row = self->row + y;
309 root 1.30
310     for (x = x0; x < x0 + w; x++)
311     if (x >= row->c0)
312     {
313     if (x >= row->c1)
314     break;
315 root 1.29
316 root 1.146 cell = row->col + x - row->c0;
317    
318     cell->darkness = 0;
319     cell->stat_hp = 0;
320 root 1.30 }
321     }
322 root 1.29 }
323    
324 root 1.56 static void
325 root 1.75 music_finished (void)
326 root 1.56 {
327     SDL_UserEvent ev;
328    
329     ev.type = SDL_USEREVENT;
330     ev.code = 0;
331     ev.data1 = 0;
332     ev.data2 = 0;
333    
334 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
335 root 1.56 }
336    
337 root 1.71 static void
338     channel_finished (int channel)
339     {
340     SDL_UserEvent ev;
341    
342     ev.type = SDL_USEREVENT;
343     ev.code = 1;
344 root 1.74 ev.data1 = (void *)(long)channel;
345 root 1.71 ev.data2 = 0;
346    
347     SDL_PushEvent ((SDL_Event *)&ev);
348     }
349    
350 root 1.113 static unsigned int
351     minpot (unsigned int n)
352     {
353     if (!n)
354     return 0;
355    
356     --n;
357    
358     n |= n >> 1;
359     n |= n >> 2;
360     n |= n >> 4;
361     n |= n >> 8;
362     n |= n >> 16;
363    
364     return n + 1;
365     }
366    
367 root 1.133 MODULE = CFPlus PACKAGE = CFPlus
368 root 1.1
369 root 1.11 PROTOTYPES: ENABLE
370    
371 root 1.5 BOOT:
372     {
373 root 1.133 HV *stash = gv_stashpv ("CFPlus", 1);
374 root 1.51 static const struct {
375     const char *name;
376     IV iv;
377     } *civ, const_iv[] = {
378     # define const_iv(name) { # name, (IV)name }
379     const_iv (SDL_ACTIVEEVENT),
380     const_iv (SDL_KEYDOWN),
381     const_iv (SDL_KEYUP),
382     const_iv (SDL_MOUSEMOTION),
383     const_iv (SDL_MOUSEBUTTONDOWN),
384     const_iv (SDL_MOUSEBUTTONUP),
385     const_iv (SDL_JOYAXISMOTION),
386     const_iv (SDL_JOYBALLMOTION),
387     const_iv (SDL_JOYHATMOTION),
388     const_iv (SDL_JOYBUTTONDOWN),
389     const_iv (SDL_JOYBUTTONUP),
390     const_iv (SDL_QUIT),
391     const_iv (SDL_SYSWMEVENT),
392     const_iv (SDL_EVENT_RESERVEDA),
393     const_iv (SDL_EVENT_RESERVEDB),
394     const_iv (SDL_VIDEORESIZE),
395     const_iv (SDL_VIDEOEXPOSE),
396     const_iv (SDL_USEREVENT),
397     const_iv (SDLK_KP0),
398     const_iv (SDLK_KP1),
399     const_iv (SDLK_KP2),
400     const_iv (SDLK_KP3),
401     const_iv (SDLK_KP4),
402     const_iv (SDLK_KP5),
403     const_iv (SDLK_KP6),
404     const_iv (SDLK_KP7),
405     const_iv (SDLK_KP8),
406     const_iv (SDLK_KP9),
407     const_iv (SDLK_KP_PERIOD),
408     const_iv (SDLK_KP_DIVIDE),
409     const_iv (SDLK_KP_MULTIPLY),
410     const_iv (SDLK_KP_MINUS),
411     const_iv (SDLK_KP_PLUS),
412     const_iv (SDLK_KP_ENTER),
413     const_iv (SDLK_KP_EQUALS),
414     const_iv (SDLK_UP),
415     const_iv (SDLK_DOWN),
416     const_iv (SDLK_RIGHT),
417     const_iv (SDLK_LEFT),
418     const_iv (SDLK_INSERT),
419     const_iv (SDLK_HOME),
420     const_iv (SDLK_END),
421     const_iv (SDLK_PAGEUP),
422     const_iv (SDLK_PAGEDOWN),
423     const_iv (SDLK_F1),
424     const_iv (SDLK_F2),
425     const_iv (SDLK_F3),
426     const_iv (SDLK_F4),
427     const_iv (SDLK_F5),
428     const_iv (SDLK_F6),
429     const_iv (SDLK_F7),
430     const_iv (SDLK_F8),
431     const_iv (SDLK_F9),
432     const_iv (SDLK_F10),
433     const_iv (SDLK_F11),
434     const_iv (SDLK_F12),
435     const_iv (SDLK_F13),
436     const_iv (SDLK_F14),
437     const_iv (SDLK_F15),
438     const_iv (SDLK_NUMLOCK),
439     const_iv (SDLK_CAPSLOCK),
440     const_iv (SDLK_SCROLLOCK),
441     const_iv (SDLK_RSHIFT),
442     const_iv (SDLK_LSHIFT),
443     const_iv (SDLK_RCTRL),
444     const_iv (SDLK_LCTRL),
445     const_iv (SDLK_RALT),
446     const_iv (SDLK_LALT),
447     const_iv (SDLK_RMETA),
448     const_iv (SDLK_LMETA),
449     const_iv (SDLK_LSUPER),
450     const_iv (SDLK_RSUPER),
451     const_iv (SDLK_MODE),
452     const_iv (SDLK_COMPOSE),
453     const_iv (SDLK_HELP),
454     const_iv (SDLK_PRINT),
455     const_iv (SDLK_SYSREQ),
456     const_iv (SDLK_BREAK),
457     const_iv (SDLK_MENU),
458     const_iv (SDLK_POWER),
459     const_iv (SDLK_EURO),
460     const_iv (SDLK_UNDO),
461     const_iv (KMOD_NONE),
462     const_iv (KMOD_LSHIFT),
463     const_iv (KMOD_RSHIFT),
464     const_iv (KMOD_LCTRL),
465     const_iv (KMOD_RCTRL),
466     const_iv (KMOD_LALT),
467     const_iv (KMOD_RALT),
468     const_iv (KMOD_LMETA),
469     const_iv (KMOD_RMETA),
470     const_iv (KMOD_NUM),
471     const_iv (KMOD_CAPS),
472     const_iv (KMOD_MODE),
473     const_iv (KMOD_CTRL),
474     const_iv (KMOD_SHIFT),
475     const_iv (KMOD_ALT),
476     const_iv (KMOD_META)
477     # undef const_iv
478     };
479    
480     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
481     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
482 root 1.79 }
483 root 1.51
484 root 1.129 int
485     in_destruct ()
486     CODE:
487     RETVAL = PL_main_cv == Nullcv;
488     OUTPUT:
489     RETVAL
490    
491 root 1.116 NV floor (NV x)
492    
493     NV ceil (NV x)
494    
495 root 1.79 void
496     pango_init ()
497     CODE:
498     {
499 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
500     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
501     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
502 root 1.5 }
503    
504 root 1.51 int
505 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
506 root 1.51
507     void
508     SDL_Quit ()
509    
510     void
511     SDL_ListModes ()
512     PPCODE:
513     {
514     SDL_Rect **m;
515    
516     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
517     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
518     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
519 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
520 root 1.51
521 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
522 root 1.115 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
523 root 1.85
524 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
525     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
526     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
527     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
528    
529     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
530 root 1.134 #if SDL_VERSION_ATLEAST(1,2,10)
531 root 1.131 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
532     SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
533 root 1.134 #endif
534 root 1.51
535 root 1.53 SDL_EnableUNICODE (1);
536     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
537    
538 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
539    
540     if (m && m != (SDL_Rect **)-1)
541     while (*m)
542     {
543     AV *av = newAV ();
544     av_push (av, newSViv ((*m)->w));
545     av_push (av, newSViv ((*m)->h));
546     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
547    
548     ++m;
549     }
550     }
551    
552 root 1.88 char *
553     SDL_GetError ()
554    
555 root 1.51 int
556     SDL_SetVideoMode (int w, int h, int fullscreen)
557     CODE:
558     RETVAL = !!SDL_SetVideoMode (
559     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
560     );
561 root 1.103 if (RETVAL)
562     {
563     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
564     # define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
565     # include "glfunc.h"
566     # undef GL_FUNC
567     }
568 root 1.51 OUTPUT:
569     RETVAL
570    
571 root 1.53 void
572 root 1.54 SDL_GL_SwapBuffers ()
573    
574 root 1.94 char *
575     SDL_GetKeyName (int sym)
576    
577 root 1.54 void
578 root 1.53 SDL_PollEvent ()
579     PPCODE:
580     {
581     SDL_Event ev;
582    
583     while (SDL_PollEvent (&ev))
584     {
585     HV *hv = newHV ();
586     hv_store (hv, "type", 4, newSViv (ev.type), 0);
587 root 1.70
588 root 1.53 switch (ev.type)
589     {
590     case SDL_KEYDOWN:
591     case SDL_KEYUP:
592     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
593     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
594     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
595     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
596     break;
597    
598     case SDL_ACTIVEEVENT:
599     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
600     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
601     break;
602    
603     case SDL_MOUSEMOTION:
604 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
605 root 1.93
606 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
607     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
608     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
609     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
610     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
611     break;
612    
613     case SDL_MOUSEBUTTONDOWN:
614     case SDL_MOUSEBUTTONUP:
615 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
616 root 1.93
617 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
618     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
619     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
620     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
621 root 1.70 break;
622 root 1.72
623     case SDL_USEREVENT:
624     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
625     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
626     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
627     break;
628 root 1.53 }
629    
630 root 1.133 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
631 root 1.53 }
632     }
633 root 1.52
634     int
635 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
636 root 1.56 POSTCALL:
637     Mix_HookMusicFinished (music_finished);
638 root 1.71 Mix_ChannelFinished (channel_finished);
639 root 1.52
640     void
641     Mix_CloseAudio ()
642    
643     int
644     Mix_AllocateChannels (int numchans = -1)
645    
646 root 1.10 void
647     lowdelay (int fd, int val = 1)
648     CODE:
649 root 1.48 #ifndef _WIN32
650 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
651 root 1.48 #endif
652 root 1.10
653 root 1.5 void
654 root 1.13 add_font (char *file)
655     CODE:
656 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
657 root 1.13
658     void
659 root 1.23 load_image_inline (SV *image_)
660     ALIAS:
661     load_image_file = 1
662     PPCODE:
663     {
664     STRLEN image_len;
665     char *image = (char *)SvPVbyte (image_, image_len);
666     SDL_Surface *surface, *surface2;
667     SDL_PixelFormat fmt;
668     SDL_RWops *rw = ix
669     ? SDL_RWFromFile (image, "r")
670     : SDL_RWFromConstMem (image, image_len);
671    
672     if (!rw)
673 root 1.41 croak ("load_image: %s", SDL_GetError ());
674 root 1.23
675     surface = IMG_Load_RW (rw, 1);
676     if (!surface)
677 root 1.41 croak ("load_image: %s", SDL_GetError ());
678 root 1.23
679     fmt.palette = NULL;
680     fmt.BitsPerPixel = 32;
681     fmt.BytesPerPixel = 4;
682 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
683 root 1.23 fmt.Rmask = 0x000000ff;
684     fmt.Gmask = 0x0000ff00;
685     fmt.Bmask = 0x00ff0000;
686     fmt.Amask = 0xff000000;
687 root 1.49 #else
688     fmt.Rmask = 0xff000000;
689     fmt.Gmask = 0x00ff0000;
690     fmt.Bmask = 0x0000ff00;
691     fmt.Amask = 0x000000ff;
692     #endif
693 root 1.23 fmt.Rloss = 0;
694     fmt.Gloss = 0;
695     fmt.Bloss = 0;
696     fmt.Aloss = 0;
697     fmt.Rshift = 0;
698     fmt.Gshift = 8;
699     fmt.Bshift = 16;
700     fmt.Ashift = 24;
701     fmt.colorkey = 0;
702     fmt.alpha = 0;
703    
704     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
705    
706 root 1.39 assert (surface2->pitch == surface2->w * 4);
707    
708 root 1.129 SDL_LockSurface (surface2);
709     EXTEND (SP, 6);
710 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
711     PUSHs (sv_2mortal (newSViv (surface2->h)));
712     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
713 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
714 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
715 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
716 root 1.129 SDL_UnlockSurface (surface2);
717 root 1.23
718     SDL_FreeSurface (surface);
719     SDL_FreeSurface (surface2);
720     }
721    
722 root 1.25 void
723 root 1.39 average (int x, int y, uint32_t *data)
724     PPCODE:
725     {
726     uint32_t r = 0, g = 0, b = 0, a = 0;
727    
728     x = y = x * y;
729    
730     while (x--)
731     {
732     uint32_t p = *data++;
733    
734     r += (p ) & 255;
735     g += (p >> 8) & 255;
736     b += (p >> 16) & 255;
737     a += (p >> 24) & 255;
738     }
739    
740     EXTEND (SP, 4);
741 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
742     PUSHs (sv_2mortal (newSViv (g / y)));
743     PUSHs (sv_2mortal (newSViv (b / y)));
744     PUSHs (sv_2mortal (newSViv (a / y)));
745 root 1.39 }
746    
747     void
748 root 1.66 error (char *message)
749     CODE:
750 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
751 root 1.66 #ifdef _WIN32
752 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
753 root 1.66 #endif
754    
755     void
756 root 1.25 fatal (char *message)
757     CODE:
758 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
759 root 1.50 #ifdef _WIN32
760 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
761 root 1.25 #endif
762 root 1.112 _exit (1);
763 root 1.111
764     void
765     _exit (int retval)
766     CODE:
767 root 1.112 _exit (retval);
768 root 1.25
769 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
770 root 1.61
771 root 1.133 CFPlus::Font
772 root 1.70 new_from_file (SV *class, char *path, int id = 0)
773 root 1.61 CODE:
774     {
775     int count;
776 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
777 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
778     FcPatternDestroy (pattern);
779     }
780     OUTPUT:
781     RETVAL
782    
783     void
784 root 1.133 DESTROY (CFPlus::Font self)
785 root 1.61 CODE:
786     pango_font_description_free (self);
787    
788     void
789 root 1.133 make_default (CFPlus::Font self)
790 root 1.61 CODE:
791     default_font = self;
792    
793 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
794 root 1.14
795 root 1.124 void
796 root 1.129 reset_glyph_cache ()
797 root 1.124 CODE:
798     tc_clear ();
799    
800 root 1.133 CFPlus::Layout
801 root 1.128 new (SV *class)
802 root 1.14 CODE:
803     New (0, RETVAL, 1, struct cf_layout);
804 root 1.76
805 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
806 root 1.76 RETVAL->r = 1.;
807     RETVAL->g = 1.;
808     RETVAL->b = 1.;
809     RETVAL->a = 1.;
810     RETVAL->base_height = MIN_FONT_HEIGHT;
811     RETVAL->font = 0;
812    
813 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
814 root 1.76 layout_update_font (RETVAL);
815 root 1.14 OUTPUT:
816     RETVAL
817    
818     void
819 root 1.133 DESTROY (CFPlus::Layout self)
820 root 1.14 CODE:
821     g_object_unref (self->pl);
822     Safefree (self);
823 root 1.13
824 root 1.8 void
825 root 1.133 set_text (CFPlus::Layout self, SV *text_)
826 root 1.35 CODE:
827     {
828     STRLEN textlen;
829     char *text = SvPVutf8 (text_, textlen);
830    
831     pango_layout_set_text (self->pl, text, textlen);
832     }
833    
834     void
835 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
836 root 1.14 CODE:
837 root 1.5 {
838     STRLEN textlen;
839     char *text = SvPVutf8 (text_, textlen);
840 root 1.14
841     pango_layout_set_markup (self->pl, text, textlen);
842     }
843    
844 root 1.121 void
845 root 1.133 set_shapes (CFPlus::Layout self, ...)
846 root 1.121 CODE:
847     {
848     PangoAttrList *attrs = 0;
849     const char *text = pango_layout_get_text (self->pl);
850     const char *pos = text;
851 root 1.122 int arg = 4;
852 root 1.121
853     while (arg < items && (pos = strstr (pos, OBJ_STR)))
854     {
855 root 1.122 PangoRectangle inkrect, rect;
856 root 1.121 PangoAttribute *attr;
857    
858 root 1.122 int x = SvIV (ST (arg - 3));
859     int y = SvIV (ST (arg - 2));
860 root 1.121 int w = SvIV (ST (arg - 1));
861 root 1.122 int h = SvIV (ST (arg ));
862 root 1.121
863 root 1.122 inkrect.x = 0;
864     inkrect.y = 0;
865     inkrect.width = 0;
866     inkrect.height = 0;
867    
868     rect.x = x * PANGO_SCALE;
869     rect.y = y * PANGO_SCALE;
870     rect.width = w * PANGO_SCALE;
871 root 1.121 rect.height = h * PANGO_SCALE;
872    
873     if (!attrs)
874     attrs = pango_layout_get_attributes (self->pl);
875    
876 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
877 root 1.121 attr->start_index = pos - text;
878     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
879     pango_attr_list_insert (attrs, attr);
880    
881 root 1.122 arg += 4;
882 root 1.121 pos += sizeof (OBJ_STR) - 1;
883     }
884    
885     if (attrs)
886     pango_layout_set_attributes (self->pl, attrs);
887     }
888    
889     void
890 root 1.133 get_shapes (CFPlus::Layout self)
891 root 1.121 PPCODE:
892     {
893     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
894    
895     do
896     {
897     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
898    
899     if (run && shape_attr_p (run))
900     {
901     PangoRectangle extents;
902     pango_layout_iter_get_run_extents (iter, 0, &extents);
903    
904 root 1.129 EXTEND (SP, 2);
905 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
906     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
907     }
908     }
909     while (pango_layout_iter_next_run (iter));
910    
911     pango_layout_iter_free (iter);
912     }
913    
914     int
915 root 1.133 has_wrapped (CFPlus::Layout self)
916 root 1.121 CODE:
917     {
918     int lines = 1;
919     const char *text = pango_layout_get_text (self->pl);
920    
921     while (*text)
922     lines += *text++ == '\n';
923    
924     RETVAL = lines < pango_layout_get_line_count (self->pl);
925     }
926     OUTPUT:
927     RETVAL
928    
929 root 1.46 SV *
930 root 1.133 get_text (CFPlus::Layout self)
931 root 1.46 CODE:
932 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
933 root 1.107 sv_utf8_decode (RETVAL);
934 root 1.46 OUTPUT:
935     RETVAL
936    
937 root 1.14 void
938 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
939 root 1.76 CODE:
940     self->r = r;
941     self->g = g;
942     self->b = b;
943     self->a = a;
944    
945     void
946 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
947 root 1.61 CODE:
948     if (self->font != font)
949     {
950     self->font = font;
951     layout_update_font (self);
952     }
953    
954     void
955 root 1.133 set_height (CFPlus::Layout self, int base_height)
956 root 1.16 CODE:
957 root 1.61 if (self->base_height != base_height)
958     {
959     self->base_height = base_height;
960     layout_update_font (self);
961     }
962 root 1.16
963     void
964 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
965 root 1.14 CODE:
966     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
967    
968     void
969 root 1.133 set_indent (CFPlus::Layout self, int indent)
970 root 1.84 CODE:
971     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
972    
973     void
974 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
975 root 1.84 CODE:
976     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
977    
978     void
979 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
980 root 1.84 CODE:
981     pango_layout_set_ellipsize (self->pl,
982     ellipsise == 1 ? PANGO_ELLIPSIZE_START
983     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
984     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
985     : PANGO_ELLIPSIZE_NONE
986     );
987    
988     void
989 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
990 root 1.84 CODE:
991     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
992    
993     void
994 root 1.133 size (CFPlus::Layout self)
995 root 1.14 PPCODE:
996     {
997     int w, h;
998    
999     layout_get_pixel_size (self, &w, &h);
1000    
1001     EXTEND (SP, 2);
1002     PUSHs (sv_2mortal (newSViv (w)));
1003     PUSHs (sv_2mortal (newSViv (h)));
1004     }
1005    
1006 root 1.17 int
1007 root 1.133 descent (CFPlus::Layout self)
1008 root 1.122 CODE:
1009     {
1010     PangoRectangle rect;
1011     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1012     pango_layout_line_get_pixel_extents (line, 0, &rect);
1013     RETVAL = PANGO_DESCENT (rect);
1014     }
1015     OUTPUT:
1016     RETVAL
1017    
1018     int
1019 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1020 root 1.17 CODE:
1021     {
1022     int index, trailing;
1023     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1024     RETVAL = index;
1025     }
1026     OUTPUT:
1027     RETVAL
1028    
1029     void
1030 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1031 root 1.17 PPCODE:
1032     {
1033     PangoRectangle strong_pos;
1034     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1035 root 1.30
1036 root 1.17 EXTEND (SP, 3);
1037     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1038     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1039     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1040     }
1041    
1042 root 1.14 void
1043 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1044 root 1.14 PPCODE:
1045 root 1.124 pango_opengl_render_layout_subpixel (
1046     self->pl,
1047     x * PANGO_SCALE, y * PANGO_SCALE,
1048 root 1.135 self->r, self->g, self->b, self->a,
1049     flags
1050 root 1.124 );
1051 root 1.11
1052 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1053 root 1.11
1054     void
1055 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1056     CODE:
1057     {
1058     int ow = SvIV (w_);
1059     int oh = SvIV (h_);
1060    
1061     if (ow && oh)
1062     {
1063     int nw = minpot (ow);
1064     int nh = minpot (oh);
1065    
1066     if (nw != ow || nh != oh)
1067     {
1068     if (SvOK (data_))
1069     {
1070     STRLEN datalen;
1071     char *data = SvPVbyte (data_, datalen);
1072     int bpp = datalen / (ow * oh);
1073     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1074    
1075     SvPOK_only (result_);
1076     SvCUR_set (result_, nw * nh * bpp);
1077    
1078     memset (SvPVX (result_), 0, nw * nh * bpp);
1079     while (oh--)
1080     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1081    
1082     sv_setsv (data_, result_);
1083     }
1084    
1085     sv_setiv (w_, nw);
1086     sv_setiv (h_, nh);
1087     }
1088     }
1089     }
1090    
1091     void
1092 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1093 root 1.12 PROTOTYPE: $$$;$$
1094 root 1.76 ALIAS:
1095     draw_quad_alpha = 1
1096     draw_quad_alpha_premultiplied = 2
1097 root 1.11 CODE:
1098     {
1099 root 1.12 HV *hv = (HV *)SvRV (self);
1100 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1101     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1102 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1103    
1104     if (items < 5)
1105     {
1106 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1107     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1108 root 1.12 }
1109    
1110 root 1.76 if (ix)
1111     {
1112     glEnable (GL_BLEND);
1113 root 1.103
1114     if (ix == 2)
1115     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1116     else
1117     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1118 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1119 root 1.103
1120 root 1.86 glEnable (GL_ALPHA_TEST);
1121     glAlphaFunc (GL_GREATER, 0.01f);
1122 root 1.76 }
1123    
1124 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1125 root 1.76
1126 root 1.12 glBegin (GL_QUADS);
1127 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1128     glTexCoord2f (0, t); glVertex2f (x , y + h);
1129     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1130     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1131 root 1.12 glEnd ();
1132 root 1.76
1133     if (ix)
1134 root 1.86 {
1135     glDisable (GL_ALPHA_TEST);
1136     glDisable (GL_BLEND);
1137     }
1138 root 1.11 }
1139 root 1.28
1140 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1141 root 1.28
1142 root 1.133 CFPlus::Map
1143 root 1.28 new (SV *class, int map_width, int map_height)
1144     CODE:
1145     New (0, RETVAL, 1, struct map);
1146 root 1.42 RETVAL->x = 0;
1147     RETVAL->y = 0;
1148     RETVAL->w = map_width;
1149     RETVAL->h = map_height;
1150     RETVAL->ox = 0;
1151     RETVAL->oy = 0;
1152 root 1.30 RETVAL->faces = 8192;
1153     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1154 root 1.42 RETVAL->texs = 8192;
1155     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1156 root 1.28 RETVAL->rows = 0;
1157     RETVAL->row = 0;
1158     OUTPUT:
1159     RETVAL
1160    
1161     void
1162 root 1.133 DESTROY (CFPlus::Map self)
1163 root 1.28 CODE:
1164     {
1165 root 1.30 map_clear (self);
1166 root 1.28 Safefree (self->face);
1167 root 1.111 Safefree (self->tex);
1168 root 1.29 Safefree (self);
1169     }
1170    
1171     void
1172 root 1.133 clear (CFPlus::Map self)
1173 root 1.30 CODE:
1174     map_clear (self);
1175    
1176     void
1177 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1178 root 1.29 CODE:
1179     {
1180 root 1.42 while (self->faces <= face)
1181 root 1.28 {
1182 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1183 root 1.29 self->faces *= 2;
1184     }
1185 root 1.28
1186 root 1.42 self->face [face] = texid;
1187     }
1188    
1189     void
1190 root 1.133 set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1191 root 1.42 CODE:
1192     {
1193     while (self->texs <= texid)
1194     {
1195     Append (maptex, self->tex, self->texs, self->texs);
1196     self->texs *= 2;
1197     }
1198    
1199 root 1.48 {
1200     maptex *tex = self->tex + texid;
1201 root 1.39
1202 root 1.48 tex->name = name;
1203     tex->w = w;
1204     tex->h = h;
1205     tex->s = s;
1206     tex->t = t;
1207     tex->r = r;
1208     tex->g = g;
1209     tex->b = b;
1210     tex->a = a;
1211     }
1212 root 1.95
1213     // somewhat hackish, but for textures that require it, it really
1214     // improves the look, and most others don't suffer.
1215     glBindTexture (GL_TEXTURE_2D, name);
1216 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1217     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1218     // use uglier nearest interpolation because linear suffers
1219     // from transparent color bleeding and ugly wrapping effects.
1220     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1221 root 1.29 }
1222    
1223 root 1.42 int
1224 root 1.133 ox (CFPlus::Map self)
1225 root 1.42 ALIAS:
1226     oy = 1
1227 root 1.101 x = 2
1228     y = 3
1229 root 1.102 w = 4
1230     h = 5
1231 root 1.42 CODE:
1232     switch (ix)
1233     {
1234     case 0: RETVAL = self->ox; break;
1235     case 1: RETVAL = self->oy; break;
1236 root 1.101 case 2: RETVAL = self->x; break;
1237     case 3: RETVAL = self->y; break;
1238 root 1.102 case 4: RETVAL = self->w; break;
1239     case 5: RETVAL = self->h; break;
1240 root 1.42 }
1241     OUTPUT:
1242     RETVAL
1243    
1244 root 1.29 void
1245 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1246 root 1.43 CODE:
1247     {
1248 root 1.44 if (dx > 0)
1249     map_blank (self, self->x, self->y, dx - 1, self->h);
1250     else if (dx < 0)
1251     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1252    
1253     if (dy > 0)
1254     map_blank (self, self->x, self->y, self->w, dy - 1);
1255     else if (dy < 0)
1256     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1257 root 1.43
1258 root 1.44 self->ox += dx; self->x += dx;
1259     self->oy += dy; self->y += dy;
1260 root 1.43
1261     while (self->y < 0)
1262     {
1263     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1264    
1265     self->rows += MAP_EXTEND_Y;
1266     self->y += MAP_EXTEND_Y;
1267     }
1268 root 1.44 }
1269 root 1.43
1270 root 1.44 void
1271 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1272 root 1.44 CODE:
1273     {
1274 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1275     uint8_t *data_end = (uint8_t *)SvEND (data_);
1276 root 1.48 mapcell *cell;
1277     int x, y, flags;
1278 root 1.43
1279 root 1.150 while (data < data_end - 1)
1280 root 1.29 {
1281 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1282 root 1.30
1283 root 1.120 x = self->x + ((flags >> 10) & 63);
1284     y = self->y + ((flags >> 4) & 63);
1285 root 1.29
1286 root 1.48 cell = map_get_cell (self, x, y);
1287 root 1.29
1288     if (flags & 15)
1289     {
1290 root 1.142 if (!cell->darkness)
1291 root 1.29 {
1292 root 1.142 cell->darkness = 256;
1293 root 1.29 cell->face [0] = 0;
1294     cell->face [1] = 0;
1295     cell->face [2] = 0;
1296     }
1297 root 1.45
1298 root 1.142 //TODO: don't trust server data to be in-range(!)
1299    
1300 root 1.141 if (flags & 8)
1301     {
1302     if (extmap)
1303     {
1304     uint8_t ext, cmd;
1305    
1306     do
1307     {
1308     ext = *data++;
1309 root 1.144 cmd = ext & 0x3f;
1310 root 1.141
1311 root 1.147 if (cmd < 4)
1312 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1313 root 1.147 else if (cmd == 5) // health
1314     {
1315     cell->stat_width = 1;
1316     cell->stat_hp = *data++;
1317     }
1318     else if (cmd == 6) // monster width
1319     cell->stat_width = *data++ + 1;
1320 root 1.153 else if (cmd == 0x47) // monster width
1321     {
1322     if (*data == 4)
1323     ; // decode player tag
1324    
1325     data += *data + 1;
1326     }
1327     else if (cmd == 8) // cell flags
1328     cell->flags = *data++;
1329 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1330     data += *data + 1;
1331 root 1.147 else
1332     data++;
1333 root 1.141 }
1334 root 1.147 while (ext & 0x80);
1335 root 1.141 }
1336     else
1337 root 1.142 cell->darkness = *data++ + 1;
1338 root 1.141 }
1339 root 1.29
1340     if (flags & 4)
1341     {
1342 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1343 root 1.29 }
1344    
1345     if (flags & 2)
1346     {
1347 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1348 root 1.29 }
1349    
1350     if (flags & 1)
1351     {
1352 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1353 root 1.29 }
1354     }
1355     else
1356 root 1.146 {
1357     cell->darkness = 0;
1358     cell->stat_hp = 0;
1359     }
1360 root 1.29 }
1361 root 1.28 }
1362    
1363 root 1.40 SV *
1364 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1365 root 1.40 CODE:
1366     {
1367 root 1.55 int x1, x;
1368     int y1, y;
1369 root 1.40 int z;
1370     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1371     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1372    
1373     SvPOK_only (map_sv);
1374     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1375    
1376 root 1.55 x0 += self->x; x1 = x0 + w;
1377     y0 += self->y; y1 = y0 + h;
1378 root 1.40
1379     for (y = y0; y < y1; y++)
1380     {
1381     maprow *row = 0 <= y && y < self->rows
1382     ? self->row + y
1383     : 0;
1384    
1385     for (x = x0; x < x1; x++)
1386     {
1387     int r = 32, g = 32, b = 32, a = 192;
1388    
1389     if (row && row->c0 <= x && x < row->c1)
1390     {
1391     mapcell *cell = row->col + (x - row->c0);
1392    
1393     for (z = 0; z <= 0; z++)
1394     {
1395 root 1.42 mapface face = cell->face [z];
1396 root 1.40
1397     if (face)
1398     {
1399 root 1.42 maptex tex = self->tex [face];
1400 root 1.40 int a0 = 255 - tex.a;
1401     int a1 = tex.a;
1402    
1403     r = (r * a0 + tex.r * a1) / 255;
1404     g = (g * a0 + tex.g * a1) / 255;
1405     b = (b * a0 + tex.b * a1) / 255;
1406     a = (a * a0 + tex.a * a1) / 255;
1407     }
1408     }
1409     }
1410    
1411     *map++ = (r )
1412     | (g << 8)
1413     | (b << 16)
1414     | (a << 24);
1415     }
1416     }
1417    
1418     RETVAL = map_sv;
1419     }
1420     OUTPUT:
1421     RETVAL
1422    
1423 root 1.30 void
1424 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1425 root 1.116 CODE:
1426 root 1.30 {
1427 root 1.48 int vx, vy;
1428     int x, y, z;
1429     int last_name;
1430     mapface face;
1431    
1432 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1433     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1434 root 1.38
1435 root 1.42 /*
1436     int vx = self->vx = self->w >= sw
1437     ? self->x + (self->w - sw) / 2
1438     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1439    
1440     int vy = self->vy = self->h >= sh
1441     ? self->y + (self->h - sh) / 2
1442     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1443     */
1444 root 1.30
1445     glColor4ub (255, 255, 255, 255);
1446    
1447 root 1.117 glEnable (GL_BLEND);
1448 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1449     glEnable (GL_TEXTURE_2D);
1450     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1451    
1452 root 1.48 glBegin (GL_QUADS);
1453 root 1.30
1454 root 1.48 last_name = 0;
1455 root 1.30
1456     for (z = 0; z < 3; z++)
1457     for (y = 0; y < sh; y++)
1458     if (0 <= y + vy && y + vy < self->rows)
1459     {
1460     maprow *row = self->row + (y + vy);
1461    
1462     for (x = 0; x < sw; x++)
1463     if (row->c0 <= x + vx && x + vx < row->c1)
1464     {
1465     mapcell *cell = row->col + (x + vx - row->c0);
1466 root 1.32
1467 root 1.48 face = cell->face [z];
1468 root 1.30
1469 root 1.145 if (face && face < self->texs)
1470 root 1.30 {
1471 root 1.42 maptex tex = self->tex [face];
1472 root 1.30 int px = (x + 1) * 32 - tex.w;
1473     int py = (y + 1) * 32 - tex.h;
1474    
1475     if (last_name != tex.name)
1476     {
1477     glEnd ();
1478 root 1.153 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1479 root 1.30 glBegin (GL_QUADS);
1480     }
1481    
1482     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1483     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1484     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1485     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1486     }
1487 root 1.153
1488     if (cell->flags && z == 2)
1489     {
1490     if (cell->flags & 1)
1491     {
1492     maptex tex = self->tex [1];
1493     int px = (x + 1) * 32 - tex.w + 2;
1494     int py = (y + 1) * 32 - tex.h - 6;
1495    
1496     glEnd ();
1497     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1498     glBegin (GL_QUADS);
1499    
1500     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1501     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1502     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1503     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1504     }
1505     }
1506 root 1.30 }
1507     }
1508    
1509     glEnd ();
1510 root 1.32
1511 root 1.34 glDisable (GL_TEXTURE_2D);
1512 root 1.152 glDisable (GL_BLEND);
1513 root 1.143
1514 root 1.145 // top layer: overlays such as the health bar
1515 root 1.143 for (y = 0; y < sh; y++)
1516     if (0 <= y + vy && y + vy < self->rows)
1517     {
1518     maprow *row = self->row + (y + vy);
1519    
1520     for (x = 0; x < sw; x++)
1521     if (row->c0 <= x + vx && x + vx < row->c1)
1522     {
1523     mapcell *cell = row->col + (x + vx - row->c0);
1524    
1525     int px = x * 32;
1526     int py = y * 32;
1527    
1528     if (cell->stat_hp)
1529     {
1530 root 1.147 int width = cell->stat_width * 32;
1531     int thick = sh / 28 + 1 + cell->stat_width;
1532 root 1.143
1533 root 1.152 glColor3ub (0, 0, 0);
1534 root 1.151 glRectf (px + 1, py - thick - 2,
1535     px + width - 1, py);
1536 root 1.147
1537 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1538 root 1.147 glRectf (px + 2,
1539 root 1.151 py - thick - 1,
1540     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1541 root 1.143 }
1542     }
1543     }
1544 root 1.116 }
1545    
1546     void
1547 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1548 root 1.117 CODE:
1549     {
1550     static float color[16][3] = {
1551 root 1.123 { 0.00F, 0.00F, 0.00F },
1552     { 1.00F, 1.00F, 1.00F },
1553     { 0.00F, 0.00F, 0.55F },
1554     { 1.00F, 0.00F, 0.00F },
1555    
1556     { 1.00F, 0.54F, 0.00F },
1557     { 0.11F, 0.56F, 1.00F },
1558     { 0.93F, 0.46F, 0.00F },
1559     { 0.18F, 0.54F, 0.34F },
1560    
1561     { 0.56F, 0.73F, 0.56F },
1562     { 0.80F, 0.80F, 0.80F },
1563     { 0.55F, 0.41F, 0.13F },
1564     { 0.99F, 0.77F, 0.26F },
1565    
1566     { 0.74F, 0.65F, 0.41F },
1567    
1568     { 0.00F, 1.00F, 1.00F },
1569     { 1.00F, 0.00F, 1.00F },
1570     { 1.00F, 1.00F, 0.00F },
1571 root 1.117 };
1572    
1573     int x, y;
1574    
1575     glEnable (GL_TEXTURE_2D);
1576     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1577     glEnable (GL_BLEND);
1578     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1579     glBegin (GL_QUADS);
1580    
1581     for (y = 0; y < h; y++)
1582     for (x = 0; x < w; x++)
1583     {
1584     unsigned char m = data [x + y * w];
1585    
1586 root 1.118 if (m)
1587     {
1588     float *c = color [m & 15];
1589    
1590     float tx1 = m & 0x40 ? 0.5 : 0.;
1591     float tx2 = tx1 + 0.5;
1592    
1593     glColor4f (c[0], c[1], c[2], 0.75);
1594     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1595     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1596     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1597     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1598     }
1599 root 1.117 }
1600    
1601     glEnd ();
1602     glDisable (GL_BLEND);
1603     glDisable (GL_TEXTURE_2D);
1604     }
1605    
1606     void
1607 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1608 root 1.116 PPCODE:
1609     {
1610     int vx, vy;
1611     int x, y;
1612     int sw4 = (sw + 3) & ~3;
1613     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1614     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1615    
1616     memset (darkness, 255, sw4 * sh);
1617     SvPOK_only (darkness_sv);
1618     SvCUR_set (darkness_sv, sw4 * sh);
1619    
1620     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1621     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1622    
1623     for (y = 0; y < sh; y++)
1624     if (0 <= y + vy && y + vy < self->rows)
1625     {
1626     maprow *row = self->row + (y + vy);
1627    
1628     for (x = 0; x < sw; x++)
1629     if (row->c0 <= x + vx && x + vx < row->c1)
1630     {
1631     mapcell *cell = row->col + (x + vx - row->c0);
1632    
1633 root 1.142 darkness[y * sw4 + x] = cell->darkness
1634 root 1.143 ? 255 - (cell->darkness - 1)
1635 root 1.142 : 255 - FOW_DARKNESS;
1636 root 1.116 }
1637     }
1638 root 1.34
1639 root 1.32 EXTEND (SP, 3);
1640     PUSHs (sv_2mortal (newSViv (sw4)));
1641     PUSHs (sv_2mortal (newSViv (sh)));
1642     PUSHs (darkness_sv);
1643 root 1.30 }
1644    
1645 root 1.42 SV *
1646 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1647 root 1.42 CODE:
1648     {
1649     int x, y, x1, y1;
1650     SV *data_sv = newSV (w * h * 7 + 5);
1651     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1652    
1653     *data++ = 0; /* version 0 format */
1654     *data++ = w >> 8; *data++ = w;
1655     *data++ = h >> 8; *data++ = h;
1656    
1657     // we need to do this 'cause we don't keep an absolute coord system for rows
1658 root 1.55 // TODO: treat rows as we treat columns
1659 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1660     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1661    
1662     x0 += self->x - self->ox;
1663     y0 += self->y - self->oy;
1664    
1665     x1 = x0 + w;
1666     y1 = y0 + h;
1667    
1668     for (y = y0; y < y1; y++)
1669     {
1670     maprow *row = 0 <= y && y < self->rows
1671     ? self->row + y
1672     : 0;
1673    
1674     for (x = x0; x < x1; x++)
1675     {
1676     if (row && row->c0 <= x && x < row->c1)
1677     {
1678     mapcell *cell = row->col + (x - row->c0);
1679     uint8_t flags = 0;
1680    
1681     if (cell->face [0]) flags |= 1;
1682     if (cell->face [1]) flags |= 2;
1683     if (cell->face [2]) flags |= 4;
1684    
1685     *data++ = flags;
1686    
1687     if (flags & 1)
1688     {
1689     *data++ = cell->face [0] >> 8;
1690     *data++ = cell->face [0];
1691     }
1692    
1693     if (flags & 2)
1694     {
1695     *data++ = cell->face [1] >> 8;
1696     *data++ = cell->face [1];
1697     }
1698    
1699     if (flags & 4)
1700     {
1701     *data++ = cell->face [2] >> 8;
1702     *data++ = cell->face [2];
1703     }
1704     }
1705     else
1706     *data++ = 0;
1707     }
1708     }
1709    
1710     SvPOK_only (data_sv);
1711     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1712     RETVAL = data_sv;
1713     }
1714     OUTPUT:
1715     RETVAL
1716    
1717     void
1718 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1719 root 1.42 PPCODE:
1720     {
1721     int x, y, z;
1722 root 1.48 int w, h;
1723 root 1.42 int x1, y1;
1724    
1725     if (*data++ != 0)
1726     return; /* version mismatch */
1727    
1728 root 1.48 w = *data++ << 8; w |= *data++;
1729     h = *data++ << 8; h |= *data++;
1730 root 1.42
1731     // we need to do this 'cause we don't keep an absolute coord system for rows
1732 root 1.55 // TODO: treat rows as we treat columns
1733 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1734     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1735    
1736     x0 += self->x - self->ox;
1737     y0 += self->y - self->oy;
1738    
1739     x1 = x0 + w;
1740     y1 = y0 + h;
1741    
1742     for (y = y0; y < y1; y++)
1743     {
1744     maprow *row = map_get_row (self, y);
1745    
1746     for (x = x0; x < x1; x++)
1747     {
1748     uint8_t flags = *data++;
1749    
1750     if (flags)
1751     {
1752     mapface face[3] = { 0, 0, 0 };
1753    
1754     mapcell *cell = row_get_cell (row, x);
1755    
1756     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1757     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1758     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1759    
1760 root 1.143 if (cell->darkness == 0)
1761 root 1.42 {
1762 root 1.142 cell->darkness = 0;
1763 root 1.42
1764     for (z = 0; z <= 2; z++)
1765     {
1766     cell->face[z] = face[z];
1767    
1768     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1769     XPUSHs (sv_2mortal (newSViv (face[z])));
1770     }
1771     }
1772     }
1773     }
1774     }
1775     }
1776    
1777 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1778 root 1.52
1779 root 1.133 CFPlus::MixChunk
1780 root 1.52 new_from_file (SV *class, char *path)
1781     CODE:
1782     RETVAL = Mix_LoadWAV (path);
1783     OUTPUT:
1784     RETVAL
1785    
1786     void
1787 root 1.133 DESTROY (CFPlus::MixChunk self)
1788 root 1.52 CODE:
1789     Mix_FreeChunk (self);
1790    
1791     int
1792 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1793 root 1.52 CODE:
1794     RETVAL = Mix_VolumeChunk (self, volume);
1795     OUTPUT:
1796     RETVAL
1797    
1798     int
1799 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1800 root 1.52 CODE:
1801     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1802     OUTPUT:
1803     RETVAL
1804    
1805 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1806 root 1.52
1807     int
1808     volume (int volume = -1)
1809     CODE:
1810     RETVAL = Mix_VolumeMusic (volume);
1811     OUTPUT:
1812     RETVAL
1813    
1814 root 1.133 CFPlus::MixMusic
1815 root 1.52 new_from_file (SV *class, char *path)
1816     CODE:
1817     RETVAL = Mix_LoadMUS (path);
1818     OUTPUT:
1819     RETVAL
1820    
1821     void
1822 root 1.133 DESTROY (CFPlus::MixMusic self)
1823 root 1.52 CODE:
1824     Mix_FreeMusic (self);
1825    
1826     int
1827 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1828 root 1.52 CODE:
1829     RETVAL = Mix_PlayMusic (self, loops);
1830     OUTPUT:
1831     RETVAL
1832    
1833 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1834 root 1.54
1835     BOOT:
1836     {
1837 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1838 root 1.54 static const struct {
1839     const char *name;
1840     IV iv;
1841     } *civ, const_iv[] = {
1842     # define const_iv(name) { # name, (IV)name }
1843     const_iv (GL_COLOR_MATERIAL),
1844     const_iv (GL_SMOOTH),
1845     const_iv (GL_FLAT),
1846 root 1.69 const_iv (GL_DITHER),
1847 root 1.54 const_iv (GL_BLEND),
1848 root 1.89 const_iv (GL_CULL_FACE),
1849 root 1.69 const_iv (GL_SCISSOR_TEST),
1850 root 1.89 const_iv (GL_DEPTH_TEST),
1851     const_iv (GL_ALPHA_TEST),
1852     const_iv (GL_NORMALIZE),
1853     const_iv (GL_RESCALE_NORMAL),
1854 root 1.119 const_iv (GL_FRONT),
1855     const_iv (GL_BACK),
1856 root 1.54 const_iv (GL_AND),
1857 root 1.67 const_iv (GL_ONE),
1858     const_iv (GL_ZERO),
1859 root 1.54 const_iv (GL_SRC_ALPHA),
1860 root 1.104 const_iv (GL_DST_ALPHA),
1861 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1862 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1863 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1864 root 1.54 const_iv (GL_RGB),
1865     const_iv (GL_RGBA),
1866 root 1.115 const_iv (GL_RGBA4),
1867     const_iv (GL_RGBA8),
1868     const_iv (GL_RGB5_A1),
1869 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1870 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1871     const_iv (GL_UNSIGNED_INT),
1872 root 1.54 const_iv (GL_ALPHA),
1873 root 1.86 const_iv (GL_INTENSITY),
1874 root 1.76 const_iv (GL_LUMINANCE),
1875 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1876 root 1.54 const_iv (GL_FLOAT),
1877     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1878     const_iv (GL_COMPILE),
1879     const_iv (GL_TEXTURE_1D),
1880     const_iv (GL_TEXTURE_2D),
1881     const_iv (GL_TEXTURE_ENV),
1882     const_iv (GL_TEXTURE_MAG_FILTER),
1883     const_iv (GL_TEXTURE_MIN_FILTER),
1884     const_iv (GL_TEXTURE_ENV_MODE),
1885     const_iv (GL_TEXTURE_WRAP_S),
1886     const_iv (GL_TEXTURE_WRAP_T),
1887 root 1.98 const_iv (GL_REPEAT),
1888 root 1.54 const_iv (GL_CLAMP),
1889 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1890 root 1.54 const_iv (GL_NEAREST),
1891     const_iv (GL_LINEAR),
1892 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1893     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1894     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1895     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1896     const_iv (GL_GENERATE_MIPMAP),
1897 root 1.54 const_iv (GL_MODULATE),
1898 root 1.69 const_iv (GL_DECAL),
1899 root 1.54 const_iv (GL_REPLACE),
1900 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1901 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1902     const_iv (GL_PROJECTION),
1903     const_iv (GL_MODELVIEW),
1904     const_iv (GL_COLOR_LOGIC_OP),
1905 root 1.69 const_iv (GL_SEPARABLE_2D),
1906 root 1.54 const_iv (GL_CONVOLUTION_2D),
1907     const_iv (GL_CONVOLUTION_BORDER_MODE),
1908     const_iv (GL_CONSTANT_BORDER),
1909     const_iv (GL_LINES),
1910 root 1.138 const_iv (GL_LINE_STRIP),
1911 root 1.89 const_iv (GL_LINE_LOOP),
1912 root 1.54 const_iv (GL_QUADS),
1913 root 1.89 const_iv (GL_QUAD_STRIP),
1914     const_iv (GL_TRIANGLES),
1915     const_iv (GL_TRIANGLE_STRIP),
1916     const_iv (GL_TRIANGLE_FAN),
1917 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1918     const_iv (GL_FASTEST),
1919 root 1.89 const_iv (GL_V2F),
1920     const_iv (GL_V3F),
1921     const_iv (GL_T2F_V3F),
1922     const_iv (GL_T2F_N3F_V3F),
1923 root 1.54 # undef const_iv
1924     };
1925    
1926     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1927     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1928     }
1929    
1930 root 1.97 char *
1931     gl_vendor ()
1932     CODE:
1933     RETVAL = (char *)glGetString (GL_VENDOR);
1934     OUTPUT:
1935     RETVAL
1936    
1937     char *
1938     gl_version ()
1939     CODE:
1940     RETVAL = (char *)glGetString (GL_VERSION);
1941     OUTPUT:
1942     RETVAL
1943    
1944     char *
1945     gl_extensions ()
1946     CODE:
1947     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1948     OUTPUT:
1949     RETVAL
1950    
1951 root 1.54 int glGetError ()
1952    
1953 root 1.114 void glFinish ()
1954    
1955 root 1.54 void glClear (int mask)
1956    
1957     void glClearColor (float r, float g, float b, float a = 1.0)
1958     PROTOTYPE: @
1959    
1960     void glEnable (int cap)
1961    
1962     void glDisable (int cap)
1963    
1964     void glShadeModel (int mode)
1965    
1966     void glHint (int target, int mode)
1967    
1968     void glBlendFunc (int sfactor, int dfactor)
1969    
1970 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1971     CODE:
1972     gl_BlendFuncSeparate (sa, da, saa, daa);
1973    
1974 root 1.89 void glDepthMask (int flag)
1975    
1976 root 1.54 void glLogicOp (int opcode)
1977    
1978 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1979    
1980 root 1.54 void glMatrixMode (int mode)
1981    
1982     void glPushMatrix ()
1983    
1984     void glPopMatrix ()
1985    
1986     void glLoadIdentity ()
1987    
1988 root 1.119 void glDrawBuffer (int buffer)
1989    
1990     void glReadBuffer (int buffer)
1991    
1992 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1993     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1994    
1995     # near_ and far_ are due to microsofts buggy "c" compiler
1996 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1997 root 1.54
1998     void glViewport (int x, int y, int width, int height)
1999    
2000 root 1.69 void glScissor (int x, int y, int width, int height)
2001    
2002 root 1.54 void glTranslate (float x, float y, float z = 0.)
2003     CODE:
2004     glTranslatef (x, y, z);
2005    
2006 root 1.62 void glScale (float x, float y, float z = 1.)
2007 root 1.54 CODE:
2008     glScalef (x, y, z);
2009    
2010     void glRotate (float angle, float x, float y, float z)
2011     CODE:
2012     glRotatef (angle, x, y, z);
2013    
2014     void glBegin (int mode)
2015    
2016     void glEnd ()
2017    
2018     void glColor (float r, float g, float b, float a = 1.0)
2019     PROTOTYPE: @
2020 root 1.103 ALIAS:
2021     glColor_premultiply = 1
2022 root 1.54 CODE:
2023 root 1.103 if (ix)
2024     {
2025     r *= a;
2026     g *= a;
2027     b *= a;
2028     }
2029 root 1.90 // microsoft visual "c" rounds instead of truncating...
2030 root 1.130 glColor4f (r, g, b, a);
2031 root 1.54
2032 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
2033    
2034     void glDrawElements (int mode, int count, int type, char *indices)
2035    
2036     # 1.2 void glDrawRangeElements (int mode, int start, int end
2037    
2038 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2039     CODE:
2040     glRasterPos3f (0, 0, z);
2041     glBitmap (0, 0, 0, 0, x, y, 0);
2042    
2043 root 1.54 void glVertex (float x, float y, float z = 0.)
2044     CODE:
2045     glVertex3f (x, y, z);
2046    
2047     void glTexCoord (float s, float t)
2048     CODE:
2049     glTexCoord2f (s, t);
2050    
2051     void glTexEnv (int target, int pname, float param)
2052     CODE:
2053     glTexEnvf (target, pname, param);
2054    
2055     void glTexParameter (int target, int pname, float param)
2056     CODE:
2057     glTexParameterf (target, pname, param);
2058    
2059     void glBindTexture (int target, int name)
2060    
2061     void glConvolutionParameter (int target, int pname, float params)
2062     CODE:
2063 root 1.103 if (gl.ConvolutionParameterf)
2064     gl.ConvolutionParameterf (target, pname, params);
2065 root 1.54
2066     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2067 root 1.64 CODE:
2068 root 1.103 if (gl.ConvolutionFilter2D)
2069     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2070 root 1.54
2071 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2072     CODE:
2073 root 1.103 if (gl.SeparableFilter2D)
2074     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2075 root 1.69
2076 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2077    
2078     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2079    
2080 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2081 root 1.68
2082     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2083    
2084 root 1.54 int glGenTexture ()
2085     CODE:
2086     {
2087     GLuint name;
2088     glGenTextures (1, &name);
2089     RETVAL = name;
2090     }
2091     OUTPUT:
2092     RETVAL
2093    
2094     void glDeleteTexture (int name)
2095     CODE:
2096     {
2097     GLuint name_ = name;
2098     glDeleteTextures (1, &name_);
2099     }
2100    
2101     int glGenList ()
2102     CODE:
2103     RETVAL = glGenLists (1);
2104     OUTPUT:
2105     RETVAL
2106    
2107     void glDeleteList (int list)
2108     CODE:
2109     glDeleteLists (list, 1);
2110    
2111     void glNewList (int list, int mode = GL_COMPILE)
2112    
2113     void glEndList ()
2114    
2115     void glCallList (int list)
2116