ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.56
Committed: Thu Apr 20 09:13:31 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.55: +15 -0 lines
Log Message:
bg music loop

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2     # include <malloc.h>
3     #endif
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.5 #include <string.h>
10 root 1.25 #include <stdio.h>
11 root 1.5
12 root 1.2 #include <SDL.h>
13 root 1.23 #include <SDL_image.h>
14 root 1.52 #include <SDL_mixer.h>
15 root 1.3 #include <SDL_opengl.h>
16 root 1.5
17 root 1.30 #include <glib/gmacros.h>
18    
19 root 1.5 #include <pango/pango.h>
20 root 1.10 #include <pango/pangofc-fontmap.h>
21 root 1.5 #include <pango/pangoft2.h>
22    
23 root 1.48 #ifndef _WIN32
24     # include <sys/types.h>
25     # include <sys/socket.h>
26     # include <netinet/in.h>
27     # include <netinet/tcp.h>
28     # include <inttypes.h>
29     #else
30     typedef unsigned char uint8_t;
31     typedef unsigned short uint16_t;
32     typedef unsigned int uint32_t;
33     typedef signed char int8_t;
34     typedef signed short int16_t;
35     typedef signed int int32_t;
36     #endif
37 root 1.28
38 root 1.29 #define FOW_DARKNESS 32
39    
40     #define MAP_EXTEND_X 32
41     #define MAP_EXTEND_Y 512
42    
43 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
44     typedef Mix_Music *CFClient__MixMusic;
45    
46 root 1.5 static PangoContext *context;
47     static PangoFontMap *fontmap;
48 root 1.2
49 root 1.14 typedef struct cf_layout {
50     PangoLayout *pl;
51     int base_height;
52 root 1.15 } *CFClient__Layout;
53 root 1.14
54     static void
55 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
56     {
57 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
58 root 1.35 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
59 root 1.19 }
60    
61     static void
62 root 1.17 layout_update (CFClient__Layout self)
63     {
64 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
65     * reasonably well with bitstream vera
66     */
67 root 1.17 PangoFontDescription *font = pango_context_get_font_description (context);
68 root 1.46
69     int height = self->base_height * (PANGO_SCALE * 8 / 10);
70    
71     if (pango_font_description_get_size (font) != height)
72     {
73     pango_font_description_set_absolute_size (font, height);
74     pango_layout_context_changed (self->pl);
75     }
76 root 1.17 }
77    
78     static void
79 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
80 root 1.14 {
81 root 1.19 layout_update (self);
82 root 1.16
83 root 1.14 pango_layout_get_pixel_size (self->pl, w, h);
84    
85     *w = (*w + 3) & ~3;
86     if (!*w) *w = 1;
87     if (!*h) *h = 1;
88     }
89    
90 root 1.42 typedef uint16_t mapface;
91    
92 root 1.28 typedef struct {
93 root 1.30 GLint name;
94     int w, h;
95     float s, t;
96 root 1.39 uint8_t r, g, b, a;
97 root 1.42 } maptex;
98 root 1.30
99     typedef struct {
100 root 1.29 int16_t darkness;
101 root 1.42 mapface face[3];
102 root 1.28 } mapcell;
103    
104     typedef struct {
105 root 1.30 int32_t c0, c1;
106 root 1.28 mapcell *col;
107     } maprow;
108    
109     typedef struct map {
110     int x, y, w, h;
111 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
112 root 1.28 int faces;
113 root 1.30 mapface *face;
114 root 1.28
115 root 1.42 int texs;
116     maptex *tex;
117    
118 root 1.48 int32_t rows;
119 root 1.28 maprow *row;
120     } *CFClient__Map;
121    
122 root 1.30 static char *
123     prepend (char *ptr, int sze, int inc)
124     {
125     char *p;
126    
127     New (0, p, sze + inc, char);
128     Zero (p, inc, char);
129     Move (ptr, p + inc, sze, char);
130     Safefree (ptr);
131    
132     return p;
133     }
134    
135     static char *
136     append (char *ptr, int sze, int inc)
137     {
138     Renew (ptr, sze + inc, char);
139     Zero (ptr + sze, inc, char);
140    
141     return ptr;
142     }
143    
144     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
145     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
146    
147 root 1.42 static maprow *
148     map_get_row (CFClient__Map self, int y)
149     {
150     if (0 > y)
151     {
152     int extend = - y + MAP_EXTEND_Y;
153     Prepend (maprow, self->row, self->rows, extend);
154    
155     self->rows += extend;
156     self->y += extend;
157     y += extend;
158     }
159     else if (y >= self->rows)
160     {
161     int extend = y - self->rows + MAP_EXTEND_Y;
162     Append (maprow, self->row, self->rows, extend);
163     self->rows += extend;
164     }
165    
166     return self->row + y;
167     }
168    
169     static mapcell *
170     row_get_cell (maprow *row, int x)
171     {
172     if (!row->col)
173     {
174     Newz (0, row->col, MAP_EXTEND_X, mapcell);
175     row->c0 = x - MAP_EXTEND_X / 4;
176     row->c1 = row->c0 + MAP_EXTEND_X;
177     }
178    
179     if (row->c0 > x)
180     {
181     int extend = row->c0 - x + MAP_EXTEND_X;
182     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
183     row->c0 -= extend;
184     }
185     else if (x >= row->c1)
186     {
187     int extend = x - row->c1 + MAP_EXTEND_X;
188     Append (mapcell, row->col, row->c1 - row->c0, extend);
189     row->c1 += extend;
190     }
191    
192     return row->col + (x - row->c0);
193     }
194    
195     static mapcell *
196     map_get_cell (CFClient__Map self, int x, int y)
197     {
198     return row_get_cell (map_get_row (self, y), x);
199     }
200    
201 root 1.30 static void
202     map_clear (CFClient__Map self)
203     {
204     int r;
205    
206     for (r = 0; r < self->rows; r++)
207     Safefree (self->row[r].col);
208    
209     Safefree (self->row);
210    
211     self->x = 0;
212     self->y = 0;
213 root 1.42 self->ox = 0;
214     self->oy = 0;
215 root 1.30 self->row = 0;
216     self->rows = 0;
217     }
218    
219 root 1.29 static void
220     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
221     {
222     int x, y;
223 root 1.48 maprow *row;
224 root 1.29
225     for (y = y0; y < y0 + h; y++)
226 root 1.30 if (y >= 0)
227     {
228     if (y >= self->rows)
229     break;
230    
231 root 1.48 row = self->row + y;
232 root 1.30
233     for (x = x0; x < x0 + w; x++)
234     if (x >= row->c0)
235     {
236     if (x >= row->c1)
237     break;
238 root 1.29
239 root 1.31 row->col[x - row->c0].darkness = -1;
240 root 1.30 }
241     }
242 root 1.29 }
243    
244 root 1.56 static void
245     music_finished ()
246     {
247     SDL_UserEvent ev;
248    
249     ev.type = SDL_USEREVENT;
250     ev.code = 0;
251     ev.data1 = 0;
252     ev.data2 = 0;
253    
254     SDL_PushEvent (&ev);
255     }
256    
257 root 1.15 MODULE = CFClient PACKAGE = CFClient
258 root 1.1
259 root 1.11 PROTOTYPES: ENABLE
260    
261 root 1.5 BOOT:
262     {
263 root 1.51 HV *stash = gv_stashpv ("CFClient", 1);
264     static const struct {
265     const char *name;
266     IV iv;
267     } *civ, const_iv[] = {
268     # define const_iv(name) { # name, (IV)name }
269     const_iv (SDL_ACTIVEEVENT),
270     const_iv (SDL_KEYDOWN),
271     const_iv (SDL_KEYUP),
272     const_iv (SDL_MOUSEMOTION),
273     const_iv (SDL_MOUSEBUTTONDOWN),
274     const_iv (SDL_MOUSEBUTTONUP),
275     const_iv (SDL_JOYAXISMOTION),
276     const_iv (SDL_JOYBALLMOTION),
277     const_iv (SDL_JOYHATMOTION),
278     const_iv (SDL_JOYBUTTONDOWN),
279     const_iv (SDL_JOYBUTTONUP),
280     const_iv (SDL_QUIT),
281     const_iv (SDL_SYSWMEVENT),
282     const_iv (SDL_EVENT_RESERVEDA),
283     const_iv (SDL_EVENT_RESERVEDB),
284     const_iv (SDL_VIDEORESIZE),
285     const_iv (SDL_VIDEOEXPOSE),
286     const_iv (SDL_USEREVENT),
287     const_iv (SDLK_KP0),
288     const_iv (SDLK_KP1),
289     const_iv (SDLK_KP2),
290     const_iv (SDLK_KP3),
291     const_iv (SDLK_KP4),
292     const_iv (SDLK_KP5),
293     const_iv (SDLK_KP6),
294     const_iv (SDLK_KP7),
295     const_iv (SDLK_KP8),
296     const_iv (SDLK_KP9),
297     const_iv (SDLK_KP_PERIOD),
298     const_iv (SDLK_KP_DIVIDE),
299     const_iv (SDLK_KP_MULTIPLY),
300     const_iv (SDLK_KP_MINUS),
301     const_iv (SDLK_KP_PLUS),
302     const_iv (SDLK_KP_ENTER),
303     const_iv (SDLK_KP_EQUALS),
304     const_iv (SDLK_UP),
305     const_iv (SDLK_DOWN),
306     const_iv (SDLK_RIGHT),
307     const_iv (SDLK_LEFT),
308     const_iv (SDLK_INSERT),
309     const_iv (SDLK_HOME),
310     const_iv (SDLK_END),
311     const_iv (SDLK_PAGEUP),
312     const_iv (SDLK_PAGEDOWN),
313     const_iv (SDLK_F1),
314     const_iv (SDLK_F2),
315     const_iv (SDLK_F3),
316     const_iv (SDLK_F4),
317     const_iv (SDLK_F5),
318     const_iv (SDLK_F6),
319     const_iv (SDLK_F7),
320     const_iv (SDLK_F8),
321     const_iv (SDLK_F9),
322     const_iv (SDLK_F10),
323     const_iv (SDLK_F11),
324     const_iv (SDLK_F12),
325     const_iv (SDLK_F13),
326     const_iv (SDLK_F14),
327     const_iv (SDLK_F15),
328     const_iv (SDLK_NUMLOCK),
329     const_iv (SDLK_CAPSLOCK),
330     const_iv (SDLK_SCROLLOCK),
331     const_iv (SDLK_RSHIFT),
332     const_iv (SDLK_LSHIFT),
333     const_iv (SDLK_RCTRL),
334     const_iv (SDLK_LCTRL),
335     const_iv (SDLK_RALT),
336     const_iv (SDLK_LALT),
337     const_iv (SDLK_RMETA),
338     const_iv (SDLK_LMETA),
339     const_iv (SDLK_LSUPER),
340     const_iv (SDLK_RSUPER),
341     const_iv (SDLK_MODE),
342     const_iv (SDLK_COMPOSE),
343     const_iv (SDLK_HELP),
344     const_iv (SDLK_PRINT),
345     const_iv (SDLK_SYSREQ),
346     const_iv (SDLK_BREAK),
347     const_iv (SDLK_MENU),
348     const_iv (SDLK_POWER),
349     const_iv (SDLK_EURO),
350     const_iv (SDLK_UNDO),
351     const_iv (KMOD_NONE),
352     const_iv (KMOD_LSHIFT),
353     const_iv (KMOD_RSHIFT),
354     const_iv (KMOD_LCTRL),
355     const_iv (KMOD_RCTRL),
356     const_iv (KMOD_LALT),
357     const_iv (KMOD_RALT),
358     const_iv (KMOD_LMETA),
359     const_iv (KMOD_RMETA),
360     const_iv (KMOD_NUM),
361     const_iv (KMOD_CAPS),
362     const_iv (KMOD_MODE),
363     const_iv (KMOD_CTRL),
364     const_iv (KMOD_SHIFT),
365     const_iv (KMOD_ALT),
366     const_iv (KMOD_META)
367     # undef const_iv
368     };
369    
370     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
371     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
372    
373     fontmap = pango_ft2_font_map_new ();
374     pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
375     context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
376 root 1.5 }
377    
378 root 1.51 int
379     SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO)
380    
381     void
382     SDL_Quit ()
383    
384     void
385     SDL_ListModes ()
386     PPCODE:
387     {
388     SDL_Rect **m;
389    
390     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
391     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
392     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
393     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
394    
395     SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
396     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
397     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
398     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
399    
400     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
401     SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
402     SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
403    
404 root 1.53 SDL_EnableUNICODE (1);
405     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
406    
407 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
408    
409     if (m && m != (SDL_Rect **)-1)
410     while (*m)
411     {
412     AV *av = newAV ();
413     av_push (av, newSViv ((*m)->w));
414     av_push (av, newSViv ((*m)->h));
415     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
416    
417     ++m;
418     }
419     }
420    
421     int
422     SDL_SetVideoMode (int w, int h, int fullscreen)
423     CODE:
424     RETVAL = !!SDL_SetVideoMode (
425     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
426     );
427     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
428     OUTPUT:
429     RETVAL
430    
431 root 1.53 void
432 root 1.54 SDL_GL_SwapBuffers ()
433    
434     void
435 root 1.53 SDL_PollEvent ()
436     PPCODE:
437     {
438     SDL_Event ev;
439    
440     while (SDL_PollEvent (&ev))
441     {
442     HV *hv = newHV ();
443     hv_store (hv, "type", 4, newSViv (ev.type), 0);
444     switch (ev.type)
445     {
446     case SDL_KEYDOWN:
447     case SDL_KEYUP:
448     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
449     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
450     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
451     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
452     break;
453    
454     case SDL_ACTIVEEVENT:
455     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
456     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
457     break;
458    
459     case SDL_MOUSEMOTION:
460     hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
461     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
462     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
463     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
464     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
465     break;
466    
467     case SDL_MOUSEBUTTONDOWN:
468     case SDL_MOUSEBUTTONUP:
469     hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
470     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
471     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
472     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
473     }
474    
475     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
476     }
477     }
478 root 1.52
479     int
480     Mix_OpenAudio (int frequency = 22050, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 512)
481 root 1.56 POSTCALL:
482     Mix_HookMusicFinished (music_finished);
483 root 1.52
484     void
485     Mix_CloseAudio ()
486    
487     int
488     Mix_AllocateChannels (int numchans = -1)
489    
490 root 1.10 void
491     lowdelay (int fd, int val = 1)
492     CODE:
493 root 1.48 #ifndef _WIN32
494 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
495 root 1.48 #endif
496 root 1.10
497 root 1.3 char *
498 root 1.4 gl_version ()
499     CODE:
500 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
501 root 1.4 OUTPUT:
502     RETVAL
503    
504     char *
505 root 1.3 gl_extensions ()
506     CODE:
507 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
508 root 1.3 OUTPUT:
509     RETVAL
510    
511 root 1.5 void
512 root 1.13 add_font (char *file)
513     CODE:
514     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
515    
516     void
517 root 1.9 set_font (char *file)
518 root 1.8 CODE:
519     {
520 root 1.9 int count;
521     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)file, 0, 0, &count);
522 root 1.10 PangoFontDescription *font = pango_fc_font_description_from_pattern (pattern, 0);
523 root 1.9 FcPatternDestroy (pattern);
524 root 1.8 pango_context_set_font_description (context, font);
525     }
526    
527 root 1.23 void
528     load_image_inline (SV *image_)
529     ALIAS:
530     load_image_file = 1
531     PPCODE:
532     {
533     STRLEN image_len;
534     char *image = (char *)SvPVbyte (image_, image_len);
535     SDL_Surface *surface, *surface2;
536     SDL_PixelFormat fmt;
537     SDL_RWops *rw = ix
538     ? SDL_RWFromFile (image, "r")
539     : SDL_RWFromConstMem (image, image_len);
540    
541     if (!rw)
542 root 1.41 croak ("load_image: %s", SDL_GetError ());
543 root 1.23
544     surface = IMG_Load_RW (rw, 1);
545     if (!surface)
546 root 1.41 croak ("load_image: %s", SDL_GetError ());
547 root 1.23
548     fmt.palette = NULL;
549     fmt.BitsPerPixel = 32;
550     fmt.BytesPerPixel = 4;
551 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
552 root 1.23 fmt.Rmask = 0x000000ff;
553     fmt.Gmask = 0x0000ff00;
554     fmt.Bmask = 0x00ff0000;
555     fmt.Amask = 0xff000000;
556 root 1.49 #else
557     fmt.Rmask = 0xff000000;
558     fmt.Gmask = 0x00ff0000;
559     fmt.Bmask = 0x0000ff00;
560     fmt.Amask = 0x000000ff;
561     #endif
562 root 1.23 fmt.Rloss = 0;
563     fmt.Gloss = 0;
564     fmt.Bloss = 0;
565     fmt.Aloss = 0;
566     fmt.Rshift = 0;
567     fmt.Gshift = 8;
568     fmt.Bshift = 16;
569     fmt.Ashift = 24;
570     fmt.colorkey = 0;
571     fmt.alpha = 0;
572    
573     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
574    
575 root 1.39 assert (surface2->pitch == surface2->w * 4);
576    
577 root 1.23 EXTEND (SP, 5);
578     PUSHs (sv_2mortal (newSViv (surface2->w)));
579     PUSHs (sv_2mortal (newSViv (surface2->h)));
580     SDL_LockSurface (surface2);
581     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
582     SDL_UnlockSurface (surface2);
583 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
584 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
585 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
586 root 1.23
587     SDL_FreeSurface (surface);
588     SDL_FreeSurface (surface2);
589     }
590    
591 root 1.25 void
592 root 1.39 average (int x, int y, uint32_t *data)
593     PPCODE:
594     {
595     uint32_t r = 0, g = 0, b = 0, a = 0;
596    
597     x = y = x * y;
598    
599     while (x--)
600     {
601     uint32_t p = *data++;
602    
603     r += (p ) & 255;
604     g += (p >> 8) & 255;
605     b += (p >> 16) & 255;
606     a += (p >> 24) & 255;
607     }
608    
609     EXTEND (SP, 4);
610 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
611     PUSHs (sv_2mortal (newSViv (g / y)));
612     PUSHs (sv_2mortal (newSViv (b / y)));
613     PUSHs (sv_2mortal (newSViv (a / y)));
614 root 1.39 }
615    
616     void
617 root 1.25 fatal (char *message)
618     CODE:
619 root 1.50 #ifdef _WIN32
620 root 1.25 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
621     #else
622 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
623 root 1.25 #endif
624     exit (1);
625    
626 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
627 root 1.14
628 root 1.15 CFClient::Layout
629 root 1.14 new (SV *class, int base_height = 10)
630     CODE:
631     New (0, RETVAL, 1, struct cf_layout);
632     RETVAL->base_height = base_height;
633     RETVAL->pl = pango_layout_new (context);
634     pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
635     OUTPUT:
636     RETVAL
637    
638     void
639 root 1.15 DESTROY (CFClient::Layout self)
640 root 1.14 CODE:
641     g_object_unref (self->pl);
642     Safefree (self);
643 root 1.13
644 root 1.8 void
645 root 1.35 set_text (CFClient::Layout self, SV *text_)
646     CODE:
647     {
648     STRLEN textlen;
649     char *text = SvPVutf8 (text_, textlen);
650    
651     pango_layout_set_text (self->pl, text, textlen);
652     }
653    
654     void
655 root 1.15 set_markup (CFClient::Layout self, SV *text_)
656 root 1.14 CODE:
657 root 1.5 {
658     STRLEN textlen;
659     char *text = SvPVutf8 (text_, textlen);
660 root 1.14
661     pango_layout_set_markup (self->pl, text, textlen);
662     }
663    
664 root 1.46 SV *
665     get_text (CFClient::Layout self)
666     CODE:
667 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
668 root 1.46 SvUTF8_on (RETVAL);
669     OUTPUT:
670     RETVAL
671    
672 root 1.14 void
673 root 1.16 set_height (CFClient::Layout self, int base_height)
674     CODE:
675     self->base_height = base_height;
676    
677     void
678 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
679 root 1.14 CODE:
680     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
681    
682     void
683 root 1.15 size (CFClient::Layout self)
684 root 1.14 PPCODE:
685     {
686     int w, h;
687    
688 root 1.17 layout_update (self);
689 root 1.14 layout_get_pixel_size (self, &w, &h);
690    
691     EXTEND (SP, 2);
692     PUSHs (sv_2mortal (newSViv (w)));
693     PUSHs (sv_2mortal (newSViv (h)));
694     }
695    
696 root 1.17 int
697     xy_to_index (CFClient::Layout self, int x, int y)
698     CODE:
699     {
700     int index, trailing;
701    
702     layout_update (self);
703     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
704    
705     RETVAL = index;
706     }
707     OUTPUT:
708     RETVAL
709    
710     void
711     cursor_pos (CFClient::Layout self, int index)
712     PPCODE:
713     {
714     PangoRectangle strong_pos;
715     layout_update (self);
716     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
717 root 1.30
718 root 1.17 EXTEND (SP, 3);
719     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
720     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
721     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
722     }
723    
724 root 1.14 void
725 root 1.15 render (CFClient::Layout self)
726 root 1.14 PPCODE:
727     {
728 root 1.5 SV *retval;
729     int w, h;
730     FT_Bitmap bitmap;
731    
732 root 1.17 layout_update (self);
733 root 1.14 layout_get_pixel_size (self, &w, &h);
734 root 1.5
735     retval = newSV (w * h);
736     SvPOK_only (retval);
737     SvCUR_set (retval, w * h);
738    
739     bitmap.rows = h;
740     bitmap.width = w;
741     bitmap.pitch = w;
742     bitmap.buffer = (unsigned char*)SvPVX (retval);
743     bitmap.num_grays = 256;
744     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
745    
746     memset (bitmap.buffer, 0, w * h);
747    
748 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
749 root 1.1
750 root 1.5 EXTEND (SP, 3);
751     PUSHs (sv_2mortal (newSViv (w)));
752     PUSHs (sv_2mortal (newSViv (h)));
753     PUSHs (sv_2mortal (retval));
754     }
755 root 1.11
756 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
757 root 1.11
758     void
759 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
760 root 1.12 PROTOTYPE: $$$;$$
761 root 1.11 CODE:
762     {
763 root 1.12 HV *hv = (HV *)SvRV (self);
764 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
765     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
766 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
767 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
768 root 1.12
769     if (items < 5)
770     {
771 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
772     h = SvNV (*hv_fetch (hv, "h", 1, 1));
773 root 1.12 }
774    
775     glBindTexture (GL_TEXTURE_2D, name);
776 elmex 1.36 if (wrap_mode) {
777     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
778     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
779     }
780 root 1.12 glBegin (GL_QUADS);
781 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
782     glTexCoord2f (0, t); glVertex2f (x , y + h);
783     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
784     glTexCoord2f (s, 0); glVertex2f (x + w, y );
785 root 1.12 glEnd ();
786 root 1.11 }
787 root 1.28
788     MODULE = CFClient PACKAGE = CFClient::Map
789    
790     CFClient::Map
791     new (SV *class, int map_width, int map_height)
792     CODE:
793     New (0, RETVAL, 1, struct map);
794 root 1.42 RETVAL->x = 0;
795     RETVAL->y = 0;
796     RETVAL->w = map_width;
797     RETVAL->h = map_height;
798     RETVAL->ox = 0;
799     RETVAL->oy = 0;
800 root 1.30 RETVAL->faces = 8192;
801     Newz (0, RETVAL->face, RETVAL->faces, mapface);
802 root 1.42 RETVAL->texs = 8192;
803     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
804 root 1.28 RETVAL->rows = 0;
805     RETVAL->row = 0;
806     OUTPUT:
807     RETVAL
808    
809     void
810     DESTROY (CFClient::Map self)
811     CODE:
812     {
813 root 1.30 map_clear (self);
814 root 1.28 Safefree (self->face);
815 root 1.29 Safefree (self);
816     }
817    
818     void
819 root 1.30 clear (CFClient::Map self)
820     CODE:
821     map_clear (self);
822    
823     void
824 root 1.42 set_face (CFClient::Map self, int face, int texid)
825 root 1.29 CODE:
826     {
827 root 1.42 while (self->faces <= face)
828 root 1.28 {
829 root 1.30 Append (mapface, self->face, self->faces, self->faces);
830 root 1.29 self->faces *= 2;
831     }
832 root 1.28
833 root 1.42 self->face [face] = texid;
834     }
835    
836     void
837     set_texture (CFClient::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
838     CODE:
839     {
840     while (self->texs <= texid)
841     {
842     Append (maptex, self->tex, self->texs, self->texs);
843     self->texs *= 2;
844     }
845    
846 root 1.48 {
847     maptex *tex = self->tex + texid;
848 root 1.39
849 root 1.48 tex->name = name;
850     tex->w = w;
851     tex->h = h;
852     tex->s = s;
853     tex->t = t;
854     tex->r = r;
855     tex->g = g;
856     tex->b = b;
857     tex->a = a;
858     }
859 root 1.29 }
860    
861 root 1.42 int
862     ox (CFClient::Map self)
863     ALIAS:
864     oy = 1
865     CODE:
866     switch (ix)
867     {
868     case 0: RETVAL = self->ox; break;
869     case 1: RETVAL = self->oy; break;
870     }
871     OUTPUT:
872     RETVAL
873    
874 root 1.29 void
875 root 1.43 scroll (CFClient::Map self, int dx, int dy)
876     CODE:
877     {
878 root 1.44 if (dx > 0)
879     map_blank (self, self->x, self->y, dx - 1, self->h);
880     else if (dx < 0)
881     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
882    
883     if (dy > 0)
884     map_blank (self, self->x, self->y, self->w, dy - 1);
885     else if (dy < 0)
886     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
887 root 1.43
888 root 1.44 self->ox += dx; self->x += dx;
889     self->oy += dy; self->y += dy;
890 root 1.43
891     while (self->y < 0)
892     {
893     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
894    
895     self->rows += MAP_EXTEND_Y;
896     self->y += MAP_EXTEND_Y;
897     }
898 root 1.44 }
899 root 1.43
900 root 1.44 void
901     map1a_update (CFClient::Map self, SV *data_)
902     CODE:
903     {
904 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
905     uint8_t *data_end = (uint8_t *)SvEND (data_);
906 root 1.48 mapcell *cell;
907     int x, y, flags;
908 root 1.43
909 root 1.29 while (data < data_end)
910     {
911 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
912 root 1.30
913 root 1.48 x = ((flags >> 10) & 63) + self->x;
914     y = ((flags >> 4) & 63) + self->y;
915 root 1.29
916 root 1.48 cell = map_get_cell (self, x, y);
917 root 1.29
918     if (flags & 15)
919     {
920 root 1.45 if (cell->darkness < 0)
921 root 1.29 {
922     cell->darkness = 0;
923     cell->face [0] = 0;
924     cell->face [1] = 0;
925     cell->face [2] = 0;
926     }
927 root 1.45
928 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
929    
930 root 1.42 //TODO: don't trust server data to be in-range(!)
931    
932 root 1.29 if (flags & 4)
933     {
934 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
935 root 1.29 }
936    
937     if (flags & 2)
938     {
939 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
940 root 1.29 }
941    
942     if (flags & 1)
943     {
944 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
945 root 1.29 }
946     }
947     else
948 root 1.31 cell->darkness = -1;
949 root 1.29 }
950 root 1.28 }
951    
952 root 1.40 SV *
953 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
954 root 1.40 CODE:
955     {
956 root 1.55 int x1, x;
957     int y1, y;
958 root 1.40 int z;
959     SV *map_sv = newSV (w * h * sizeof (uint32_t));
960     uint32_t *map = (uint32_t *)SvPVX (map_sv);
961    
962     SvPOK_only (map_sv);
963     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
964    
965 root 1.55 x0 += self->x; x1 = x0 + w;
966     y0 += self->y; y1 = y0 + h;
967 root 1.40
968     for (y = y0; y < y1; y++)
969     {
970     maprow *row = 0 <= y && y < self->rows
971     ? self->row + y
972     : 0;
973    
974     for (x = x0; x < x1; x++)
975     {
976     int r = 32, g = 32, b = 32, a = 192;
977    
978     if (row && row->c0 <= x && x < row->c1)
979     {
980     mapcell *cell = row->col + (x - row->c0);
981    
982     for (z = 0; z <= 0; z++)
983     {
984 root 1.42 mapface face = cell->face [z];
985 root 1.40
986     if (face)
987     {
988 root 1.42 maptex tex = self->tex [face];
989 root 1.40 int a0 = 255 - tex.a;
990     int a1 = tex.a;
991    
992     r = (r * a0 + tex.r * a1) / 255;
993     g = (g * a0 + tex.g * a1) / 255;
994     b = (b * a0 + tex.b * a1) / 255;
995     a = (a * a0 + tex.a * a1) / 255;
996     }
997     }
998     }
999    
1000     *map++ = (r )
1001     | (g << 8)
1002     | (b << 16)
1003     | (a << 24);
1004     }
1005     }
1006    
1007     RETVAL = map_sv;
1008     }
1009     OUTPUT:
1010     RETVAL
1011    
1012 root 1.30 void
1013 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1014 root 1.32 PPCODE:
1015 root 1.30 {
1016 root 1.48 int vx, vy;
1017     int x, y, z;
1018     int last_name;
1019     mapface face;
1020 root 1.32 int sw4 = (sw + 3) & ~3;
1021     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1022 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1023 root 1.48
1024 root 1.42 memset (darkness, 255, sw4 * sh);
1025 root 1.32 SvPOK_only (darkness_sv);
1026     SvCUR_set (darkness_sv, sw4 * sh);
1027    
1028 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1029     vy = self->y + (self->h - sh) / 2 - shift_y;
1030 root 1.38
1031 root 1.42 /*
1032     int vx = self->vx = self->w >= sw
1033     ? self->x + (self->w - sw) / 2
1034     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1035    
1036     int vy = self->vy = self->h >= sh
1037     ? self->y + (self->h - sh) / 2
1038     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1039     */
1040 root 1.30
1041     glColor4ub (255, 255, 255, 255);
1042    
1043     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1044     glEnable (GL_BLEND);
1045     glEnable (GL_TEXTURE_2D);
1046     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1047    
1048 root 1.48 glBegin (GL_QUADS);
1049 root 1.30
1050 root 1.48 last_name = 0;
1051 root 1.30
1052     for (z = 0; z < 3; z++)
1053     for (y = 0; y < sh; y++)
1054     if (0 <= y + vy && y + vy < self->rows)
1055     {
1056     maprow *row = self->row + (y + vy);
1057    
1058     for (x = 0; x < sw; x++)
1059     if (row->c0 <= x + vx && x + vx < row->c1)
1060     {
1061     mapcell *cell = row->col + (x + vx - row->c0);
1062 root 1.32
1063     darkness[y * sw4 + x] = cell->darkness < 0
1064 root 1.33 ? 255 - FOW_DARKNESS
1065 root 1.32 : 255 - cell->darkness;
1066    
1067 root 1.48 face = cell->face [z];
1068 root 1.30
1069     if (face)
1070     {
1071 root 1.42 maptex tex = self->tex [face];
1072 root 1.30
1073     int px = (x + 1) * 32 - tex.w;
1074     int py = (y + 1) * 32 - tex.h;
1075    
1076     if (last_name != tex.name)
1077     {
1078     glEnd ();
1079     last_name = tex.name;
1080     glBindTexture (GL_TEXTURE_2D, last_name);
1081     glBegin (GL_QUADS);
1082     }
1083    
1084     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1085     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1086     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1087     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1088     }
1089     }
1090     }
1091    
1092     glEnd ();
1093 root 1.32
1094 root 1.34 glDisable (GL_TEXTURE_2D);
1095     glDisable (GL_BLEND);
1096    
1097 root 1.32 EXTEND (SP, 3);
1098     PUSHs (sv_2mortal (newSViv (sw4)));
1099     PUSHs (sv_2mortal (newSViv (sh)));
1100     PUSHs (darkness_sv);
1101 root 1.30 }
1102    
1103 root 1.42 SV *
1104     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1105     CODE:
1106     {
1107     int x, y, x1, y1;
1108     SV *data_sv = newSV (w * h * 7 + 5);
1109     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1110    
1111     *data++ = 0; /* version 0 format */
1112     *data++ = w >> 8; *data++ = w;
1113     *data++ = h >> 8; *data++ = h;
1114    
1115     // we need to do this 'cause we don't keep an absolute coord system for rows
1116 root 1.55 // TODO: treat rows as we treat columns
1117 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1118     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1119    
1120     x0 += self->x - self->ox;
1121     y0 += self->y - self->oy;
1122    
1123     x1 = x0 + w;
1124     y1 = y0 + h;
1125    
1126     for (y = y0; y < y1; y++)
1127     {
1128     maprow *row = 0 <= y && y < self->rows
1129     ? self->row + y
1130     : 0;
1131    
1132     for (x = x0; x < x1; x++)
1133     {
1134     if (row && row->c0 <= x && x < row->c1)
1135     {
1136     mapcell *cell = row->col + (x - row->c0);
1137     uint8_t flags = 0;
1138    
1139     if (cell->face [0]) flags |= 1;
1140     if (cell->face [1]) flags |= 2;
1141     if (cell->face [2]) flags |= 4;
1142    
1143     *data++ = flags;
1144    
1145     if (flags & 1)
1146     {
1147     *data++ = cell->face [0] >> 8;
1148     *data++ = cell->face [0];
1149     }
1150    
1151     if (flags & 2)
1152     {
1153     *data++ = cell->face [1] >> 8;
1154     *data++ = cell->face [1];
1155     }
1156    
1157     if (flags & 4)
1158     {
1159     *data++ = cell->face [2] >> 8;
1160     *data++ = cell->face [2];
1161     }
1162     }
1163     else
1164     *data++ = 0;
1165     }
1166     }
1167    
1168     SvPOK_only (data_sv);
1169     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1170     RETVAL = data_sv;
1171     }
1172     OUTPUT:
1173     RETVAL
1174    
1175     void
1176     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1177     PPCODE:
1178     {
1179     int x, y, z;
1180 root 1.48 int w, h;
1181 root 1.42 int x1, y1;
1182    
1183     if (*data++ != 0)
1184     return; /* version mismatch */
1185    
1186 root 1.48 w = *data++ << 8; w |= *data++;
1187     h = *data++ << 8; h |= *data++;
1188 root 1.42
1189     // we need to do this 'cause we don't keep an absolute coord system for rows
1190 root 1.55 // TODO: treat rows as we treat columns
1191 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1192     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1193    
1194     x0 += self->x - self->ox;
1195     y0 += self->y - self->oy;
1196    
1197     x1 = x0 + w;
1198     y1 = y0 + h;
1199    
1200     for (y = y0; y < y1; y++)
1201     {
1202     maprow *row = map_get_row (self, y);
1203    
1204     for (x = x0; x < x1; x++)
1205     {
1206     uint8_t flags = *data++;
1207    
1208     if (flags)
1209     {
1210     mapface face[3] = { 0, 0, 0 };
1211    
1212     mapcell *cell = row_get_cell (row, x);
1213    
1214     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1215     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1216     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1217    
1218     if (cell->darkness <= 0)
1219     {
1220     cell->darkness = -1;
1221    
1222     for (z = 0; z <= 2; z++)
1223     {
1224     cell->face[z] = face[z];
1225    
1226     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1227     XPUSHs (sv_2mortal (newSViv (face[z])));
1228     }
1229     }
1230     }
1231     }
1232     }
1233     }
1234    
1235 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1236    
1237     CFClient::MixChunk
1238     new_from_file (SV *class, char *path)
1239     CODE:
1240     RETVAL = Mix_LoadWAV (path);
1241     OUTPUT:
1242     RETVAL
1243    
1244     void
1245     DESTROY (CFClient::MixChunk self)
1246     CODE:
1247     Mix_FreeChunk (self);
1248    
1249     int
1250     volume (CFClient::MixChunk self, int volume = -1)
1251     CODE:
1252     RETVAL = Mix_VolumeChunk (self, volume);
1253     OUTPUT:
1254     RETVAL
1255    
1256     int
1257     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1258     CODE:
1259     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1260     OUTPUT:
1261     RETVAL
1262    
1263     MODULE = CFClient PACKAGE = CFClient::MixMusic
1264    
1265     int
1266     volume (int volume = -1)
1267     CODE:
1268     RETVAL = Mix_VolumeMusic (volume);
1269     OUTPUT:
1270     RETVAL
1271    
1272     CFClient::MixMusic
1273     new_from_file (SV *class, char *path)
1274     CODE:
1275     RETVAL = Mix_LoadMUS (path);
1276     OUTPUT:
1277     RETVAL
1278    
1279     void
1280     DESTROY (CFClient::MixMusic self)
1281     CODE:
1282     Mix_FreeMusic (self);
1283    
1284     int
1285     play (CFClient::MixMusic self, int loops = -1)
1286     CODE:
1287     RETVAL = Mix_PlayMusic (self, loops);
1288     OUTPUT:
1289     RETVAL
1290    
1291 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1292    
1293     BOOT:
1294     {
1295     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1296     static const struct {
1297     const char *name;
1298     IV iv;
1299     } *civ, const_iv[] = {
1300     # define const_iv(name) { # name, (IV)name }
1301     const_iv (GL_COLOR_MATERIAL),
1302     const_iv (GL_SMOOTH),
1303     const_iv (GL_FLAT),
1304     const_iv (GL_BLEND),
1305     const_iv (GL_AND),
1306     const_iv (GL_SRC_ALPHA),
1307     const_iv (GL_ONE_MINUS_SRC_ALPHA),
1308     const_iv (GL_RGB),
1309     const_iv (GL_RGBA),
1310     const_iv (GL_UNSIGNED_BYTE),
1311     const_iv (GL_ALPHA4),
1312     const_iv (GL_ALPHA),
1313     const_iv (GL_FLOAT),
1314     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1315     const_iv (GL_COMPILE),
1316     const_iv (GL_TEXTURE_1D),
1317     const_iv (GL_TEXTURE_2D),
1318     const_iv (GL_TEXTURE_ENV),
1319     const_iv (GL_TEXTURE_MAG_FILTER),
1320     const_iv (GL_TEXTURE_MIN_FILTER),
1321     const_iv (GL_TEXTURE_ENV_MODE),
1322     const_iv (GL_TEXTURE_WRAP_S),
1323     const_iv (GL_TEXTURE_WRAP_T),
1324     const_iv (GL_CLAMP),
1325     const_iv (GL_REPEAT),
1326     const_iv (GL_NEAREST),
1327     const_iv (GL_LINEAR),
1328     const_iv (GL_MODULATE),
1329     const_iv (GL_REPLACE),
1330     const_iv (GL_COLOR_BUFFER_BIT),
1331     const_iv (GL_PROJECTION),
1332     const_iv (GL_MODELVIEW),
1333     const_iv (GL_COLOR_LOGIC_OP),
1334     const_iv (GL_CONVOLUTION_2D),
1335     const_iv (GL_CONVOLUTION_BORDER_MODE),
1336     const_iv (GL_CONSTANT_BORDER),
1337     const_iv (GL_LINES),
1338     const_iv (GL_QUADS),
1339 root 1.55 const_iv (GL_LINE_LOOP),
1340 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1341     const_iv (GL_FASTEST),
1342     # undef const_iv
1343     };
1344    
1345     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1346     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1347     }
1348    
1349     int glGetError ()
1350    
1351     void glClear (int mask)
1352    
1353     void glClearColor (float r, float g, float b, float a = 1.0)
1354     PROTOTYPE: @
1355    
1356     void glEnable (int cap)
1357    
1358     void glDisable (int cap)
1359    
1360     void glShadeModel (int mode)
1361    
1362     void glHint (int target, int mode)
1363    
1364     void glBlendFunc (int sfactor, int dfactor)
1365    
1366     void glLogicOp (int opcode)
1367    
1368     void glMatrixMode (int mode)
1369    
1370     void glPushMatrix ()
1371    
1372     void glPopMatrix ()
1373    
1374     void glLoadIdentity ()
1375    
1376     void glOrtho (double left, double right, double bottom, double top, double near, double far)
1377    
1378     void glViewport (int x, int y, int width, int height)
1379    
1380     void glTranslate (float x, float y, float z = 0.)
1381     CODE:
1382     glTranslatef (x, y, z);
1383    
1384     void glScale (float x, float y, float z)
1385     CODE:
1386     glScalef (x, y, z);
1387    
1388     void glRotate (float angle, float x, float y, float z)
1389     CODE:
1390     glRotatef (angle, x, y, z);
1391    
1392     void glBegin (int mode)
1393    
1394     void glEnd ()
1395    
1396     void glColor (float r, float g, float b, float a = 1.0)
1397     PROTOTYPE: @
1398     CODE:
1399     glColor4f (r, g, b, a);
1400    
1401     void glVertex (float x, float y, float z = 0.)
1402     CODE:
1403     glVertex3f (x, y, z);
1404    
1405     void glTexCoord (float s, float t)
1406     CODE:
1407     glTexCoord2f (s, t);
1408    
1409     void glTexEnv (int target, int pname, float param)
1410     CODE:
1411     glTexEnvf (target, pname, param);
1412    
1413     void glTexParameter (int target, int pname, float param)
1414     CODE:
1415     glTexParameterf (target, pname, param);
1416    
1417     void glBindTexture (int target, int name)
1418    
1419     void glConvolutionParameter (int target, int pname, float params)
1420     CODE:
1421     glConvolutionParameterf (target, pname, params);
1422    
1423     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1424    
1425     void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1426    
1427     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1428    
1429     int glGenTexture ()
1430     CODE:
1431     {
1432     GLuint name;
1433     glGenTextures (1, &name);
1434     RETVAL = name;
1435     }
1436     OUTPUT:
1437     RETVAL
1438    
1439     void glDeleteTexture (int name)
1440     CODE:
1441     {
1442     GLuint name_ = name;
1443     glDeleteTextures (1, &name_);
1444     }
1445    
1446     int glGenList ()
1447     CODE:
1448     RETVAL = glGenLists (1);
1449     OUTPUT:
1450     RETVAL
1451    
1452     void glDeleteList (int list)
1453     CODE:
1454     glDeleteLists (list, 1);
1455    
1456     void glNewList (int list, int mode = GL_COMPILE)
1457    
1458     void glEndList ()
1459    
1460     void glCallList (int list)
1461