ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.173
Committed: Wed Apr 4 02:43:29 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.172: +1 -1 lines
Log Message:
support new tileset negotiation

File Contents

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