ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.167
Committed: Sat Dec 9 02:21:25 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.166: +21 -4 lines
Log Message:
- slightly cleaned up and "outsourced" components
- completely rewrote keybind bindings
  - not functional yet
  - buggy a shell
  - hits perlbug

File Contents

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