ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.70
Committed: Sun Apr 30 09:21:47 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.69: +5 -3 lines
Log Message:
*** empty log message ***

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.68 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
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 root 1.70
463 root 1.53 switch (ev.type)
464     {
465     case SDL_KEYDOWN:
466     case SDL_KEYUP:
467     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
468     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
469     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
470     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
471     break;
472    
473     case SDL_ACTIVEEVENT:
474     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
475     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
476     break;
477    
478     case SDL_MOUSEMOTION:
479     hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
480     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
481     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
482     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
483     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
484     break;
485    
486     case SDL_MOUSEBUTTONDOWN:
487     case SDL_MOUSEBUTTONUP:
488     hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
489     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
490     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
491     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
492 root 1.70 break;
493 root 1.53 }
494    
495     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
496     }
497     }
498 root 1.52
499     int
500     Mix_OpenAudio (int frequency = 22050, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 512)
501 root 1.56 POSTCALL:
502     Mix_HookMusicFinished (music_finished);
503 root 1.52
504     void
505     Mix_CloseAudio ()
506    
507     int
508     Mix_AllocateChannels (int numchans = -1)
509    
510 root 1.10 void
511     lowdelay (int fd, int val = 1)
512     CODE:
513 root 1.48 #ifndef _WIN32
514 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
515 root 1.48 #endif
516 root 1.10
517 root 1.3 char *
518 root 1.4 gl_version ()
519     CODE:
520 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
521 root 1.4 OUTPUT:
522     RETVAL
523    
524     char *
525 root 1.3 gl_extensions ()
526     CODE:
527 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
528 root 1.3 OUTPUT:
529     RETVAL
530    
531 root 1.5 void
532 root 1.13 add_font (char *file)
533     CODE:
534     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
535    
536     void
537 root 1.23 load_image_inline (SV *image_)
538     ALIAS:
539     load_image_file = 1
540     PPCODE:
541     {
542     STRLEN image_len;
543     char *image = (char *)SvPVbyte (image_, image_len);
544     SDL_Surface *surface, *surface2;
545     SDL_PixelFormat fmt;
546     SDL_RWops *rw = ix
547     ? SDL_RWFromFile (image, "r")
548     : SDL_RWFromConstMem (image, image_len);
549    
550     if (!rw)
551 root 1.41 croak ("load_image: %s", SDL_GetError ());
552 root 1.23
553     surface = IMG_Load_RW (rw, 1);
554     if (!surface)
555 root 1.41 croak ("load_image: %s", SDL_GetError ());
556 root 1.23
557     fmt.palette = NULL;
558     fmt.BitsPerPixel = 32;
559     fmt.BytesPerPixel = 4;
560 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
561 root 1.23 fmt.Rmask = 0x000000ff;
562     fmt.Gmask = 0x0000ff00;
563     fmt.Bmask = 0x00ff0000;
564     fmt.Amask = 0xff000000;
565 root 1.49 #else
566     fmt.Rmask = 0xff000000;
567     fmt.Gmask = 0x00ff0000;
568     fmt.Bmask = 0x0000ff00;
569     fmt.Amask = 0x000000ff;
570     #endif
571 root 1.23 fmt.Rloss = 0;
572     fmt.Gloss = 0;
573     fmt.Bloss = 0;
574     fmt.Aloss = 0;
575     fmt.Rshift = 0;
576     fmt.Gshift = 8;
577     fmt.Bshift = 16;
578     fmt.Ashift = 24;
579     fmt.colorkey = 0;
580     fmt.alpha = 0;
581    
582     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
583    
584 root 1.39 assert (surface2->pitch == surface2->w * 4);
585    
586 root 1.23 EXTEND (SP, 5);
587     PUSHs (sv_2mortal (newSViv (surface2->w)));
588     PUSHs (sv_2mortal (newSViv (surface2->h)));
589     SDL_LockSurface (surface2);
590     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
591     SDL_UnlockSurface (surface2);
592 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
593 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
594 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
595 root 1.23
596     SDL_FreeSurface (surface);
597     SDL_FreeSurface (surface2);
598     }
599    
600 root 1.25 void
601 root 1.39 average (int x, int y, uint32_t *data)
602     PPCODE:
603     {
604     uint32_t r = 0, g = 0, b = 0, a = 0;
605    
606     x = y = x * y;
607    
608     while (x--)
609     {
610     uint32_t p = *data++;
611    
612     r += (p ) & 255;
613     g += (p >> 8) & 255;
614     b += (p >> 16) & 255;
615     a += (p >> 24) & 255;
616     }
617    
618     EXTEND (SP, 4);
619 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
620     PUSHs (sv_2mortal (newSViv (g / y)));
621     PUSHs (sv_2mortal (newSViv (b / y)));
622     PUSHs (sv_2mortal (newSViv (a / y)));
623 root 1.39 }
624    
625     void
626 root 1.66 error (char *message)
627     CODE:
628     #ifdef _WIN32
629     MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
630     #else
631     fprintf (stderr, "ERROR: %s\n", message);
632     #endif
633    
634     void
635 root 1.25 fatal (char *message)
636     CODE:
637 root 1.50 #ifdef _WIN32
638 root 1.25 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
639     #else
640 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
641 root 1.25 #endif
642     exit (1);
643    
644 root 1.61 MODULE = CFClient PACKAGE = CFClient::Font
645    
646     CFClient::Font
647 root 1.70 new_from_file (SV *class, char *path, int id = 0)
648 root 1.61 CODE:
649     {
650     int count;
651 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
652 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
653     FcPatternDestroy (pattern);
654     }
655     OUTPUT:
656     RETVAL
657    
658     void
659     DESTROY (CFClient::Font self)
660     CODE:
661     pango_font_description_free (self);
662    
663     void
664     make_default (CFClient::Font self)
665     CODE:
666     default_font = self;
667    
668 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
669 root 1.14
670 root 1.15 CFClient::Layout
671 root 1.61 new (SV *class, int base_height = MIN_FONT_HEIGHT)
672 root 1.14 CODE:
673     New (0, RETVAL, 1, struct cf_layout);
674 root 1.61 RETVAL->pl = pango_layout_new (context);
675 root 1.14 RETVAL->base_height = base_height;
676 root 1.61 RETVAL->font = 0;
677 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
678 root 1.61 pango_layout_set_font_description (RETVAL->pl, default_font);
679 root 1.14 OUTPUT:
680     RETVAL
681    
682     void
683 root 1.15 DESTROY (CFClient::Layout self)
684 root 1.14 CODE:
685     g_object_unref (self->pl);
686     Safefree (self);
687 root 1.13
688 root 1.8 void
689 root 1.35 set_text (CFClient::Layout self, SV *text_)
690     CODE:
691     {
692     STRLEN textlen;
693     char *text = SvPVutf8 (text_, textlen);
694    
695     pango_layout_set_text (self->pl, text, textlen);
696     }
697    
698     void
699 root 1.15 set_markup (CFClient::Layout self, SV *text_)
700 root 1.14 CODE:
701 root 1.5 {
702     STRLEN textlen;
703     char *text = SvPVutf8 (text_, textlen);
704 root 1.14
705     pango_layout_set_markup (self->pl, text, textlen);
706     }
707    
708 root 1.46 SV *
709     get_text (CFClient::Layout self)
710     CODE:
711 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
712 root 1.46 SvUTF8_on (RETVAL);
713     OUTPUT:
714     RETVAL
715    
716 root 1.14 void
717 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
718     CODE:
719     if (self->font != font)
720     {
721     self->font = font;
722     layout_update_font (self);
723     }
724    
725     void
726 root 1.16 set_height (CFClient::Layout self, int base_height)
727     CODE:
728 root 1.61 if (self->base_height != base_height)
729     {
730     self->base_height = base_height;
731     layout_update_font (self);
732     }
733 root 1.16
734     void
735 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
736 root 1.14 CODE:
737     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
738    
739     void
740 root 1.15 size (CFClient::Layout self)
741 root 1.14 PPCODE:
742     {
743     int w, h;
744    
745     layout_get_pixel_size (self, &w, &h);
746    
747     EXTEND (SP, 2);
748     PUSHs (sv_2mortal (newSViv (w)));
749     PUSHs (sv_2mortal (newSViv (h)));
750     }
751    
752 root 1.17 int
753     xy_to_index (CFClient::Layout self, int x, int y)
754     CODE:
755     {
756     int index, trailing;
757     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
758     RETVAL = index;
759     }
760     OUTPUT:
761     RETVAL
762    
763     void
764     cursor_pos (CFClient::Layout self, int index)
765     PPCODE:
766     {
767     PangoRectangle strong_pos;
768     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
769 root 1.30
770 root 1.17 EXTEND (SP, 3);
771     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
772     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
773     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
774     }
775    
776 root 1.14 void
777 root 1.15 render (CFClient::Layout self)
778 root 1.14 PPCODE:
779     {
780 root 1.5 SV *retval;
781     int w, h;
782     FT_Bitmap bitmap;
783    
784 root 1.14 layout_get_pixel_size (self, &w, &h);
785 root 1.5
786     retval = newSV (w * h);
787     SvPOK_only (retval);
788     SvCUR_set (retval, w * h);
789    
790     bitmap.rows = h;
791     bitmap.width = w;
792     bitmap.pitch = w;
793     bitmap.buffer = (unsigned char*)SvPVX (retval);
794     bitmap.num_grays = 256;
795     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
796    
797     memset (bitmap.buffer, 0, w * h);
798    
799 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
800 root 1.1
801 root 1.5 EXTEND (SP, 3);
802     PUSHs (sv_2mortal (newSViv (w)));
803     PUSHs (sv_2mortal (newSViv (h)));
804     PUSHs (sv_2mortal (retval));
805     }
806 root 1.11
807 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
808 root 1.11
809     void
810 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
811 root 1.12 PROTOTYPE: $$$;$$
812 root 1.11 CODE:
813     {
814 root 1.12 HV *hv = (HV *)SvRV (self);
815 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
816     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
817 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
818 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
819 root 1.12
820     if (items < 5)
821     {
822 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
823     h = SvNV (*hv_fetch (hv, "h", 1, 1));
824 root 1.12 }
825    
826     glBindTexture (GL_TEXTURE_2D, name);
827 elmex 1.36 if (wrap_mode) {
828     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
829     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
830     }
831 root 1.12 glBegin (GL_QUADS);
832 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
833     glTexCoord2f (0, t); glVertex2f (x , y + h);
834     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
835     glTexCoord2f (s, 0); glVertex2f (x + w, y );
836 root 1.12 glEnd ();
837 root 1.11 }
838 root 1.28
839     MODULE = CFClient PACKAGE = CFClient::Map
840    
841     CFClient::Map
842     new (SV *class, int map_width, int map_height)
843     CODE:
844     New (0, RETVAL, 1, struct map);
845 root 1.42 RETVAL->x = 0;
846     RETVAL->y = 0;
847     RETVAL->w = map_width;
848     RETVAL->h = map_height;
849     RETVAL->ox = 0;
850     RETVAL->oy = 0;
851 root 1.30 RETVAL->faces = 8192;
852     Newz (0, RETVAL->face, RETVAL->faces, mapface);
853 root 1.42 RETVAL->texs = 8192;
854     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
855 root 1.28 RETVAL->rows = 0;
856     RETVAL->row = 0;
857     OUTPUT:
858     RETVAL
859    
860     void
861     DESTROY (CFClient::Map self)
862     CODE:
863     {
864 root 1.30 map_clear (self);
865 root 1.28 Safefree (self->face);
866 root 1.29 Safefree (self);
867     }
868    
869     void
870 root 1.30 clear (CFClient::Map self)
871     CODE:
872     map_clear (self);
873    
874     void
875 root 1.42 set_face (CFClient::Map self, int face, int texid)
876 root 1.29 CODE:
877     {
878 root 1.42 while (self->faces <= face)
879 root 1.28 {
880 root 1.30 Append (mapface, self->face, self->faces, self->faces);
881 root 1.29 self->faces *= 2;
882     }
883 root 1.28
884 root 1.42 self->face [face] = texid;
885     }
886    
887     void
888     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)
889     CODE:
890     {
891     while (self->texs <= texid)
892     {
893     Append (maptex, self->tex, self->texs, self->texs);
894     self->texs *= 2;
895     }
896    
897 root 1.48 {
898     maptex *tex = self->tex + texid;
899 root 1.39
900 root 1.48 tex->name = name;
901     tex->w = w;
902     tex->h = h;
903     tex->s = s;
904     tex->t = t;
905     tex->r = r;
906     tex->g = g;
907     tex->b = b;
908     tex->a = a;
909     }
910 root 1.29 }
911    
912 root 1.42 int
913     ox (CFClient::Map self)
914     ALIAS:
915     oy = 1
916     CODE:
917     switch (ix)
918     {
919     case 0: RETVAL = self->ox; break;
920     case 1: RETVAL = self->oy; break;
921     }
922     OUTPUT:
923     RETVAL
924    
925 root 1.29 void
926 root 1.43 scroll (CFClient::Map self, int dx, int dy)
927     CODE:
928     {
929 root 1.44 if (dx > 0)
930     map_blank (self, self->x, self->y, dx - 1, self->h);
931     else if (dx < 0)
932     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
933    
934     if (dy > 0)
935     map_blank (self, self->x, self->y, self->w, dy - 1);
936     else if (dy < 0)
937     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
938 root 1.43
939 root 1.44 self->ox += dx; self->x += dx;
940     self->oy += dy; self->y += dy;
941 root 1.43
942     while (self->y < 0)
943     {
944     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
945    
946     self->rows += MAP_EXTEND_Y;
947     self->y += MAP_EXTEND_Y;
948     }
949 root 1.44 }
950 root 1.43
951 root 1.44 void
952     map1a_update (CFClient::Map self, SV *data_)
953     CODE:
954     {
955 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
956     uint8_t *data_end = (uint8_t *)SvEND (data_);
957 root 1.48 mapcell *cell;
958     int x, y, flags;
959 root 1.43
960 root 1.29 while (data < data_end)
961     {
962 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
963 root 1.30
964 root 1.48 x = ((flags >> 10) & 63) + self->x;
965     y = ((flags >> 4) & 63) + self->y;
966 root 1.29
967 root 1.48 cell = map_get_cell (self, x, y);
968 root 1.29
969     if (flags & 15)
970     {
971 root 1.45 if (cell->darkness < 0)
972 root 1.29 {
973     cell->darkness = 0;
974     cell->face [0] = 0;
975     cell->face [1] = 0;
976     cell->face [2] = 0;
977     }
978 root 1.45
979 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
980    
981 root 1.42 //TODO: don't trust server data to be in-range(!)
982    
983 root 1.29 if (flags & 4)
984     {
985 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
986 root 1.29 }
987    
988     if (flags & 2)
989     {
990 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
991 root 1.29 }
992    
993     if (flags & 1)
994     {
995 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
996 root 1.29 }
997     }
998     else
999 root 1.31 cell->darkness = -1;
1000 root 1.29 }
1001 root 1.28 }
1002    
1003 root 1.40 SV *
1004 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1005 root 1.40 CODE:
1006     {
1007 root 1.55 int x1, x;
1008     int y1, y;
1009 root 1.40 int z;
1010     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1011     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1012    
1013     SvPOK_only (map_sv);
1014     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1015    
1016 root 1.55 x0 += self->x; x1 = x0 + w;
1017     y0 += self->y; y1 = y0 + h;
1018 root 1.40
1019     for (y = y0; y < y1; y++)
1020     {
1021     maprow *row = 0 <= y && y < self->rows
1022     ? self->row + y
1023     : 0;
1024    
1025     for (x = x0; x < x1; x++)
1026     {
1027     int r = 32, g = 32, b = 32, a = 192;
1028    
1029     if (row && row->c0 <= x && x < row->c1)
1030     {
1031     mapcell *cell = row->col + (x - row->c0);
1032    
1033     for (z = 0; z <= 0; z++)
1034     {
1035 root 1.42 mapface face = cell->face [z];
1036 root 1.40
1037     if (face)
1038     {
1039 root 1.42 maptex tex = self->tex [face];
1040 root 1.40 int a0 = 255 - tex.a;
1041     int a1 = tex.a;
1042    
1043     r = (r * a0 + tex.r * a1) / 255;
1044     g = (g * a0 + tex.g * a1) / 255;
1045     b = (b * a0 + tex.b * a1) / 255;
1046     a = (a * a0 + tex.a * a1) / 255;
1047     }
1048     }
1049     }
1050    
1051     *map++ = (r )
1052     | (g << 8)
1053     | (b << 16)
1054     | (a << 24);
1055     }
1056     }
1057    
1058     RETVAL = map_sv;
1059     }
1060     OUTPUT:
1061     RETVAL
1062    
1063 root 1.30 void
1064 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1065 root 1.32 PPCODE:
1066 root 1.30 {
1067 root 1.48 int vx, vy;
1068     int x, y, z;
1069     int last_name;
1070     mapface face;
1071 root 1.32 int sw4 = (sw + 3) & ~3;
1072     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1073 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1074 root 1.48
1075 root 1.42 memset (darkness, 255, sw4 * sh);
1076 root 1.32 SvPOK_only (darkness_sv);
1077     SvCUR_set (darkness_sv, sw4 * sh);
1078    
1079 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1080     vy = self->y + (self->h - sh) / 2 - shift_y;
1081 root 1.38
1082 root 1.42 /*
1083     int vx = self->vx = self->w >= sw
1084     ? self->x + (self->w - sw) / 2
1085     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1086    
1087     int vy = self->vy = self->h >= sh
1088     ? self->y + (self->h - sh) / 2
1089     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1090     */
1091 root 1.30
1092     glColor4ub (255, 255, 255, 255);
1093    
1094     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1095     glEnable (GL_BLEND);
1096     glEnable (GL_TEXTURE_2D);
1097     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1098    
1099 root 1.48 glBegin (GL_QUADS);
1100 root 1.30
1101 root 1.48 last_name = 0;
1102 root 1.30
1103     for (z = 0; z < 3; z++)
1104     for (y = 0; y < sh; y++)
1105     if (0 <= y + vy && y + vy < self->rows)
1106     {
1107     maprow *row = self->row + (y + vy);
1108    
1109     for (x = 0; x < sw; x++)
1110     if (row->c0 <= x + vx && x + vx < row->c1)
1111     {
1112     mapcell *cell = row->col + (x + vx - row->c0);
1113 root 1.32
1114     darkness[y * sw4 + x] = cell->darkness < 0
1115 root 1.33 ? 255 - FOW_DARKNESS
1116 root 1.32 : 255 - cell->darkness;
1117    
1118 root 1.48 face = cell->face [z];
1119 root 1.30
1120     if (face)
1121     {
1122 root 1.42 maptex tex = self->tex [face];
1123 root 1.30
1124     int px = (x + 1) * 32 - tex.w;
1125     int py = (y + 1) * 32 - tex.h;
1126    
1127     if (last_name != tex.name)
1128     {
1129     glEnd ();
1130     last_name = tex.name;
1131     glBindTexture (GL_TEXTURE_2D, last_name);
1132     glBegin (GL_QUADS);
1133     }
1134    
1135     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1136     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1137     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1138     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1139     }
1140     }
1141     }
1142    
1143     glEnd ();
1144 root 1.32
1145 root 1.34 glDisable (GL_TEXTURE_2D);
1146     glDisable (GL_BLEND);
1147    
1148 root 1.32 EXTEND (SP, 3);
1149     PUSHs (sv_2mortal (newSViv (sw4)));
1150     PUSHs (sv_2mortal (newSViv (sh)));
1151     PUSHs (darkness_sv);
1152 root 1.30 }
1153    
1154 root 1.42 SV *
1155     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1156     CODE:
1157     {
1158     int x, y, x1, y1;
1159     SV *data_sv = newSV (w * h * 7 + 5);
1160     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1161    
1162     *data++ = 0; /* version 0 format */
1163     *data++ = w >> 8; *data++ = w;
1164     *data++ = h >> 8; *data++ = h;
1165    
1166     // we need to do this 'cause we don't keep an absolute coord system for rows
1167 root 1.55 // TODO: treat rows as we treat columns
1168 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1169     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1170    
1171     x0 += self->x - self->ox;
1172     y0 += self->y - self->oy;
1173    
1174     x1 = x0 + w;
1175     y1 = y0 + h;
1176    
1177     for (y = y0; y < y1; y++)
1178     {
1179     maprow *row = 0 <= y && y < self->rows
1180     ? self->row + y
1181     : 0;
1182    
1183     for (x = x0; x < x1; x++)
1184     {
1185     if (row && row->c0 <= x && x < row->c1)
1186     {
1187     mapcell *cell = row->col + (x - row->c0);
1188     uint8_t flags = 0;
1189    
1190     if (cell->face [0]) flags |= 1;
1191     if (cell->face [1]) flags |= 2;
1192     if (cell->face [2]) flags |= 4;
1193    
1194     *data++ = flags;
1195    
1196     if (flags & 1)
1197     {
1198     *data++ = cell->face [0] >> 8;
1199     *data++ = cell->face [0];
1200     }
1201    
1202     if (flags & 2)
1203     {
1204     *data++ = cell->face [1] >> 8;
1205     *data++ = cell->face [1];
1206     }
1207    
1208     if (flags & 4)
1209     {
1210     *data++ = cell->face [2] >> 8;
1211     *data++ = cell->face [2];
1212     }
1213     }
1214     else
1215     *data++ = 0;
1216     }
1217     }
1218    
1219     SvPOK_only (data_sv);
1220     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1221     RETVAL = data_sv;
1222     }
1223     OUTPUT:
1224     RETVAL
1225    
1226     void
1227     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1228     PPCODE:
1229     {
1230     int x, y, z;
1231 root 1.48 int w, h;
1232 root 1.42 int x1, y1;
1233    
1234     if (*data++ != 0)
1235     return; /* version mismatch */
1236    
1237 root 1.48 w = *data++ << 8; w |= *data++;
1238     h = *data++ << 8; h |= *data++;
1239 root 1.42
1240     // we need to do this 'cause we don't keep an absolute coord system for rows
1241 root 1.55 // TODO: treat rows as we treat columns
1242 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1243     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1244    
1245     x0 += self->x - self->ox;
1246     y0 += self->y - self->oy;
1247    
1248     x1 = x0 + w;
1249     y1 = y0 + h;
1250    
1251     for (y = y0; y < y1; y++)
1252     {
1253     maprow *row = map_get_row (self, y);
1254    
1255     for (x = x0; x < x1; x++)
1256     {
1257     uint8_t flags = *data++;
1258    
1259     if (flags)
1260     {
1261     mapface face[3] = { 0, 0, 0 };
1262    
1263     mapcell *cell = row_get_cell (row, x);
1264    
1265     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1266     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1267     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1268    
1269     if (cell->darkness <= 0)
1270     {
1271     cell->darkness = -1;
1272    
1273     for (z = 0; z <= 2; z++)
1274     {
1275     cell->face[z] = face[z];
1276    
1277     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1278     XPUSHs (sv_2mortal (newSViv (face[z])));
1279     }
1280     }
1281     }
1282     }
1283     }
1284     }
1285    
1286 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1287    
1288     CFClient::MixChunk
1289     new_from_file (SV *class, char *path)
1290     CODE:
1291     RETVAL = Mix_LoadWAV (path);
1292     OUTPUT:
1293     RETVAL
1294    
1295     void
1296     DESTROY (CFClient::MixChunk self)
1297     CODE:
1298     Mix_FreeChunk (self);
1299    
1300     int
1301     volume (CFClient::MixChunk self, int volume = -1)
1302     CODE:
1303     RETVAL = Mix_VolumeChunk (self, volume);
1304     OUTPUT:
1305     RETVAL
1306    
1307     int
1308     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1309     CODE:
1310     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1311     OUTPUT:
1312     RETVAL
1313    
1314     MODULE = CFClient PACKAGE = CFClient::MixMusic
1315    
1316     int
1317     volume (int volume = -1)
1318     CODE:
1319     RETVAL = Mix_VolumeMusic (volume);
1320     OUTPUT:
1321     RETVAL
1322    
1323     CFClient::MixMusic
1324     new_from_file (SV *class, char *path)
1325     CODE:
1326     RETVAL = Mix_LoadMUS (path);
1327     OUTPUT:
1328     RETVAL
1329    
1330     void
1331     DESTROY (CFClient::MixMusic self)
1332     CODE:
1333     Mix_FreeMusic (self);
1334    
1335     int
1336     play (CFClient::MixMusic self, int loops = -1)
1337     CODE:
1338     RETVAL = Mix_PlayMusic (self, loops);
1339     OUTPUT:
1340     RETVAL
1341    
1342 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1343    
1344     BOOT:
1345     {
1346     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1347     static const struct {
1348     const char *name;
1349     IV iv;
1350     } *civ, const_iv[] = {
1351     # define const_iv(name) { # name, (IV)name }
1352     const_iv (GL_COLOR_MATERIAL),
1353     const_iv (GL_SMOOTH),
1354     const_iv (GL_FLAT),
1355 root 1.69 const_iv (GL_DITHER),
1356 root 1.54 const_iv (GL_BLEND),
1357 root 1.69 const_iv (GL_SCISSOR_TEST),
1358 root 1.54 const_iv (GL_AND),
1359 root 1.67 const_iv (GL_ONE),
1360     const_iv (GL_ZERO),
1361 root 1.54 const_iv (GL_SRC_ALPHA),
1362 root 1.67 const_iv (GL_SRC_ALPHA_SATURATE),
1363 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1364 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1365 root 1.54 const_iv (GL_RGB),
1366     const_iv (GL_RGBA),
1367     const_iv (GL_UNSIGNED_BYTE),
1368     const_iv (GL_ALPHA),
1369     const_iv (GL_FLOAT),
1370     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1371     const_iv (GL_COMPILE),
1372     const_iv (GL_TEXTURE_1D),
1373     const_iv (GL_TEXTURE_2D),
1374     const_iv (GL_TEXTURE_ENV),
1375     const_iv (GL_TEXTURE_MAG_FILTER),
1376     const_iv (GL_TEXTURE_MIN_FILTER),
1377     const_iv (GL_TEXTURE_ENV_MODE),
1378     const_iv (GL_TEXTURE_WRAP_S),
1379     const_iv (GL_TEXTURE_WRAP_T),
1380     const_iv (GL_CLAMP),
1381     const_iv (GL_REPEAT),
1382     const_iv (GL_NEAREST),
1383     const_iv (GL_LINEAR),
1384 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1385     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1386     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1387     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1388     const_iv (GL_GENERATE_MIPMAP),
1389 root 1.54 const_iv (GL_MODULATE),
1390 root 1.69 const_iv (GL_DECAL),
1391 root 1.54 const_iv (GL_REPLACE),
1392     const_iv (GL_COLOR_BUFFER_BIT),
1393     const_iv (GL_PROJECTION),
1394     const_iv (GL_MODELVIEW),
1395     const_iv (GL_COLOR_LOGIC_OP),
1396 root 1.69 const_iv (GL_SEPARABLE_2D),
1397 root 1.54 const_iv (GL_CONVOLUTION_2D),
1398     const_iv (GL_CONVOLUTION_BORDER_MODE),
1399     const_iv (GL_CONSTANT_BORDER),
1400     const_iv (GL_LINES),
1401     const_iv (GL_QUADS),
1402 root 1.55 const_iv (GL_LINE_LOOP),
1403 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1404     const_iv (GL_FASTEST),
1405     # undef const_iv
1406     };
1407    
1408     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1409     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1410     }
1411    
1412     int glGetError ()
1413    
1414     void glClear (int mask)
1415    
1416     void glClearColor (float r, float g, float b, float a = 1.0)
1417     PROTOTYPE: @
1418    
1419     void glEnable (int cap)
1420    
1421     void glDisable (int cap)
1422    
1423     void glShadeModel (int mode)
1424    
1425     void glHint (int target, int mode)
1426    
1427     void glBlendFunc (int sfactor, int dfactor)
1428    
1429     void glLogicOp (int opcode)
1430    
1431 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1432    
1433 root 1.54 void glMatrixMode (int mode)
1434    
1435     void glPushMatrix ()
1436    
1437     void glPopMatrix ()
1438    
1439     void glLoadIdentity ()
1440    
1441 root 1.64 # near and far are due to microsofts buggy c compiler
1442     void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1443 root 1.54
1444     void glViewport (int x, int y, int width, int height)
1445    
1446 root 1.69 void glScissor (int x, int y, int width, int height)
1447    
1448 root 1.54 void glTranslate (float x, float y, float z = 0.)
1449     CODE:
1450     glTranslatef (x, y, z);
1451    
1452 root 1.62 void glScale (float x, float y, float z = 1.)
1453 root 1.54 CODE:
1454     glScalef (x, y, z);
1455    
1456     void glRotate (float angle, float x, float y, float z)
1457     CODE:
1458     glRotatef (angle, x, y, z);
1459    
1460     void glBegin (int mode)
1461    
1462     void glEnd ()
1463    
1464     void glColor (float r, float g, float b, float a = 1.0)
1465     PROTOTYPE: @
1466     CODE:
1467 root 1.70 glColor4ub (r * 255., g * 255., b * 255., a * 255.);
1468 root 1.54
1469     void glVertex (float x, float y, float z = 0.)
1470     CODE:
1471     glVertex3f (x, y, z);
1472    
1473     void glTexCoord (float s, float t)
1474     CODE:
1475     glTexCoord2f (s, t);
1476    
1477     void glTexEnv (int target, int pname, float param)
1478     CODE:
1479     glTexEnvf (target, pname, param);
1480    
1481     void glTexParameter (int target, int pname, float param)
1482     CODE:
1483     glTexParameterf (target, pname, param);
1484    
1485     void glBindTexture (int target, int name)
1486    
1487     void glConvolutionParameter (int target, int pname, float params)
1488     CODE:
1489 root 1.64 GL_CALL (PFNGLCONVOLUTIONPARAMETERFEXTPROC, glConvolutionParameterf, (target, pname, params));
1490 root 1.54
1491     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1492 root 1.64 CODE:
1493     GL_CALL (PFNGLCONVOLUTIONFILTER2DEXTPROC, glConvolutionFilter2D,
1494     (target, internalformat, width, height, format, type, data));
1495 root 1.54
1496 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1497     CODE:
1498     GL_CALL (PFNGLSEPARABLEFILTER2DEXTPROC, glSeparableFilter2D,
1499     (target, internalformat, width, height, format, type, row, column));
1500    
1501 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1502    
1503     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1504    
1505 root 1.68 void glRasterPos (int x, int y)
1506     CODE:
1507     glRasterPos2i (x, y);
1508    
1509     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1510    
1511 root 1.54 int glGenTexture ()
1512     CODE:
1513     {
1514     GLuint name;
1515     glGenTextures (1, &name);
1516     RETVAL = name;
1517     }
1518     OUTPUT:
1519     RETVAL
1520    
1521     void glDeleteTexture (int name)
1522     CODE:
1523     {
1524     GLuint name_ = name;
1525     glDeleteTextures (1, &name_);
1526     }
1527    
1528     int glGenList ()
1529     CODE:
1530     RETVAL = glGenLists (1);
1531     OUTPUT:
1532     RETVAL
1533    
1534     void glDeleteList (int list)
1535     CODE:
1536     glDeleteLists (list, 1);
1537    
1538     void glNewList (int list, int mode = GL_COMPILE)
1539    
1540     void glEndList ()
1541    
1542     void glCallList (int list)
1543