ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.206
Committed: Thu Jul 19 23:29:16 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.205: +7 -0 lines
Log Message:
*** empty log message ***

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