ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.199
Committed: Tue Jul 17 13:53:02 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.198: +34 -0 lines
Log Message:
tolerate implementation texture size limits, up to a limit, or so

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