ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.104
Committed: Mon Jun 5 00:17:47 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.103: +4 -2 lines
Log Message:
play around some more

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