ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.143
Committed: Fri Aug 18 02:23:39 2006 UTC (17 years, 8 months ago) by root
Branch: MAIN
Changes since 1.142: +30 -2 lines
Log Message:
support health bar display

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     cmd = ext & 0x7f;
1306    
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.141 }
1312     while (cmd & 0x80);
1313     }
1314     else
1315 root 1.142 cell->darkness = *data++ + 1;
1316 root 1.141 }
1317 root 1.29
1318     if (flags & 4)
1319     {
1320 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1321 root 1.29 }
1322    
1323     if (flags & 2)
1324     {
1325 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1326 root 1.29 }
1327    
1328     if (flags & 1)
1329     {
1330 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1331 root 1.29 }
1332     }
1333     else
1334 root 1.142 cell->darkness = 0;
1335 root 1.29 }
1336 root 1.28 }
1337    
1338 root 1.40 SV *
1339 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1340 root 1.40 CODE:
1341     {
1342 root 1.55 int x1, x;
1343     int y1, y;
1344 root 1.40 int z;
1345     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1346     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1347    
1348     SvPOK_only (map_sv);
1349     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1350    
1351 root 1.55 x0 += self->x; x1 = x0 + w;
1352     y0 += self->y; y1 = y0 + h;
1353 root 1.40
1354     for (y = y0; y < y1; y++)
1355     {
1356     maprow *row = 0 <= y && y < self->rows
1357     ? self->row + y
1358     : 0;
1359    
1360     for (x = x0; x < x1; x++)
1361     {
1362     int r = 32, g = 32, b = 32, a = 192;
1363    
1364     if (row && row->c0 <= x && x < row->c1)
1365     {
1366     mapcell *cell = row->col + (x - row->c0);
1367    
1368     for (z = 0; z <= 0; z++)
1369     {
1370 root 1.42 mapface face = cell->face [z];
1371 root 1.40
1372     if (face)
1373     {
1374 root 1.42 maptex tex = self->tex [face];
1375 root 1.40 int a0 = 255 - tex.a;
1376     int a1 = tex.a;
1377    
1378     r = (r * a0 + tex.r * a1) / 255;
1379     g = (g * a0 + tex.g * a1) / 255;
1380     b = (b * a0 + tex.b * a1) / 255;
1381     a = (a * a0 + tex.a * a1) / 255;
1382     }
1383     }
1384     }
1385    
1386     *map++ = (r )
1387     | (g << 8)
1388     | (b << 16)
1389     | (a << 24);
1390     }
1391     }
1392    
1393     RETVAL = map_sv;
1394     }
1395     OUTPUT:
1396     RETVAL
1397    
1398 root 1.30 void
1399 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1400 root 1.116 CODE:
1401 root 1.30 {
1402 root 1.48 int vx, vy;
1403     int x, y, z;
1404     int last_name;
1405     mapface face;
1406    
1407 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1408     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1409 root 1.38
1410 root 1.42 /*
1411     int vx = self->vx = self->w >= sw
1412     ? self->x + (self->w - sw) / 2
1413     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1414    
1415     int vy = self->vy = self->h >= sh
1416     ? self->y + (self->h - sh) / 2
1417     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1418     */
1419 root 1.30
1420     glColor4ub (255, 255, 255, 255);
1421    
1422 root 1.117 glEnable (GL_BLEND);
1423 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1424     glEnable (GL_TEXTURE_2D);
1425     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1426    
1427 root 1.48 glBegin (GL_QUADS);
1428 root 1.30
1429 root 1.48 last_name = 0;
1430 root 1.30
1431     for (z = 0; z < 3; z++)
1432     for (y = 0; y < sh; y++)
1433     if (0 <= y + vy && y + vy < self->rows)
1434     {
1435     maprow *row = self->row + (y + vy);
1436    
1437     for (x = 0; x < sw; x++)
1438     if (row->c0 <= x + vx && x + vx < row->c1)
1439     {
1440     mapcell *cell = row->col + (x + vx - row->c0);
1441 root 1.32
1442 root 1.48 face = cell->face [z];
1443 root 1.30
1444     if (face)
1445     {
1446 root 1.42 maptex tex = self->tex [face];
1447 root 1.30
1448     int px = (x + 1) * 32 - tex.w;
1449     int py = (y + 1) * 32 - tex.h;
1450    
1451     if (last_name != tex.name)
1452     {
1453     glEnd ();
1454     last_name = tex.name;
1455     glBindTexture (GL_TEXTURE_2D, last_name);
1456     glBegin (GL_QUADS);
1457     }
1458    
1459     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1460     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1461     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1462     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1463     }
1464     }
1465     }
1466    
1467     glEnd ();
1468 root 1.32
1469 root 1.34 glDisable (GL_TEXTURE_2D);
1470     glDisable (GL_BLEND);
1471 root 1.143
1472     for (y = 0; y < sh; y++)
1473     if (0 <= y + vy && y + vy < self->rows)
1474     {
1475     maprow *row = self->row + (y + vy);
1476    
1477     for (x = 0; x < sw; x++)
1478     if (row->c0 <= x + vx && x + vx < row->c1)
1479     {
1480     mapcell *cell = row->col + (x + vx - row->c0);
1481    
1482     int px = x * 32;
1483     int py = y * 32;
1484    
1485     if (cell->stat_hp)
1486     {
1487     glColor3ub (0, 0, 0);
1488     glRectf (px + 1, py + 1, px + 31, py + 4);
1489    
1490     glColor3ub (0, 255, 0);
1491     glBegin (GL_LINES);
1492     glVertex2f (px + 2, py + 2.5f);
1493     glVertex2f (px + 29.f - cell->stat_hp * (28.f / 255.f), py + 2.5f);
1494     glEnd ();
1495     }
1496     }
1497     }
1498 root 1.116 }
1499    
1500     void
1501 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1502 root 1.117 CODE:
1503     {
1504     static float color[16][3] = {
1505 root 1.123 { 0.00F, 0.00F, 0.00F },
1506     { 1.00F, 1.00F, 1.00F },
1507     { 0.00F, 0.00F, 0.55F },
1508     { 1.00F, 0.00F, 0.00F },
1509    
1510     { 1.00F, 0.54F, 0.00F },
1511     { 0.11F, 0.56F, 1.00F },
1512     { 0.93F, 0.46F, 0.00F },
1513     { 0.18F, 0.54F, 0.34F },
1514    
1515     { 0.56F, 0.73F, 0.56F },
1516     { 0.80F, 0.80F, 0.80F },
1517     { 0.55F, 0.41F, 0.13F },
1518     { 0.99F, 0.77F, 0.26F },
1519    
1520     { 0.74F, 0.65F, 0.41F },
1521    
1522     { 0.00F, 1.00F, 1.00F },
1523     { 1.00F, 0.00F, 1.00F },
1524     { 1.00F, 1.00F, 0.00F },
1525 root 1.117 };
1526    
1527     int x, y;
1528    
1529     glEnable (GL_TEXTURE_2D);
1530     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1531     glEnable (GL_BLEND);
1532     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1533     glBegin (GL_QUADS);
1534    
1535     for (y = 0; y < h; y++)
1536     for (x = 0; x < w; x++)
1537     {
1538     unsigned char m = data [x + y * w];
1539    
1540 root 1.118 if (m)
1541     {
1542     float *c = color [m & 15];
1543    
1544     float tx1 = m & 0x40 ? 0.5 : 0.;
1545     float tx2 = tx1 + 0.5;
1546    
1547     glColor4f (c[0], c[1], c[2], 0.75);
1548     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1549     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1550     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1551     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1552     }
1553 root 1.117 }
1554    
1555     glEnd ();
1556     glDisable (GL_BLEND);
1557     glDisable (GL_TEXTURE_2D);
1558     }
1559    
1560     void
1561 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1562 root 1.116 PPCODE:
1563     {
1564     int vx, vy;
1565     int x, y;
1566     int sw4 = (sw + 3) & ~3;
1567     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1568     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1569    
1570     memset (darkness, 255, sw4 * sh);
1571     SvPOK_only (darkness_sv);
1572     SvCUR_set (darkness_sv, sw4 * sh);
1573    
1574     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1575     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1576    
1577     for (y = 0; y < sh; y++)
1578     if (0 <= y + vy && y + vy < self->rows)
1579     {
1580     maprow *row = self->row + (y + vy);
1581    
1582     for (x = 0; x < sw; x++)
1583     if (row->c0 <= x + vx && x + vx < row->c1)
1584     {
1585     mapcell *cell = row->col + (x + vx - row->c0);
1586    
1587 root 1.142 darkness[y * sw4 + x] = cell->darkness
1588 root 1.143 ? 255 - (cell->darkness - 1)
1589 root 1.142 : 255 - FOW_DARKNESS;
1590 root 1.116 }
1591     }
1592 root 1.34
1593 root 1.32 EXTEND (SP, 3);
1594     PUSHs (sv_2mortal (newSViv (sw4)));
1595     PUSHs (sv_2mortal (newSViv (sh)));
1596     PUSHs (darkness_sv);
1597 root 1.30 }
1598    
1599 root 1.42 SV *
1600 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1601 root 1.42 CODE:
1602     {
1603     int x, y, x1, y1;
1604     SV *data_sv = newSV (w * h * 7 + 5);
1605     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1606    
1607     *data++ = 0; /* version 0 format */
1608     *data++ = w >> 8; *data++ = w;
1609     *data++ = h >> 8; *data++ = h;
1610    
1611     // we need to do this 'cause we don't keep an absolute coord system for rows
1612 root 1.55 // TODO: treat rows as we treat columns
1613 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1614     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1615    
1616     x0 += self->x - self->ox;
1617     y0 += self->y - self->oy;
1618    
1619     x1 = x0 + w;
1620     y1 = y0 + h;
1621    
1622     for (y = y0; y < y1; y++)
1623     {
1624     maprow *row = 0 <= y && y < self->rows
1625     ? self->row + y
1626     : 0;
1627    
1628     for (x = x0; x < x1; x++)
1629     {
1630     if (row && row->c0 <= x && x < row->c1)
1631     {
1632     mapcell *cell = row->col + (x - row->c0);
1633     uint8_t flags = 0;
1634    
1635     if (cell->face [0]) flags |= 1;
1636     if (cell->face [1]) flags |= 2;
1637     if (cell->face [2]) flags |= 4;
1638    
1639     *data++ = flags;
1640    
1641     if (flags & 1)
1642     {
1643     *data++ = cell->face [0] >> 8;
1644     *data++ = cell->face [0];
1645     }
1646    
1647     if (flags & 2)
1648     {
1649     *data++ = cell->face [1] >> 8;
1650     *data++ = cell->face [1];
1651     }
1652    
1653     if (flags & 4)
1654     {
1655     *data++ = cell->face [2] >> 8;
1656     *data++ = cell->face [2];
1657     }
1658     }
1659     else
1660     *data++ = 0;
1661     }
1662     }
1663    
1664     SvPOK_only (data_sv);
1665     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1666     RETVAL = data_sv;
1667     }
1668     OUTPUT:
1669     RETVAL
1670    
1671     void
1672 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1673 root 1.42 PPCODE:
1674     {
1675     int x, y, z;
1676 root 1.48 int w, h;
1677 root 1.42 int x1, y1;
1678    
1679     if (*data++ != 0)
1680     return; /* version mismatch */
1681    
1682 root 1.48 w = *data++ << 8; w |= *data++;
1683     h = *data++ << 8; h |= *data++;
1684 root 1.42
1685     // we need to do this 'cause we don't keep an absolute coord system for rows
1686 root 1.55 // TODO: treat rows as we treat columns
1687 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1688     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1689    
1690     x0 += self->x - self->ox;
1691     y0 += self->y - self->oy;
1692    
1693     x1 = x0 + w;
1694     y1 = y0 + h;
1695    
1696     for (y = y0; y < y1; y++)
1697     {
1698     maprow *row = map_get_row (self, y);
1699    
1700     for (x = x0; x < x1; x++)
1701     {
1702     uint8_t flags = *data++;
1703    
1704     if (flags)
1705     {
1706     mapface face[3] = { 0, 0, 0 };
1707    
1708     mapcell *cell = row_get_cell (row, x);
1709    
1710     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1711     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1712     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1713    
1714 root 1.143 if (cell->darkness == 0)
1715 root 1.42 {
1716 root 1.142 cell->darkness = 0;
1717 root 1.42
1718     for (z = 0; z <= 2; z++)
1719     {
1720     cell->face[z] = face[z];
1721    
1722     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1723     XPUSHs (sv_2mortal (newSViv (face[z])));
1724     }
1725     }
1726     }
1727     }
1728     }
1729     }
1730    
1731 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1732 root 1.52
1733 root 1.133 CFPlus::MixChunk
1734 root 1.52 new_from_file (SV *class, char *path)
1735     CODE:
1736     RETVAL = Mix_LoadWAV (path);
1737     OUTPUT:
1738     RETVAL
1739    
1740     void
1741 root 1.133 DESTROY (CFPlus::MixChunk self)
1742 root 1.52 CODE:
1743     Mix_FreeChunk (self);
1744    
1745     int
1746 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1747 root 1.52 CODE:
1748     RETVAL = Mix_VolumeChunk (self, volume);
1749     OUTPUT:
1750     RETVAL
1751    
1752     int
1753 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1754 root 1.52 CODE:
1755     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1756     OUTPUT:
1757     RETVAL
1758    
1759 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1760 root 1.52
1761     int
1762     volume (int volume = -1)
1763     CODE:
1764     RETVAL = Mix_VolumeMusic (volume);
1765     OUTPUT:
1766     RETVAL
1767    
1768 root 1.133 CFPlus::MixMusic
1769 root 1.52 new_from_file (SV *class, char *path)
1770     CODE:
1771     RETVAL = Mix_LoadMUS (path);
1772     OUTPUT:
1773     RETVAL
1774    
1775     void
1776 root 1.133 DESTROY (CFPlus::MixMusic self)
1777 root 1.52 CODE:
1778     Mix_FreeMusic (self);
1779    
1780     int
1781 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1782 root 1.52 CODE:
1783     RETVAL = Mix_PlayMusic (self, loops);
1784     OUTPUT:
1785     RETVAL
1786    
1787 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1788 root 1.54
1789     BOOT:
1790     {
1791 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1792 root 1.54 static const struct {
1793     const char *name;
1794     IV iv;
1795     } *civ, const_iv[] = {
1796     # define const_iv(name) { # name, (IV)name }
1797     const_iv (GL_COLOR_MATERIAL),
1798     const_iv (GL_SMOOTH),
1799     const_iv (GL_FLAT),
1800 root 1.69 const_iv (GL_DITHER),
1801 root 1.54 const_iv (GL_BLEND),
1802 root 1.89 const_iv (GL_CULL_FACE),
1803 root 1.69 const_iv (GL_SCISSOR_TEST),
1804 root 1.89 const_iv (GL_DEPTH_TEST),
1805     const_iv (GL_ALPHA_TEST),
1806     const_iv (GL_NORMALIZE),
1807     const_iv (GL_RESCALE_NORMAL),
1808 root 1.119 const_iv (GL_FRONT),
1809     const_iv (GL_BACK),
1810 root 1.54 const_iv (GL_AND),
1811 root 1.67 const_iv (GL_ONE),
1812     const_iv (GL_ZERO),
1813 root 1.54 const_iv (GL_SRC_ALPHA),
1814 root 1.104 const_iv (GL_DST_ALPHA),
1815 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1816 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1817 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1818 root 1.54 const_iv (GL_RGB),
1819     const_iv (GL_RGBA),
1820 root 1.115 const_iv (GL_RGBA4),
1821     const_iv (GL_RGBA8),
1822     const_iv (GL_RGB5_A1),
1823 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1824 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1825     const_iv (GL_UNSIGNED_INT),
1826 root 1.54 const_iv (GL_ALPHA),
1827 root 1.86 const_iv (GL_INTENSITY),
1828 root 1.76 const_iv (GL_LUMINANCE),
1829 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1830 root 1.54 const_iv (GL_FLOAT),
1831     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1832     const_iv (GL_COMPILE),
1833     const_iv (GL_TEXTURE_1D),
1834     const_iv (GL_TEXTURE_2D),
1835     const_iv (GL_TEXTURE_ENV),
1836     const_iv (GL_TEXTURE_MAG_FILTER),
1837     const_iv (GL_TEXTURE_MIN_FILTER),
1838     const_iv (GL_TEXTURE_ENV_MODE),
1839     const_iv (GL_TEXTURE_WRAP_S),
1840     const_iv (GL_TEXTURE_WRAP_T),
1841 root 1.98 const_iv (GL_REPEAT),
1842 root 1.54 const_iv (GL_CLAMP),
1843 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1844 root 1.54 const_iv (GL_NEAREST),
1845     const_iv (GL_LINEAR),
1846 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1847     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1848     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1849     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1850     const_iv (GL_GENERATE_MIPMAP),
1851 root 1.54 const_iv (GL_MODULATE),
1852 root 1.69 const_iv (GL_DECAL),
1853 root 1.54 const_iv (GL_REPLACE),
1854 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1855 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1856     const_iv (GL_PROJECTION),
1857     const_iv (GL_MODELVIEW),
1858     const_iv (GL_COLOR_LOGIC_OP),
1859 root 1.69 const_iv (GL_SEPARABLE_2D),
1860 root 1.54 const_iv (GL_CONVOLUTION_2D),
1861     const_iv (GL_CONVOLUTION_BORDER_MODE),
1862     const_iv (GL_CONSTANT_BORDER),
1863     const_iv (GL_LINES),
1864 root 1.138 const_iv (GL_LINE_STRIP),
1865 root 1.89 const_iv (GL_LINE_LOOP),
1866 root 1.54 const_iv (GL_QUADS),
1867 root 1.89 const_iv (GL_QUAD_STRIP),
1868     const_iv (GL_TRIANGLES),
1869     const_iv (GL_TRIANGLE_STRIP),
1870     const_iv (GL_TRIANGLE_FAN),
1871 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1872     const_iv (GL_FASTEST),
1873 root 1.89 const_iv (GL_V2F),
1874     const_iv (GL_V3F),
1875     const_iv (GL_T2F_V3F),
1876     const_iv (GL_T2F_N3F_V3F),
1877 root 1.54 # undef const_iv
1878     };
1879    
1880     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1881     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1882     }
1883    
1884 root 1.97 char *
1885     gl_vendor ()
1886     CODE:
1887     RETVAL = (char *)glGetString (GL_VENDOR);
1888     OUTPUT:
1889     RETVAL
1890    
1891     char *
1892     gl_version ()
1893     CODE:
1894     RETVAL = (char *)glGetString (GL_VERSION);
1895     OUTPUT:
1896     RETVAL
1897    
1898     char *
1899     gl_extensions ()
1900     CODE:
1901     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1902     OUTPUT:
1903     RETVAL
1904    
1905 root 1.54 int glGetError ()
1906    
1907 root 1.114 void glFinish ()
1908    
1909 root 1.54 void glClear (int mask)
1910    
1911     void glClearColor (float r, float g, float b, float a = 1.0)
1912     PROTOTYPE: @
1913    
1914     void glEnable (int cap)
1915    
1916     void glDisable (int cap)
1917    
1918     void glShadeModel (int mode)
1919    
1920     void glHint (int target, int mode)
1921    
1922     void glBlendFunc (int sfactor, int dfactor)
1923    
1924 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1925     CODE:
1926     gl_BlendFuncSeparate (sa, da, saa, daa);
1927    
1928 root 1.89 void glDepthMask (int flag)
1929    
1930 root 1.54 void glLogicOp (int opcode)
1931    
1932 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1933    
1934 root 1.54 void glMatrixMode (int mode)
1935    
1936     void glPushMatrix ()
1937    
1938     void glPopMatrix ()
1939    
1940     void glLoadIdentity ()
1941    
1942 root 1.119 void glDrawBuffer (int buffer)
1943    
1944     void glReadBuffer (int buffer)
1945    
1946 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1947     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1948    
1949     # near_ and far_ are due to microsofts buggy "c" compiler
1950 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1951 root 1.54
1952     void glViewport (int x, int y, int width, int height)
1953    
1954 root 1.69 void glScissor (int x, int y, int width, int height)
1955    
1956 root 1.54 void glTranslate (float x, float y, float z = 0.)
1957     CODE:
1958     glTranslatef (x, y, z);
1959    
1960 root 1.62 void glScale (float x, float y, float z = 1.)
1961 root 1.54 CODE:
1962     glScalef (x, y, z);
1963    
1964     void glRotate (float angle, float x, float y, float z)
1965     CODE:
1966     glRotatef (angle, x, y, z);
1967    
1968     void glBegin (int mode)
1969    
1970     void glEnd ()
1971    
1972     void glColor (float r, float g, float b, float a = 1.0)
1973     PROTOTYPE: @
1974 root 1.103 ALIAS:
1975     glColor_premultiply = 1
1976 root 1.54 CODE:
1977 root 1.103 if (ix)
1978     {
1979     r *= a;
1980     g *= a;
1981     b *= a;
1982     }
1983 root 1.90 // microsoft visual "c" rounds instead of truncating...
1984 root 1.130 glColor4f (r, g, b, a);
1985 root 1.54
1986 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1987    
1988     void glDrawElements (int mode, int count, int type, char *indices)
1989    
1990     # 1.2 void glDrawRangeElements (int mode, int start, int end
1991    
1992 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1993     CODE:
1994     glRasterPos3f (0, 0, z);
1995     glBitmap (0, 0, 0, 0, x, y, 0);
1996    
1997 root 1.54 void glVertex (float x, float y, float z = 0.)
1998     CODE:
1999     glVertex3f (x, y, z);
2000    
2001     void glTexCoord (float s, float t)
2002     CODE:
2003     glTexCoord2f (s, t);
2004    
2005     void glTexEnv (int target, int pname, float param)
2006     CODE:
2007     glTexEnvf (target, pname, param);
2008    
2009     void glTexParameter (int target, int pname, float param)
2010     CODE:
2011     glTexParameterf (target, pname, param);
2012    
2013     void glBindTexture (int target, int name)
2014    
2015     void glConvolutionParameter (int target, int pname, float params)
2016     CODE:
2017 root 1.103 if (gl.ConvolutionParameterf)
2018     gl.ConvolutionParameterf (target, pname, params);
2019 root 1.54
2020     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2021 root 1.64 CODE:
2022 root 1.103 if (gl.ConvolutionFilter2D)
2023     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2024 root 1.54
2025 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2026     CODE:
2027 root 1.103 if (gl.SeparableFilter2D)
2028     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2029 root 1.69
2030 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2031    
2032     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2033    
2034 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2035 root 1.68
2036     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2037    
2038 root 1.54 int glGenTexture ()
2039     CODE:
2040     {
2041     GLuint name;
2042     glGenTextures (1, &name);
2043     RETVAL = name;
2044     }
2045     OUTPUT:
2046     RETVAL
2047    
2048     void glDeleteTexture (int name)
2049     CODE:
2050     {
2051     GLuint name_ = name;
2052     glDeleteTextures (1, &name_);
2053     }
2054    
2055     int glGenList ()
2056     CODE:
2057     RETVAL = glGenLists (1);
2058     OUTPUT:
2059     RETVAL
2060    
2061     void glDeleteList (int list)
2062     CODE:
2063     glDeleteLists (list, 1);
2064    
2065     void glNewList (int list, int mode = GL_COMPILE)
2066    
2067     void glEndList ()
2068    
2069     void glCallList (int list)
2070