ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.67
Committed: Tue Apr 25 11:18:48 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.66: +5 -2 lines
Log Message:
do not require an alpha channel for the framebuffer for the sake of software-renderers

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2     # include <malloc.h>
3     #endif
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.5 #include <string.h>
10 root 1.25 #include <stdio.h>
11 root 1.5
12 root 1.2 #include <SDL.h>
13 root 1.23 #include <SDL_image.h>
14 root 1.52 #include <SDL_mixer.h>
15 root 1.3 #include <SDL_opengl.h>
16 root 1.5
17 root 1.30 #include <glib/gmacros.h>
18    
19 root 1.5 #include <pango/pango.h>
20 root 1.10 #include <pango/pangofc-fontmap.h>
21 root 1.5 #include <pango/pangoft2.h>
22    
23 root 1.48 #ifndef _WIN32
24     # include <sys/types.h>
25     # include <sys/socket.h>
26     # include <netinet/in.h>
27     # include <netinet/tcp.h>
28     # include <inttypes.h>
29     #else
30     typedef unsigned char uint8_t;
31     typedef unsigned short uint16_t;
32     typedef unsigned int uint32_t;
33     typedef signed char int8_t;
34     typedef signed short int16_t;
35     typedef signed int int32_t;
36     #endif
37 root 1.28
38 root 1.57 #include "glext.h"
39    
40 root 1.29 #define FOW_DARKNESS 32
41    
42     #define MAP_EXTEND_X 32
43     #define MAP_EXTEND_Y 512
44    
45 root 1.63 #define MIN_FONT_HEIGHT 10
46 root 1.58
47 root 1.64 #define GL_CALL(type,func,args) \
48     { \
49     static int init_; \
50     static type fptr_; \
51     \
52     if (!init_) \
53     { \
54     init_ = 1; \
55     fptr_ = (type)SDL_GL_GetProcAddress (# func); \
56     } \
57     \
58     if (fptr_) \
59     fptr_ args; \
60     }
61    
62 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
63     typedef Mix_Music *CFClient__MixMusic;
64    
65 root 1.61 typedef PangoFontDescription *CFClient__Font;
66 root 1.2
67 root 1.14 typedef struct cf_layout {
68     PangoLayout *pl;
69     int base_height;
70 root 1.61 CFClient__Font font;
71 root 1.15 } *CFClient__Layout;
72 root 1.14
73 root 1.61 static CFClient__Font default_font;
74     static PangoContext *context;
75     static PangoFontMap *fontmap;
76    
77 root 1.14 static void
78 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
79     {
80 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
81 root 1.35 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
82 root 1.19 }
83    
84     static void
85 root 1.61 layout_update_font (CFClient__Layout self)
86 root 1.17 {
87 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
88     * reasonably well with bitstream vera
89     */
90 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
91 root 1.46
92 root 1.61 pango_font_description_set_absolute_size (font,
93     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
94 root 1.58
95 root 1.61 pango_layout_set_font_description (self->pl, font);
96 root 1.17 }
97    
98     static void
99 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
100 root 1.14 {
101     pango_layout_get_pixel_size (self->pl, w, h);
102    
103     *w = (*w + 3) & ~3;
104     if (!*w) *w = 1;
105     if (!*h) *h = 1;
106     }
107    
108 root 1.42 typedef uint16_t mapface;
109    
110 root 1.28 typedef struct {
111 root 1.30 GLint name;
112     int w, h;
113     float s, t;
114 root 1.39 uint8_t r, g, b, a;
115 root 1.42 } maptex;
116 root 1.30
117     typedef struct {
118 root 1.29 int16_t darkness;
119 root 1.42 mapface face[3];
120 root 1.28 } mapcell;
121    
122     typedef struct {
123 root 1.30 int32_t c0, c1;
124 root 1.28 mapcell *col;
125     } maprow;
126    
127     typedef struct map {
128     int x, y, w, h;
129 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
130 root 1.28 int faces;
131 root 1.30 mapface *face;
132 root 1.28
133 root 1.42 int texs;
134     maptex *tex;
135    
136 root 1.48 int32_t rows;
137 root 1.28 maprow *row;
138     } *CFClient__Map;
139    
140 root 1.30 static char *
141     prepend (char *ptr, int sze, int inc)
142     {
143     char *p;
144    
145     New (0, p, sze + inc, char);
146     Zero (p, inc, char);
147     Move (ptr, p + inc, sze, char);
148     Safefree (ptr);
149    
150     return p;
151     }
152    
153     static char *
154     append (char *ptr, int sze, int inc)
155     {
156     Renew (ptr, sze + inc, char);
157     Zero (ptr + sze, inc, char);
158    
159     return ptr;
160     }
161    
162     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
163     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
164    
165 root 1.42 static maprow *
166     map_get_row (CFClient__Map self, int y)
167     {
168     if (0 > y)
169     {
170     int extend = - y + MAP_EXTEND_Y;
171     Prepend (maprow, self->row, self->rows, extend);
172    
173     self->rows += extend;
174     self->y += extend;
175     y += extend;
176     }
177     else if (y >= self->rows)
178     {
179     int extend = y - self->rows + MAP_EXTEND_Y;
180     Append (maprow, self->row, self->rows, extend);
181     self->rows += extend;
182     }
183    
184     return self->row + y;
185     }
186    
187     static mapcell *
188     row_get_cell (maprow *row, int x)
189     {
190     if (!row->col)
191     {
192     Newz (0, row->col, MAP_EXTEND_X, mapcell);
193     row->c0 = x - MAP_EXTEND_X / 4;
194     row->c1 = row->c0 + MAP_EXTEND_X;
195     }
196    
197     if (row->c0 > x)
198     {
199     int extend = row->c0 - x + MAP_EXTEND_X;
200     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
201     row->c0 -= extend;
202     }
203     else if (x >= row->c1)
204     {
205     int extend = x - row->c1 + MAP_EXTEND_X;
206     Append (mapcell, row->col, row->c1 - row->c0, extend);
207     row->c1 += extend;
208     }
209    
210     return row->col + (x - row->c0);
211     }
212    
213     static mapcell *
214     map_get_cell (CFClient__Map self, int x, int y)
215     {
216     return row_get_cell (map_get_row (self, y), x);
217     }
218    
219 root 1.30 static void
220     map_clear (CFClient__Map self)
221     {
222     int r;
223    
224     for (r = 0; r < self->rows; r++)
225     Safefree (self->row[r].col);
226    
227     Safefree (self->row);
228    
229     self->x = 0;
230     self->y = 0;
231 root 1.42 self->ox = 0;
232     self->oy = 0;
233 root 1.30 self->row = 0;
234     self->rows = 0;
235     }
236    
237 root 1.29 static void
238     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
239     {
240     int x, y;
241 root 1.48 maprow *row;
242 root 1.29
243     for (y = y0; y < y0 + h; y++)
244 root 1.30 if (y >= 0)
245     {
246     if (y >= self->rows)
247     break;
248    
249 root 1.48 row = self->row + y;
250 root 1.30
251     for (x = x0; x < x0 + w; x++)
252     if (x >= row->c0)
253     {
254     if (x >= row->c1)
255     break;
256 root 1.29
257 root 1.31 row->col[x - row->c0].darkness = -1;
258 root 1.30 }
259     }
260 root 1.29 }
261    
262 root 1.56 static void
263     music_finished ()
264     {
265     SDL_UserEvent ev;
266    
267     ev.type = SDL_USEREVENT;
268     ev.code = 0;
269     ev.data1 = 0;
270     ev.data2 = 0;
271    
272 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
273 root 1.56 }
274    
275 root 1.15 MODULE = CFClient PACKAGE = CFClient
276 root 1.1
277 root 1.11 PROTOTYPES: ENABLE
278    
279 root 1.5 BOOT:
280     {
281 root 1.51 HV *stash = gv_stashpv ("CFClient", 1);
282     static const struct {
283     const char *name;
284     IV iv;
285     } *civ, const_iv[] = {
286     # define const_iv(name) { # name, (IV)name }
287     const_iv (SDL_ACTIVEEVENT),
288     const_iv (SDL_KEYDOWN),
289     const_iv (SDL_KEYUP),
290     const_iv (SDL_MOUSEMOTION),
291     const_iv (SDL_MOUSEBUTTONDOWN),
292     const_iv (SDL_MOUSEBUTTONUP),
293     const_iv (SDL_JOYAXISMOTION),
294     const_iv (SDL_JOYBALLMOTION),
295     const_iv (SDL_JOYHATMOTION),
296     const_iv (SDL_JOYBUTTONDOWN),
297     const_iv (SDL_JOYBUTTONUP),
298     const_iv (SDL_QUIT),
299     const_iv (SDL_SYSWMEVENT),
300     const_iv (SDL_EVENT_RESERVEDA),
301     const_iv (SDL_EVENT_RESERVEDB),
302     const_iv (SDL_VIDEORESIZE),
303     const_iv (SDL_VIDEOEXPOSE),
304     const_iv (SDL_USEREVENT),
305     const_iv (SDLK_KP0),
306     const_iv (SDLK_KP1),
307     const_iv (SDLK_KP2),
308     const_iv (SDLK_KP3),
309     const_iv (SDLK_KP4),
310     const_iv (SDLK_KP5),
311     const_iv (SDLK_KP6),
312     const_iv (SDLK_KP7),
313     const_iv (SDLK_KP8),
314     const_iv (SDLK_KP9),
315     const_iv (SDLK_KP_PERIOD),
316     const_iv (SDLK_KP_DIVIDE),
317     const_iv (SDLK_KP_MULTIPLY),
318     const_iv (SDLK_KP_MINUS),
319     const_iv (SDLK_KP_PLUS),
320     const_iv (SDLK_KP_ENTER),
321     const_iv (SDLK_KP_EQUALS),
322     const_iv (SDLK_UP),
323     const_iv (SDLK_DOWN),
324     const_iv (SDLK_RIGHT),
325     const_iv (SDLK_LEFT),
326     const_iv (SDLK_INSERT),
327     const_iv (SDLK_HOME),
328     const_iv (SDLK_END),
329     const_iv (SDLK_PAGEUP),
330     const_iv (SDLK_PAGEDOWN),
331     const_iv (SDLK_F1),
332     const_iv (SDLK_F2),
333     const_iv (SDLK_F3),
334     const_iv (SDLK_F4),
335     const_iv (SDLK_F5),
336     const_iv (SDLK_F6),
337     const_iv (SDLK_F7),
338     const_iv (SDLK_F8),
339     const_iv (SDLK_F9),
340     const_iv (SDLK_F10),
341     const_iv (SDLK_F11),
342     const_iv (SDLK_F12),
343     const_iv (SDLK_F13),
344     const_iv (SDLK_F14),
345     const_iv (SDLK_F15),
346     const_iv (SDLK_NUMLOCK),
347     const_iv (SDLK_CAPSLOCK),
348     const_iv (SDLK_SCROLLOCK),
349     const_iv (SDLK_RSHIFT),
350     const_iv (SDLK_LSHIFT),
351     const_iv (SDLK_RCTRL),
352     const_iv (SDLK_LCTRL),
353     const_iv (SDLK_RALT),
354     const_iv (SDLK_LALT),
355     const_iv (SDLK_RMETA),
356     const_iv (SDLK_LMETA),
357     const_iv (SDLK_LSUPER),
358     const_iv (SDLK_RSUPER),
359     const_iv (SDLK_MODE),
360     const_iv (SDLK_COMPOSE),
361     const_iv (SDLK_HELP),
362     const_iv (SDLK_PRINT),
363     const_iv (SDLK_SYSREQ),
364     const_iv (SDLK_BREAK),
365     const_iv (SDLK_MENU),
366     const_iv (SDLK_POWER),
367     const_iv (SDLK_EURO),
368     const_iv (SDLK_UNDO),
369     const_iv (KMOD_NONE),
370     const_iv (KMOD_LSHIFT),
371     const_iv (KMOD_RSHIFT),
372     const_iv (KMOD_LCTRL),
373     const_iv (KMOD_RCTRL),
374     const_iv (KMOD_LALT),
375     const_iv (KMOD_RALT),
376     const_iv (KMOD_LMETA),
377     const_iv (KMOD_RMETA),
378     const_iv (KMOD_NUM),
379     const_iv (KMOD_CAPS),
380     const_iv (KMOD_MODE),
381     const_iv (KMOD_CTRL),
382     const_iv (KMOD_SHIFT),
383     const_iv (KMOD_ALT),
384     const_iv (KMOD_META)
385     # undef const_iv
386     };
387    
388     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
389     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
390    
391     fontmap = pango_ft2_font_map_new ();
392     pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
393     context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
394 root 1.5 }
395    
396 root 1.51 int
397     SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO)
398    
399     void
400     SDL_Quit ()
401    
402     void
403     SDL_ListModes ()
404     PPCODE:
405     {
406     SDL_Rect **m;
407    
408     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
409     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
410     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
411 root 1.67 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 0);
412 root 1.51
413     SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
414     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
415     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
416     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
417    
418     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
419     SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
420     SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
421    
422 root 1.53 SDL_EnableUNICODE (1);
423     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
424    
425 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
426    
427     if (m && m != (SDL_Rect **)-1)
428     while (*m)
429     {
430     AV *av = newAV ();
431     av_push (av, newSViv ((*m)->w));
432     av_push (av, newSViv ((*m)->h));
433     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
434    
435     ++m;
436     }
437     }
438    
439     int
440     SDL_SetVideoMode (int w, int h, int fullscreen)
441     CODE:
442     RETVAL = !!SDL_SetVideoMode (
443     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
444     );
445     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
446     OUTPUT:
447     RETVAL
448    
449 root 1.53 void
450 root 1.54 SDL_GL_SwapBuffers ()
451    
452     void
453 root 1.53 SDL_PollEvent ()
454     PPCODE:
455     {
456     SDL_Event ev;
457    
458     while (SDL_PollEvent (&ev))
459     {
460     HV *hv = newHV ();
461     hv_store (hv, "type", 4, newSViv (ev.type), 0);
462     switch (ev.type)
463     {
464     case SDL_KEYDOWN:
465     case SDL_KEYUP:
466     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
467     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
468     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
469     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
470     break;
471    
472     case SDL_ACTIVEEVENT:
473     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
474     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
475     break;
476    
477     case SDL_MOUSEMOTION:
478     hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
479     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
480     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
481     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
482     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
483     break;
484    
485     case SDL_MOUSEBUTTONDOWN:
486     case SDL_MOUSEBUTTONUP:
487     hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
488     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
489     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
490     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
491     }
492    
493     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
494     }
495     }
496 root 1.52
497     int
498     Mix_OpenAudio (int frequency = 22050, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 512)
499 root 1.56 POSTCALL:
500     Mix_HookMusicFinished (music_finished);
501 root 1.52
502     void
503     Mix_CloseAudio ()
504    
505     int
506     Mix_AllocateChannels (int numchans = -1)
507    
508 root 1.10 void
509     lowdelay (int fd, int val = 1)
510     CODE:
511 root 1.48 #ifndef _WIN32
512 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
513 root 1.48 #endif
514 root 1.10
515 root 1.3 char *
516 root 1.4 gl_version ()
517     CODE:
518 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
519 root 1.4 OUTPUT:
520     RETVAL
521    
522     char *
523 root 1.3 gl_extensions ()
524     CODE:
525 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
526 root 1.3 OUTPUT:
527     RETVAL
528    
529 root 1.5 void
530 root 1.13 add_font (char *file)
531     CODE:
532     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
533    
534     void
535 root 1.23 load_image_inline (SV *image_)
536     ALIAS:
537     load_image_file = 1
538     PPCODE:
539     {
540     STRLEN image_len;
541     char *image = (char *)SvPVbyte (image_, image_len);
542     SDL_Surface *surface, *surface2;
543     SDL_PixelFormat fmt;
544     SDL_RWops *rw = ix
545     ? SDL_RWFromFile (image, "r")
546     : SDL_RWFromConstMem (image, image_len);
547    
548     if (!rw)
549 root 1.41 croak ("load_image: %s", SDL_GetError ());
550 root 1.23
551     surface = IMG_Load_RW (rw, 1);
552     if (!surface)
553 root 1.41 croak ("load_image: %s", SDL_GetError ());
554 root 1.23
555     fmt.palette = NULL;
556     fmt.BitsPerPixel = 32;
557     fmt.BytesPerPixel = 4;
558 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
559 root 1.23 fmt.Rmask = 0x000000ff;
560     fmt.Gmask = 0x0000ff00;
561     fmt.Bmask = 0x00ff0000;
562     fmt.Amask = 0xff000000;
563 root 1.49 #else
564     fmt.Rmask = 0xff000000;
565     fmt.Gmask = 0x00ff0000;
566     fmt.Bmask = 0x0000ff00;
567     fmt.Amask = 0x000000ff;
568     #endif
569 root 1.23 fmt.Rloss = 0;
570     fmt.Gloss = 0;
571     fmt.Bloss = 0;
572     fmt.Aloss = 0;
573     fmt.Rshift = 0;
574     fmt.Gshift = 8;
575     fmt.Bshift = 16;
576     fmt.Ashift = 24;
577     fmt.colorkey = 0;
578     fmt.alpha = 0;
579    
580     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
581    
582 root 1.39 assert (surface2->pitch == surface2->w * 4);
583    
584 root 1.23 EXTEND (SP, 5);
585     PUSHs (sv_2mortal (newSViv (surface2->w)));
586     PUSHs (sv_2mortal (newSViv (surface2->h)));
587     SDL_LockSurface (surface2);
588     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
589     SDL_UnlockSurface (surface2);
590 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
591 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
592 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
593 root 1.23
594     SDL_FreeSurface (surface);
595     SDL_FreeSurface (surface2);
596     }
597    
598 root 1.25 void
599 root 1.39 average (int x, int y, uint32_t *data)
600     PPCODE:
601     {
602     uint32_t r = 0, g = 0, b = 0, a = 0;
603    
604     x = y = x * y;
605    
606     while (x--)
607     {
608     uint32_t p = *data++;
609    
610     r += (p ) & 255;
611     g += (p >> 8) & 255;
612     b += (p >> 16) & 255;
613     a += (p >> 24) & 255;
614     }
615    
616     EXTEND (SP, 4);
617 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
618     PUSHs (sv_2mortal (newSViv (g / y)));
619     PUSHs (sv_2mortal (newSViv (b / y)));
620     PUSHs (sv_2mortal (newSViv (a / y)));
621 root 1.39 }
622    
623     void
624 root 1.66 error (char *message)
625     CODE:
626     #ifdef _WIN32
627     MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
628     #else
629     fprintf (stderr, "ERROR: %s\n", message);
630     #endif
631    
632     void
633 root 1.25 fatal (char *message)
634     CODE:
635 root 1.50 #ifdef _WIN32
636 root 1.25 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
637     #else
638 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
639 root 1.25 #endif
640     exit (1);
641    
642 root 1.61 MODULE = CFClient PACKAGE = CFClient::Font
643    
644     CFClient::Font
645     new_from_file (SV *class, char *path)
646     CODE:
647     {
648     int count;
649     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, 0, 0, &count);
650     RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
651     FcPatternDestroy (pattern);
652     }
653     OUTPUT:
654     RETVAL
655    
656     void
657     DESTROY (CFClient::Font self)
658     CODE:
659     pango_font_description_free (self);
660    
661     void
662     make_default (CFClient::Font self)
663     CODE:
664     default_font = self;
665    
666 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
667 root 1.14
668 root 1.15 CFClient::Layout
669 root 1.61 new (SV *class, int base_height = MIN_FONT_HEIGHT)
670 root 1.14 CODE:
671     New (0, RETVAL, 1, struct cf_layout);
672 root 1.61 RETVAL->pl = pango_layout_new (context);
673 root 1.14 RETVAL->base_height = base_height;
674 root 1.61 RETVAL->font = 0;
675 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
676 root 1.61 pango_layout_set_font_description (RETVAL->pl, default_font);
677 root 1.14 OUTPUT:
678     RETVAL
679    
680     void
681 root 1.15 DESTROY (CFClient::Layout self)
682 root 1.14 CODE:
683     g_object_unref (self->pl);
684     Safefree (self);
685 root 1.13
686 root 1.8 void
687 root 1.35 set_text (CFClient::Layout self, SV *text_)
688     CODE:
689     {
690     STRLEN textlen;
691     char *text = SvPVutf8 (text_, textlen);
692    
693     pango_layout_set_text (self->pl, text, textlen);
694     }
695    
696     void
697 root 1.15 set_markup (CFClient::Layout self, SV *text_)
698 root 1.14 CODE:
699 root 1.5 {
700     STRLEN textlen;
701     char *text = SvPVutf8 (text_, textlen);
702 root 1.14
703     pango_layout_set_markup (self->pl, text, textlen);
704     }
705    
706 root 1.46 SV *
707     get_text (CFClient::Layout self)
708     CODE:
709 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
710 root 1.46 SvUTF8_on (RETVAL);
711     OUTPUT:
712     RETVAL
713    
714 root 1.14 void
715 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
716     CODE:
717     if (self->font != font)
718     {
719     self->font = font;
720     layout_update_font (self);
721     }
722    
723     void
724 root 1.16 set_height (CFClient::Layout self, int base_height)
725     CODE:
726 root 1.61 if (self->base_height != base_height)
727     {
728     self->base_height = base_height;
729     layout_update_font (self);
730     }
731 root 1.16
732     void
733 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
734 root 1.14 CODE:
735     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
736    
737     void
738 root 1.15 size (CFClient::Layout self)
739 root 1.14 PPCODE:
740     {
741     int w, h;
742    
743     layout_get_pixel_size (self, &w, &h);
744    
745     EXTEND (SP, 2);
746     PUSHs (sv_2mortal (newSViv (w)));
747     PUSHs (sv_2mortal (newSViv (h)));
748     }
749    
750 root 1.17 int
751     xy_to_index (CFClient::Layout self, int x, int y)
752     CODE:
753     {
754     int index, trailing;
755     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
756     RETVAL = index;
757     }
758     OUTPUT:
759     RETVAL
760    
761     void
762     cursor_pos (CFClient::Layout self, int index)
763     PPCODE:
764     {
765     PangoRectangle strong_pos;
766     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
767 root 1.30
768 root 1.17 EXTEND (SP, 3);
769     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
770     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
771     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
772     }
773    
774 root 1.14 void
775 root 1.15 render (CFClient::Layout self)
776 root 1.14 PPCODE:
777     {
778 root 1.5 SV *retval;
779     int w, h;
780     FT_Bitmap bitmap;
781    
782 root 1.14 layout_get_pixel_size (self, &w, &h);
783 root 1.5
784     retval = newSV (w * h);
785     SvPOK_only (retval);
786     SvCUR_set (retval, w * h);
787    
788     bitmap.rows = h;
789     bitmap.width = w;
790     bitmap.pitch = w;
791     bitmap.buffer = (unsigned char*)SvPVX (retval);
792     bitmap.num_grays = 256;
793     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
794    
795     memset (bitmap.buffer, 0, w * h);
796    
797 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
798 root 1.1
799 root 1.5 EXTEND (SP, 3);
800     PUSHs (sv_2mortal (newSViv (w)));
801     PUSHs (sv_2mortal (newSViv (h)));
802     PUSHs (sv_2mortal (retval));
803     }
804 root 1.11
805 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
806 root 1.11
807     void
808 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
809 root 1.12 PROTOTYPE: $$$;$$
810 root 1.11 CODE:
811     {
812 root 1.12 HV *hv = (HV *)SvRV (self);
813 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
814     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
815 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
816 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
817 root 1.12
818     if (items < 5)
819     {
820 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
821     h = SvNV (*hv_fetch (hv, "h", 1, 1));
822 root 1.12 }
823    
824     glBindTexture (GL_TEXTURE_2D, name);
825 elmex 1.36 if (wrap_mode) {
826     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
827     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
828     }
829 root 1.12 glBegin (GL_QUADS);
830 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
831     glTexCoord2f (0, t); glVertex2f (x , y + h);
832     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
833     glTexCoord2f (s, 0); glVertex2f (x + w, y );
834 root 1.12 glEnd ();
835 root 1.11 }
836 root 1.28
837     MODULE = CFClient PACKAGE = CFClient::Map
838    
839     CFClient::Map
840     new (SV *class, int map_width, int map_height)
841     CODE:
842     New (0, RETVAL, 1, struct map);
843 root 1.42 RETVAL->x = 0;
844     RETVAL->y = 0;
845     RETVAL->w = map_width;
846     RETVAL->h = map_height;
847     RETVAL->ox = 0;
848     RETVAL->oy = 0;
849 root 1.30 RETVAL->faces = 8192;
850     Newz (0, RETVAL->face, RETVAL->faces, mapface);
851 root 1.42 RETVAL->texs = 8192;
852     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
853 root 1.28 RETVAL->rows = 0;
854     RETVAL->row = 0;
855     OUTPUT:
856     RETVAL
857    
858     void
859     DESTROY (CFClient::Map self)
860     CODE:
861     {
862 root 1.30 map_clear (self);
863 root 1.28 Safefree (self->face);
864 root 1.29 Safefree (self);
865     }
866    
867     void
868 root 1.30 clear (CFClient::Map self)
869     CODE:
870     map_clear (self);
871    
872     void
873 root 1.42 set_face (CFClient::Map self, int face, int texid)
874 root 1.29 CODE:
875     {
876 root 1.42 while (self->faces <= face)
877 root 1.28 {
878 root 1.30 Append (mapface, self->face, self->faces, self->faces);
879 root 1.29 self->faces *= 2;
880     }
881 root 1.28
882 root 1.42 self->face [face] = texid;
883     }
884    
885     void
886     set_texture (CFClient::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
887     CODE:
888     {
889     while (self->texs <= texid)
890     {
891     Append (maptex, self->tex, self->texs, self->texs);
892     self->texs *= 2;
893     }
894    
895 root 1.48 {
896     maptex *tex = self->tex + texid;
897 root 1.39
898 root 1.48 tex->name = name;
899     tex->w = w;
900     tex->h = h;
901     tex->s = s;
902     tex->t = t;
903     tex->r = r;
904     tex->g = g;
905     tex->b = b;
906     tex->a = a;
907     }
908 root 1.29 }
909    
910 root 1.42 int
911     ox (CFClient::Map self)
912     ALIAS:
913     oy = 1
914     CODE:
915     switch (ix)
916     {
917     case 0: RETVAL = self->ox; break;
918     case 1: RETVAL = self->oy; break;
919     }
920     OUTPUT:
921     RETVAL
922    
923 root 1.29 void
924 root 1.43 scroll (CFClient::Map self, int dx, int dy)
925     CODE:
926     {
927 root 1.44 if (dx > 0)
928     map_blank (self, self->x, self->y, dx - 1, self->h);
929     else if (dx < 0)
930     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
931    
932     if (dy > 0)
933     map_blank (self, self->x, self->y, self->w, dy - 1);
934     else if (dy < 0)
935     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
936 root 1.43
937 root 1.44 self->ox += dx; self->x += dx;
938     self->oy += dy; self->y += dy;
939 root 1.43
940     while (self->y < 0)
941     {
942     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
943    
944     self->rows += MAP_EXTEND_Y;
945     self->y += MAP_EXTEND_Y;
946     }
947 root 1.44 }
948 root 1.43
949 root 1.44 void
950     map1a_update (CFClient::Map self, SV *data_)
951     CODE:
952     {
953 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
954     uint8_t *data_end = (uint8_t *)SvEND (data_);
955 root 1.48 mapcell *cell;
956     int x, y, flags;
957 root 1.43
958 root 1.29 while (data < data_end)
959     {
960 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
961 root 1.30
962 root 1.48 x = ((flags >> 10) & 63) + self->x;
963     y = ((flags >> 4) & 63) + self->y;
964 root 1.29
965 root 1.48 cell = map_get_cell (self, x, y);
966 root 1.29
967     if (flags & 15)
968     {
969 root 1.45 if (cell->darkness < 0)
970 root 1.29 {
971     cell->darkness = 0;
972     cell->face [0] = 0;
973     cell->face [1] = 0;
974     cell->face [2] = 0;
975     }
976 root 1.45
977 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
978    
979 root 1.42 //TODO: don't trust server data to be in-range(!)
980    
981 root 1.29 if (flags & 4)
982     {
983 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
984 root 1.29 }
985    
986     if (flags & 2)
987     {
988 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
989 root 1.29 }
990    
991     if (flags & 1)
992     {
993 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
994 root 1.29 }
995     }
996     else
997 root 1.31 cell->darkness = -1;
998 root 1.29 }
999 root 1.28 }
1000    
1001 root 1.40 SV *
1002 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1003 root 1.40 CODE:
1004     {
1005 root 1.55 int x1, x;
1006     int y1, y;
1007 root 1.40 int z;
1008     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1009     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1010    
1011     SvPOK_only (map_sv);
1012     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1013    
1014 root 1.55 x0 += self->x; x1 = x0 + w;
1015     y0 += self->y; y1 = y0 + h;
1016 root 1.40
1017     for (y = y0; y < y1; y++)
1018     {
1019     maprow *row = 0 <= y && y < self->rows
1020     ? self->row + y
1021     : 0;
1022    
1023     for (x = x0; x < x1; x++)
1024     {
1025     int r = 32, g = 32, b = 32, a = 192;
1026    
1027     if (row && row->c0 <= x && x < row->c1)
1028     {
1029     mapcell *cell = row->col + (x - row->c0);
1030    
1031     for (z = 0; z <= 0; z++)
1032     {
1033 root 1.42 mapface face = cell->face [z];
1034 root 1.40
1035     if (face)
1036     {
1037 root 1.42 maptex tex = self->tex [face];
1038 root 1.40 int a0 = 255 - tex.a;
1039     int a1 = tex.a;
1040    
1041     r = (r * a0 + tex.r * a1) / 255;
1042     g = (g * a0 + tex.g * a1) / 255;
1043     b = (b * a0 + tex.b * a1) / 255;
1044     a = (a * a0 + tex.a * a1) / 255;
1045     }
1046     }
1047     }
1048    
1049     *map++ = (r )
1050     | (g << 8)
1051     | (b << 16)
1052     | (a << 24);
1053     }
1054     }
1055    
1056     RETVAL = map_sv;
1057     }
1058     OUTPUT:
1059     RETVAL
1060    
1061 root 1.30 void
1062 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1063 root 1.32 PPCODE:
1064 root 1.30 {
1065 root 1.48 int vx, vy;
1066     int x, y, z;
1067     int last_name;
1068     mapface face;
1069 root 1.32 int sw4 = (sw + 3) & ~3;
1070     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1071 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1072 root 1.48
1073 root 1.42 memset (darkness, 255, sw4 * sh);
1074 root 1.32 SvPOK_only (darkness_sv);
1075     SvCUR_set (darkness_sv, sw4 * sh);
1076    
1077 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1078     vy = self->y + (self->h - sh) / 2 - shift_y;
1079 root 1.38
1080 root 1.42 /*
1081     int vx = self->vx = self->w >= sw
1082     ? self->x + (self->w - sw) / 2
1083     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1084    
1085     int vy = self->vy = self->h >= sh
1086     ? self->y + (self->h - sh) / 2
1087     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1088     */
1089 root 1.30
1090     glColor4ub (255, 255, 255, 255);
1091    
1092     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1093     glEnable (GL_BLEND);
1094     glEnable (GL_TEXTURE_2D);
1095     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1096    
1097 root 1.48 glBegin (GL_QUADS);
1098 root 1.30
1099 root 1.48 last_name = 0;
1100 root 1.30
1101     for (z = 0; z < 3; z++)
1102     for (y = 0; y < sh; y++)
1103     if (0 <= y + vy && y + vy < self->rows)
1104     {
1105     maprow *row = self->row + (y + vy);
1106    
1107     for (x = 0; x < sw; x++)
1108     if (row->c0 <= x + vx && x + vx < row->c1)
1109     {
1110     mapcell *cell = row->col + (x + vx - row->c0);
1111 root 1.32
1112     darkness[y * sw4 + x] = cell->darkness < 0
1113 root 1.33 ? 255 - FOW_DARKNESS
1114 root 1.32 : 255 - cell->darkness;
1115    
1116 root 1.48 face = cell->face [z];
1117 root 1.30
1118     if (face)
1119     {
1120 root 1.42 maptex tex = self->tex [face];
1121 root 1.30
1122     int px = (x + 1) * 32 - tex.w;
1123     int py = (y + 1) * 32 - tex.h;
1124    
1125     if (last_name != tex.name)
1126     {
1127     glEnd ();
1128     last_name = tex.name;
1129     glBindTexture (GL_TEXTURE_2D, last_name);
1130     glBegin (GL_QUADS);
1131     }
1132    
1133     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1134     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1135     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1136     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1137     }
1138     }
1139     }
1140    
1141     glEnd ();
1142 root 1.32
1143 root 1.34 glDisable (GL_TEXTURE_2D);
1144     glDisable (GL_BLEND);
1145    
1146 root 1.32 EXTEND (SP, 3);
1147     PUSHs (sv_2mortal (newSViv (sw4)));
1148     PUSHs (sv_2mortal (newSViv (sh)));
1149     PUSHs (darkness_sv);
1150 root 1.30 }
1151    
1152 root 1.42 SV *
1153     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1154     CODE:
1155     {
1156     int x, y, x1, y1;
1157     SV *data_sv = newSV (w * h * 7 + 5);
1158     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1159    
1160     *data++ = 0; /* version 0 format */
1161     *data++ = w >> 8; *data++ = w;
1162     *data++ = h >> 8; *data++ = h;
1163    
1164     // we need to do this 'cause we don't keep an absolute coord system for rows
1165 root 1.55 // TODO: treat rows as we treat columns
1166 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1167     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1168    
1169     x0 += self->x - self->ox;
1170     y0 += self->y - self->oy;
1171    
1172     x1 = x0 + w;
1173     y1 = y0 + h;
1174    
1175     for (y = y0; y < y1; y++)
1176     {
1177     maprow *row = 0 <= y && y < self->rows
1178     ? self->row + y
1179     : 0;
1180    
1181     for (x = x0; x < x1; x++)
1182     {
1183     if (row && row->c0 <= x && x < row->c1)
1184     {
1185     mapcell *cell = row->col + (x - row->c0);
1186     uint8_t flags = 0;
1187    
1188     if (cell->face [0]) flags |= 1;
1189     if (cell->face [1]) flags |= 2;
1190     if (cell->face [2]) flags |= 4;
1191    
1192     *data++ = flags;
1193    
1194     if (flags & 1)
1195     {
1196     *data++ = cell->face [0] >> 8;
1197     *data++ = cell->face [0];
1198     }
1199    
1200     if (flags & 2)
1201     {
1202     *data++ = cell->face [1] >> 8;
1203     *data++ = cell->face [1];
1204     }
1205    
1206     if (flags & 4)
1207     {
1208     *data++ = cell->face [2] >> 8;
1209     *data++ = cell->face [2];
1210     }
1211     }
1212     else
1213     *data++ = 0;
1214     }
1215     }
1216    
1217     SvPOK_only (data_sv);
1218     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1219     RETVAL = data_sv;
1220     }
1221     OUTPUT:
1222     RETVAL
1223    
1224     void
1225     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1226     PPCODE:
1227     {
1228     int x, y, z;
1229 root 1.48 int w, h;
1230 root 1.42 int x1, y1;
1231    
1232     if (*data++ != 0)
1233     return; /* version mismatch */
1234    
1235 root 1.48 w = *data++ << 8; w |= *data++;
1236     h = *data++ << 8; h |= *data++;
1237 root 1.42
1238     // we need to do this 'cause we don't keep an absolute coord system for rows
1239 root 1.55 // TODO: treat rows as we treat columns
1240 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1241     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1242    
1243     x0 += self->x - self->ox;
1244     y0 += self->y - self->oy;
1245    
1246     x1 = x0 + w;
1247     y1 = y0 + h;
1248    
1249     for (y = y0; y < y1; y++)
1250     {
1251     maprow *row = map_get_row (self, y);
1252    
1253     for (x = x0; x < x1; x++)
1254     {
1255     uint8_t flags = *data++;
1256    
1257     if (flags)
1258     {
1259     mapface face[3] = { 0, 0, 0 };
1260    
1261     mapcell *cell = row_get_cell (row, x);
1262    
1263     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1264     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1265     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1266    
1267     if (cell->darkness <= 0)
1268     {
1269     cell->darkness = -1;
1270    
1271     for (z = 0; z <= 2; z++)
1272     {
1273     cell->face[z] = face[z];
1274    
1275     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1276     XPUSHs (sv_2mortal (newSViv (face[z])));
1277     }
1278     }
1279     }
1280     }
1281     }
1282     }
1283    
1284 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1285    
1286     CFClient::MixChunk
1287     new_from_file (SV *class, char *path)
1288     CODE:
1289     RETVAL = Mix_LoadWAV (path);
1290     OUTPUT:
1291     RETVAL
1292    
1293     void
1294     DESTROY (CFClient::MixChunk self)
1295     CODE:
1296     Mix_FreeChunk (self);
1297    
1298     int
1299     volume (CFClient::MixChunk self, int volume = -1)
1300     CODE:
1301     RETVAL = Mix_VolumeChunk (self, volume);
1302     OUTPUT:
1303     RETVAL
1304    
1305     int
1306     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1307     CODE:
1308     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1309     OUTPUT:
1310     RETVAL
1311    
1312     MODULE = CFClient PACKAGE = CFClient::MixMusic
1313    
1314     int
1315     volume (int volume = -1)
1316     CODE:
1317     RETVAL = Mix_VolumeMusic (volume);
1318     OUTPUT:
1319     RETVAL
1320    
1321     CFClient::MixMusic
1322     new_from_file (SV *class, char *path)
1323     CODE:
1324     RETVAL = Mix_LoadMUS (path);
1325     OUTPUT:
1326     RETVAL
1327    
1328     void
1329     DESTROY (CFClient::MixMusic self)
1330     CODE:
1331     Mix_FreeMusic (self);
1332    
1333     int
1334     play (CFClient::MixMusic self, int loops = -1)
1335     CODE:
1336     RETVAL = Mix_PlayMusic (self, loops);
1337     OUTPUT:
1338     RETVAL
1339    
1340 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1341    
1342     BOOT:
1343     {
1344     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1345     static const struct {
1346     const char *name;
1347     IV iv;
1348     } *civ, const_iv[] = {
1349     # define const_iv(name) { # name, (IV)name }
1350     const_iv (GL_COLOR_MATERIAL),
1351     const_iv (GL_SMOOTH),
1352     const_iv (GL_FLAT),
1353     const_iv (GL_BLEND),
1354     const_iv (GL_AND),
1355 root 1.67 const_iv (GL_ONE),
1356     const_iv (GL_ZERO),
1357 root 1.54 const_iv (GL_SRC_ALPHA),
1358 root 1.67 const_iv (GL_SRC_ALPHA_SATURATE),
1359 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1360 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1361 root 1.54 const_iv (GL_RGB),
1362     const_iv (GL_RGBA),
1363     const_iv (GL_UNSIGNED_BYTE),
1364     const_iv (GL_ALPHA),
1365     const_iv (GL_FLOAT),
1366     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1367     const_iv (GL_COMPILE),
1368     const_iv (GL_TEXTURE_1D),
1369     const_iv (GL_TEXTURE_2D),
1370     const_iv (GL_TEXTURE_ENV),
1371     const_iv (GL_TEXTURE_MAG_FILTER),
1372     const_iv (GL_TEXTURE_MIN_FILTER),
1373     const_iv (GL_TEXTURE_ENV_MODE),
1374     const_iv (GL_TEXTURE_WRAP_S),
1375     const_iv (GL_TEXTURE_WRAP_T),
1376     const_iv (GL_CLAMP),
1377     const_iv (GL_REPEAT),
1378     const_iv (GL_NEAREST),
1379     const_iv (GL_LINEAR),
1380 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1381     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1382     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1383     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1384     const_iv (GL_GENERATE_MIPMAP),
1385 root 1.54 const_iv (GL_MODULATE),
1386     const_iv (GL_REPLACE),
1387     const_iv (GL_COLOR_BUFFER_BIT),
1388     const_iv (GL_PROJECTION),
1389     const_iv (GL_MODELVIEW),
1390     const_iv (GL_COLOR_LOGIC_OP),
1391     const_iv (GL_CONVOLUTION_2D),
1392     const_iv (GL_CONVOLUTION_BORDER_MODE),
1393     const_iv (GL_CONSTANT_BORDER),
1394     const_iv (GL_LINES),
1395     const_iv (GL_QUADS),
1396 root 1.55 const_iv (GL_LINE_LOOP),
1397 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1398     const_iv (GL_FASTEST),
1399     # undef const_iv
1400     };
1401    
1402     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1403     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1404     }
1405    
1406     int glGetError ()
1407    
1408     void glClear (int mask)
1409    
1410     void glClearColor (float r, float g, float b, float a = 1.0)
1411     PROTOTYPE: @
1412    
1413     void glEnable (int cap)
1414    
1415     void glDisable (int cap)
1416    
1417     void glShadeModel (int mode)
1418    
1419     void glHint (int target, int mode)
1420    
1421     void glBlendFunc (int sfactor, int dfactor)
1422    
1423     void glLogicOp (int opcode)
1424    
1425     void glMatrixMode (int mode)
1426    
1427     void glPushMatrix ()
1428    
1429     void glPopMatrix ()
1430    
1431     void glLoadIdentity ()
1432    
1433 root 1.64 # near and far are due to microsofts buggy c compiler
1434     void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1435 root 1.54
1436     void glViewport (int x, int y, int width, int height)
1437    
1438     void glTranslate (float x, float y, float z = 0.)
1439     CODE:
1440     glTranslatef (x, y, z);
1441    
1442 root 1.62 void glScale (float x, float y, float z = 1.)
1443 root 1.54 CODE:
1444     glScalef (x, y, z);
1445    
1446     void glRotate (float angle, float x, float y, float z)
1447     CODE:
1448     glRotatef (angle, x, y, z);
1449    
1450     void glBegin (int mode)
1451    
1452     void glEnd ()
1453    
1454     void glColor (float r, float g, float b, float a = 1.0)
1455     PROTOTYPE: @
1456     CODE:
1457     glColor4f (r, g, b, a);
1458    
1459     void glVertex (float x, float y, float z = 0.)
1460     CODE:
1461     glVertex3f (x, y, z);
1462    
1463     void glTexCoord (float s, float t)
1464     CODE:
1465     glTexCoord2f (s, t);
1466    
1467     void glTexEnv (int target, int pname, float param)
1468     CODE:
1469     glTexEnvf (target, pname, param);
1470    
1471     void glTexParameter (int target, int pname, float param)
1472     CODE:
1473     glTexParameterf (target, pname, param);
1474    
1475     void glBindTexture (int target, int name)
1476    
1477     void glConvolutionParameter (int target, int pname, float params)
1478     CODE:
1479 root 1.64 GL_CALL (PFNGLCONVOLUTIONPARAMETERFEXTPROC, glConvolutionParameterf, (target, pname, params));
1480 root 1.54
1481     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1482 root 1.64 CODE:
1483     GL_CALL (PFNGLCONVOLUTIONFILTER2DEXTPROC, glConvolutionFilter2D,
1484     (target, internalformat, width, height, format, type, data));
1485 root 1.54
1486     void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1487    
1488     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1489    
1490     int glGenTexture ()
1491     CODE:
1492     {
1493     GLuint name;
1494     glGenTextures (1, &name);
1495     RETVAL = name;
1496     }
1497     OUTPUT:
1498     RETVAL
1499    
1500     void glDeleteTexture (int name)
1501     CODE:
1502     {
1503     GLuint name_ = name;
1504     glDeleteTextures (1, &name_);
1505     }
1506    
1507     int glGenList ()
1508     CODE:
1509     RETVAL = glGenLists (1);
1510     OUTPUT:
1511     RETVAL
1512    
1513     void glDeleteList (int list)
1514     CODE:
1515     glDeleteLists (list, 1);
1516    
1517     void glNewList (int list, int mode = GL_COMPILE)
1518    
1519     void glEndList ()
1520    
1521     void glCallList (int list)
1522