ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.160
Committed: Mon Oct 9 01:06:36 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.159: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

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