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