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