ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.145
Committed: Fri Aug 18 03:19:58 2006 UTC (17 years, 8 months ago) by root
Branch: MAIN
Changes since 1.144: +7 -7 lines
Log Message:
*** empty log message ***

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