ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.174
Committed: Fri Apr 6 07:45:34 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.173: +98 -82 lines
Log Message:
- changed most db accesses to be asynchronous
  (this was way more difficult than anticipated)
- face id allocation is still synchronous (and has to be as long as
  we want to allow multiple instances running in parallel)
- facemap is cached locally, so subsequent accesses are fast
- the alternative would be to store faceids, not tileids, in the
  in-memory map, but then mapcache tiles are non-displayable
  unless the server already sent them.
- tile loading and map cache load/store are fully asynchronous
- replaced 32x32 dialogue and noface images by 64 bit versions
- properly scale special dialogue/noface textures to tilesize

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