ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.86
Committed: Fri May 19 16:43:56 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.85: +14 -9 lines
Log Message:
*** empty log message ***

File Contents

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