ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.94
Committed: Tue May 23 18:57:35 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.93: +5 -25 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.79 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
3 root 1.48 # include <malloc.h>
4 root 1.79 # include <windows.h>
5 root 1.75 # pragma warning(disable:4244)
6 root 1.48 #endif
7    
8 root 1.1 #include "EXTERN.h"
9     #include "perl.h"
10     #include "XSUB.h"
11    
12 root 1.80 #include <math.h>
13 root 1.5 #include <string.h>
14 root 1.25 #include <stdio.h>
15 root 1.5
16 root 1.2 #include <SDL.h>
17 root 1.76 #include <SDL_endian.h>
18 root 1.23 #include <SDL_image.h>
19 root 1.52 #include <SDL_mixer.h>
20 root 1.3 #include <SDL_opengl.h>
21 root 1.5
22 root 1.30 #include <glib/gmacros.h>
23    
24 root 1.5 #include <pango/pango.h>
25 root 1.10 #include <pango/pangofc-fontmap.h>
26 root 1.5 #include <pango/pangoft2.h>
27 root 1.76 #include <pango/pangocairo.h>
28 root 1.5
29 root 1.48 #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 root 1.28
44 root 1.57 #include "glext.h"
45    
46 root 1.29 #define FOW_DARKNESS 32
47    
48     #define MAP_EXTEND_X 32
49     #define MAP_EXTEND_Y 512
50    
51 root 1.63 #define MIN_FONT_HEIGHT 10
52 root 1.58
53 root 1.64 #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 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
69     typedef Mix_Music *CFClient__MixMusic;
70    
71 root 1.61 typedef PangoFontDescription *CFClient__Font;
72 root 1.2
73 root 1.14 typedef struct cf_layout {
74 root 1.76 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 root 1.14 int base_height;
78 root 1.61 CFClient__Font font;
79 root 1.15 } *CFClient__Layout;
80 root 1.14
81 root 1.61 static CFClient__Font default_font;
82 root 1.76 static PangoContext *ft2_context, *cairo_context;
83     static PangoFontMap *ft2_fontmap, *cairo_fontmap;
84 root 1.61
85 root 1.14 static void
86 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
87     {
88 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
89 root 1.83 #ifdef _WIN32
90     FcPatternAddBool (pattern, FC_AUTOHINT, 1);
91     #else
92 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
93     #endif
94 root 1.19 }
95    
96     static void
97 root 1.61 layout_update_font (CFClient__Layout self)
98 root 1.17 {
99 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
100     * reasonably well with bitstream vera
101     */
102 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
103 root 1.46
104 root 1.61 pango_font_description_set_absolute_size (font,
105     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
106 root 1.58
107 root 1.61 pango_layout_set_font_description (self->pl, font);
108 root 1.17 }
109    
110     static void
111 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
112 root 1.14 {
113     pango_layout_get_pixel_size (self->pl, w, h);
114    
115     if (!*w) *w = 1;
116     if (!*h) *h = 1;
117 root 1.76
118     *w = (*w + 3) & ~3;
119 root 1.14 }
120    
121 root 1.42 typedef uint16_t mapface;
122    
123 root 1.28 typedef struct {
124 root 1.30 GLint name;
125     int w, h;
126     float s, t;
127 root 1.39 uint8_t r, g, b, a;
128 root 1.42 } maptex;
129 root 1.30
130     typedef struct {
131 root 1.29 int16_t darkness;
132 root 1.42 mapface face[3];
133 root 1.28 } mapcell;
134    
135     typedef struct {
136 root 1.30 int32_t c0, c1;
137 root 1.28 mapcell *col;
138     } maprow;
139    
140     typedef struct map {
141     int x, y, w, h;
142 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
143 root 1.28 int faces;
144 root 1.30 mapface *face;
145 root 1.28
146 root 1.42 int texs;
147     maptex *tex;
148    
149 root 1.48 int32_t rows;
150 root 1.28 maprow *row;
151     } *CFClient__Map;
152    
153 root 1.30 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 root 1.42 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 root 1.30 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 root 1.42 self->ox = 0;
245     self->oy = 0;
246 root 1.30 self->row = 0;
247     self->rows = 0;
248     }
249    
250 root 1.29 static void
251     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
252     {
253     int x, y;
254 root 1.48 maprow *row;
255 root 1.29
256     for (y = y0; y < y0 + h; y++)
257 root 1.30 if (y >= 0)
258     {
259     if (y >= self->rows)
260     break;
261    
262 root 1.48 row = self->row + y;
263 root 1.30
264     for (x = x0; x < x0 + w; x++)
265     if (x >= row->c0)
266     {
267     if (x >= row->c1)
268     break;
269 root 1.29
270 root 1.31 row->col[x - row->c0].darkness = -1;
271 root 1.30 }
272     }
273 root 1.29 }
274    
275 root 1.56 static void
276 root 1.75 music_finished (void)
277 root 1.56 {
278     SDL_UserEvent ev;
279    
280     ev.type = SDL_USEREVENT;
281     ev.code = 0;
282     ev.data1 = 0;
283     ev.data2 = 0;
284    
285 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
286 root 1.56 }
287    
288 root 1.71 static void
289     channel_finished (int channel)
290     {
291     SDL_UserEvent ev;
292    
293     ev.type = SDL_USEREVENT;
294     ev.code = 1;
295 root 1.74 ev.data1 = (void *)(long)channel;
296 root 1.71 ev.data2 = 0;
297    
298     SDL_PushEvent ((SDL_Event *)&ev);
299     }
300    
301 root 1.15 MODULE = CFClient PACKAGE = CFClient
302 root 1.1
303 root 1.11 PROTOTYPES: ENABLE
304    
305 root 1.5 BOOT:
306     {
307 root 1.51 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 root 1.79 }
417 root 1.51
418 root 1.79 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 root 1.76
427 root 1.79 cairo_fontmap = pango_cairo_font_map_get_default ();
428     cairo_context = pango_cairo_font_map_create_context ((PangoCairoFontMap *)cairo_fontmap);
429 root 1.5 }
430    
431 root 1.51 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 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
447 root 1.51
448 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
449 root 1.89 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
450 root 1.85
451 root 1.51 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 root 1.53 SDL_EnableUNICODE (1);
459     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
460    
461 root 1.51 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 root 1.88 char *
476     SDL_GetError ()
477    
478 root 1.51 int
479     SDL_SetVideoMode (int w, int h, int fullscreen)
480     CODE:
481     RETVAL = !!SDL_SetVideoMode (
482     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
483     );
484     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
485     OUTPUT:
486     RETVAL
487    
488 root 1.53 void
489 root 1.54 SDL_GL_SwapBuffers ()
490    
491 root 1.94 char *
492     SDL_GetKeyName (int sym)
493    
494 root 1.54 void
495 root 1.53 SDL_PollEvent ()
496     PPCODE:
497     {
498     SDL_Event ev;
499    
500     while (SDL_PollEvent (&ev))
501     {
502     HV *hv = newHV ();
503     hv_store (hv, "type", 4, newSViv (ev.type), 0);
504 root 1.70
505 root 1.53 switch (ev.type)
506     {
507     case SDL_KEYDOWN:
508     case SDL_KEYUP:
509     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
510     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
511     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
512     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
513     break;
514    
515     case SDL_ACTIVEEVENT:
516     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
517     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
518     break;
519    
520     case SDL_MOUSEMOTION:
521 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
522 root 1.93
523 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
524     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
525     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
526     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
527     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
528     break;
529    
530     case SDL_MOUSEBUTTONDOWN:
531     case SDL_MOUSEBUTTONUP:
532 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
533 root 1.93
534 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
535     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
536     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
537     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
538 root 1.70 break;
539 root 1.72
540     case SDL_USEREVENT:
541     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
542     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
543     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
544     break;
545 root 1.53 }
546    
547     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
548     }
549     }
550 root 1.52
551     int
552 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
553 root 1.56 POSTCALL:
554     Mix_HookMusicFinished (music_finished);
555 root 1.71 Mix_ChannelFinished (channel_finished);
556 root 1.52
557     void
558     Mix_CloseAudio ()
559    
560     int
561     Mix_AllocateChannels (int numchans = -1)
562    
563 root 1.10 void
564     lowdelay (int fd, int val = 1)
565     CODE:
566 root 1.48 #ifndef _WIN32
567 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
568 root 1.48 #endif
569 root 1.10
570 root 1.3 char *
571 elmex 1.92 gl_vendor ()
572     CODE:
573     RETVAL = (char *)glGetString (GL_VENDOR);
574     OUTPUT:
575     RETVAL
576    
577     char *
578 root 1.4 gl_version ()
579     CODE:
580 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
581 root 1.4 OUTPUT:
582     RETVAL
583    
584     char *
585 root 1.3 gl_extensions ()
586     CODE:
587 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
588 root 1.3 OUTPUT:
589     RETVAL
590    
591 root 1.5 void
592 root 1.13 add_font (char *file)
593     CODE:
594     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
595 root 1.79 #ifdef _WIN32
596     // cairo... sigh... requires win2000
597     AddFontResourceEx (file, FR_PRIVATE, 0);
598     #endif
599 root 1.13
600     void
601 root 1.23 load_image_inline (SV *image_)
602     ALIAS:
603     load_image_file = 1
604     PPCODE:
605     {
606     STRLEN image_len;
607     char *image = (char *)SvPVbyte (image_, image_len);
608     SDL_Surface *surface, *surface2;
609     SDL_PixelFormat fmt;
610     SDL_RWops *rw = ix
611     ? SDL_RWFromFile (image, "r")
612     : SDL_RWFromConstMem (image, image_len);
613    
614     if (!rw)
615 root 1.41 croak ("load_image: %s", SDL_GetError ());
616 root 1.23
617     surface = IMG_Load_RW (rw, 1);
618     if (!surface)
619 root 1.41 croak ("load_image: %s", SDL_GetError ());
620 root 1.23
621     fmt.palette = NULL;
622     fmt.BitsPerPixel = 32;
623     fmt.BytesPerPixel = 4;
624 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
625 root 1.23 fmt.Rmask = 0x000000ff;
626     fmt.Gmask = 0x0000ff00;
627     fmt.Bmask = 0x00ff0000;
628     fmt.Amask = 0xff000000;
629 root 1.49 #else
630     fmt.Rmask = 0xff000000;
631     fmt.Gmask = 0x00ff0000;
632     fmt.Bmask = 0x0000ff00;
633     fmt.Amask = 0x000000ff;
634     #endif
635 root 1.23 fmt.Rloss = 0;
636     fmt.Gloss = 0;
637     fmt.Bloss = 0;
638     fmt.Aloss = 0;
639     fmt.Rshift = 0;
640     fmt.Gshift = 8;
641     fmt.Bshift = 16;
642     fmt.Ashift = 24;
643     fmt.colorkey = 0;
644     fmt.alpha = 0;
645    
646     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
647    
648 root 1.39 assert (surface2->pitch == surface2->w * 4);
649    
650 root 1.23 EXTEND (SP, 5);
651     PUSHs (sv_2mortal (newSViv (surface2->w)));
652     PUSHs (sv_2mortal (newSViv (surface2->h)));
653     SDL_LockSurface (surface2);
654     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
655     SDL_UnlockSurface (surface2);
656 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
657 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
658 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
659 root 1.23
660     SDL_FreeSurface (surface);
661     SDL_FreeSurface (surface2);
662     }
663    
664 root 1.25 void
665 root 1.39 average (int x, int y, uint32_t *data)
666     PPCODE:
667     {
668     uint32_t r = 0, g = 0, b = 0, a = 0;
669    
670     x = y = x * y;
671    
672     while (x--)
673     {
674     uint32_t p = *data++;
675    
676     r += (p ) & 255;
677     g += (p >> 8) & 255;
678     b += (p >> 16) & 255;
679     a += (p >> 24) & 255;
680     }
681    
682     EXTEND (SP, 4);
683 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
684     PUSHs (sv_2mortal (newSViv (g / y)));
685     PUSHs (sv_2mortal (newSViv (b / y)));
686     PUSHs (sv_2mortal (newSViv (a / y)));
687 root 1.39 }
688    
689     void
690 root 1.66 error (char *message)
691     CODE:
692 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
693 root 1.66 #ifdef _WIN32
694 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
695 root 1.66 #endif
696    
697     void
698 root 1.25 fatal (char *message)
699     CODE:
700 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
701 root 1.50 #ifdef _WIN32
702 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
703 root 1.25 #endif
704     exit (1);
705    
706 root 1.61 MODULE = CFClient PACKAGE = CFClient::Font
707    
708     CFClient::Font
709 root 1.70 new_from_file (SV *class, char *path, int id = 0)
710 root 1.61 CODE:
711     {
712     int count;
713 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
714 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
715     FcPatternDestroy (pattern);
716     }
717     OUTPUT:
718     RETVAL
719    
720     void
721     DESTROY (CFClient::Font self)
722     CODE:
723     pango_font_description_free (self);
724    
725     void
726     make_default (CFClient::Font self)
727     CODE:
728     default_font = self;
729    
730 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
731 root 1.14
732 root 1.15 CFClient::Layout
733 root 1.76 new (SV *class, int rgba = 0)
734 root 1.14 CODE:
735 root 1.87 #if _WIN32
736     rgba = 0;//D
737     #endif
738 root 1.14 New (0, RETVAL, 1, struct cf_layout);
739 root 1.76
740     RETVAL->pl = pango_layout_new (rgba ? cairo_context : ft2_context);
741     RETVAL->rgba = rgba;
742     RETVAL->r = 1.;
743     RETVAL->g = 1.;
744     RETVAL->b = 1.;
745     RETVAL->a = 1.;
746     RETVAL->base_height = MIN_FONT_HEIGHT;
747     RETVAL->font = 0;
748    
749 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
750 root 1.76 layout_update_font (RETVAL);
751 root 1.14 OUTPUT:
752     RETVAL
753    
754     void
755 root 1.15 DESTROY (CFClient::Layout self)
756 root 1.14 CODE:
757     g_object_unref (self->pl);
758     Safefree (self);
759 root 1.13
760 root 1.76 int
761     is_rgba (CFClient::Layout self)
762     CODE:
763     RETVAL = self->rgba;
764     OUTPUT:
765     RETVAL
766    
767 root 1.8 void
768 root 1.35 set_text (CFClient::Layout self, SV *text_)
769     CODE:
770     {
771     STRLEN textlen;
772     char *text = SvPVutf8 (text_, textlen);
773    
774     pango_layout_set_text (self->pl, text, textlen);
775     }
776    
777     void
778 root 1.15 set_markup (CFClient::Layout self, SV *text_)
779 root 1.14 CODE:
780 root 1.5 {
781     STRLEN textlen;
782     char *text = SvPVutf8 (text_, textlen);
783 root 1.14
784     pango_layout_set_markup (self->pl, text, textlen);
785     }
786    
787 root 1.46 SV *
788     get_text (CFClient::Layout self)
789     CODE:
790 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
791 root 1.46 SvUTF8_on (RETVAL);
792     OUTPUT:
793     RETVAL
794    
795 root 1.14 void
796 root 1.76 set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.)
797     CODE:
798     self->r = r;
799     self->g = g;
800     self->b = b;
801     self->a = a;
802    
803     void
804 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
805     CODE:
806     if (self->font != font)
807     {
808     self->font = font;
809     layout_update_font (self);
810     }
811    
812     void
813 root 1.16 set_height (CFClient::Layout self, int base_height)
814     CODE:
815 root 1.61 if (self->base_height != base_height)
816     {
817     self->base_height = base_height;
818     layout_update_font (self);
819     }
820 root 1.16
821     void
822 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
823 root 1.14 CODE:
824     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
825    
826     void
827 root 1.84 set_indent (CFClient::Layout self, int indent)
828     CODE:
829     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
830    
831     void
832     set_spacing (CFClient::Layout self, int spacing)
833     CODE:
834     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
835    
836     void
837     set_ellipsise (CFClient::Layout self, int ellipsise)
838     CODE:
839     pango_layout_set_ellipsize (self->pl,
840     ellipsise == 1 ? PANGO_ELLIPSIZE_START
841     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
842     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
843     : PANGO_ELLIPSIZE_NONE
844     );
845    
846     void
847     set_single_paragraph_mode (CFClient::Layout self, int spm)
848     CODE:
849     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
850    
851     void
852 root 1.15 size (CFClient::Layout self)
853 root 1.14 PPCODE:
854     {
855     int w, h;
856    
857     layout_get_pixel_size (self, &w, &h);
858    
859     EXTEND (SP, 2);
860     PUSHs (sv_2mortal (newSViv (w)));
861     PUSHs (sv_2mortal (newSViv (h)));
862     }
863    
864 root 1.17 int
865     xy_to_index (CFClient::Layout self, int x, int y)
866     CODE:
867     {
868     int index, trailing;
869     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
870     RETVAL = index;
871     }
872     OUTPUT:
873     RETVAL
874    
875     void
876     cursor_pos (CFClient::Layout self, int index)
877     PPCODE:
878     {
879     PangoRectangle strong_pos;
880     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
881 root 1.30
882 root 1.17 EXTEND (SP, 3);
883     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
884     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
885     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
886     }
887    
888 root 1.14 void
889 root 1.15 render (CFClient::Layout self)
890 root 1.14 PPCODE:
891     {
892 root 1.5 SV *retval;
893     int w, h;
894    
895 root 1.14 layout_get_pixel_size (self, &w, &h);
896 root 1.5
897 root 1.76 if (self->rgba)
898     {
899     cairo_surface_t *surface;
900     cairo_t *cairo;
901    
902     retval = newSV (w * h * 4);
903     SvPOK_only (retval);
904     SvCUR_set (retval, w * h * 4);
905    
906     memset (SvPVX (retval), 0, w * h * 4);
907    
908     surface = cairo_image_surface_create_for_data (
909     (void*)SvPVX (retval), CAIRO_FORMAT_ARGB32, w, h, w * 4);
910     cairo = cairo_create (surface);
911     cairo_set_source_rgba (cairo, self->r, self->g, self->b, self->a);
912    
913     pango_cairo_show_layout (cairo, self->pl);
914    
915     cairo_destroy (cairo);
916     cairo_surface_destroy (surface);
917    
918     // what a mess, and its premultiplied, too :(
919     {
920     uint32_t *p = (uint32_t *)SvPVX (retval);
921     uint32_t *e = p + w * h;
922 root 1.5
923 root 1.76 while (p < e)
924     {
925     uint32_t rgba = *p;
926     rgba = (rgba >> 24) | (rgba << 8);
927 root 1.87 #if 0
928     #ifdef _WIN32
929     {//D
930     uint8_t r = rgba >> 24;
931     uint8_t g = rgba >> 16;
932     uint8_t b = rgba >> 8;
933     uint8_t a = rgba >> 0;
934    
935     rgba = (rgba & 0xffffff00) | a;
936     }
937     #endif
938     #endif
939 root 1.76 rgba = SDL_SwapBE32 (rgba);
940     *p++ = rgba;
941     }
942     }
943    
944     EXTEND (SP, 5);
945     PUSHs (sv_2mortal (newSViv (w)));
946     PUSHs (sv_2mortal (newSViv (h)));
947     PUSHs (sv_2mortal (retval));
948     PUSHs (sv_2mortal (newSViv (GL_RGBA)));
949     PUSHs (sv_2mortal (newSViv (GL_RGBA)));
950     }
951     else
952     {
953     FT_Bitmap bitmap;
954    
955     retval = newSV (w * h);
956     SvPOK_only (retval);
957     SvCUR_set (retval, w * h);
958    
959     bitmap.rows = h;
960     bitmap.width = w;
961     bitmap.pitch = w;
962     bitmap.buffer = (unsigned char*)SvPVX (retval);
963     bitmap.num_grays = 256;
964     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
965    
966     memset (bitmap.buffer, 0, w * h);
967    
968     pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
969 root 1.1
970 root 1.76 EXTEND (SP, 5);
971     PUSHs (sv_2mortal (newSViv (w)));
972     PUSHs (sv_2mortal (newSViv (h)));
973     PUSHs (sv_2mortal (retval));
974     PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
975     PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
976     }
977 root 1.5 }
978 root 1.11
979 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
980 root 1.11
981     void
982 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
983 root 1.12 PROTOTYPE: $$$;$$
984 root 1.76 ALIAS:
985     draw_quad_alpha = 1
986     draw_quad_alpha_premultiplied = 2
987 root 1.11 CODE:
988     {
989 root 1.12 HV *hv = (HV *)SvRV (self);
990 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
991     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
992 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
993 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
994 root 1.12
995     if (items < 5)
996     {
997 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
998     h = SvNV (*hv_fetch (hv, "h", 1, 1));
999 root 1.12 }
1000    
1001 root 1.76 if (ix)
1002     {
1003     glEnable (GL_BLEND);
1004     glBlendFunc (ix == 1 ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1005 root 1.86 glEnable (GL_ALPHA_TEST);
1006     glAlphaFunc (GL_GREATER, 0.01f);
1007 root 1.76 }
1008    
1009 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1010 root 1.76
1011     if (wrap_mode)
1012     {
1013     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1014     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1015     }
1016    
1017 root 1.12 glBegin (GL_QUADS);
1018 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1019     glTexCoord2f (0, t); glVertex2f (x , y + h);
1020     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1021     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1022 root 1.12 glEnd ();
1023 root 1.76
1024     if (ix)
1025 root 1.86 {
1026     glDisable (GL_ALPHA_TEST);
1027     glDisable (GL_BLEND);
1028     }
1029 root 1.11 }
1030 root 1.28
1031     MODULE = CFClient PACKAGE = CFClient::Map
1032    
1033     CFClient::Map
1034     new (SV *class, int map_width, int map_height)
1035     CODE:
1036     New (0, RETVAL, 1, struct map);
1037 root 1.42 RETVAL->x = 0;
1038     RETVAL->y = 0;
1039     RETVAL->w = map_width;
1040     RETVAL->h = map_height;
1041     RETVAL->ox = 0;
1042     RETVAL->oy = 0;
1043 root 1.30 RETVAL->faces = 8192;
1044     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1045 root 1.42 RETVAL->texs = 8192;
1046     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1047 root 1.28 RETVAL->rows = 0;
1048     RETVAL->row = 0;
1049     OUTPUT:
1050     RETVAL
1051    
1052     void
1053     DESTROY (CFClient::Map self)
1054     CODE:
1055     {
1056 root 1.30 map_clear (self);
1057 root 1.28 Safefree (self->face);
1058 root 1.29 Safefree (self);
1059     }
1060    
1061     void
1062 root 1.30 clear (CFClient::Map self)
1063     CODE:
1064     map_clear (self);
1065    
1066     void
1067 root 1.42 set_face (CFClient::Map self, int face, int texid)
1068 root 1.29 CODE:
1069     {
1070 root 1.42 while (self->faces <= face)
1071 root 1.28 {
1072 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1073 root 1.29 self->faces *= 2;
1074     }
1075 root 1.28
1076 root 1.42 self->face [face] = texid;
1077     }
1078    
1079     void
1080     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)
1081     CODE:
1082     {
1083     while (self->texs <= texid)
1084     {
1085     Append (maptex, self->tex, self->texs, self->texs);
1086     self->texs *= 2;
1087     }
1088    
1089 root 1.48 {
1090     maptex *tex = self->tex + texid;
1091 root 1.39
1092 root 1.48 tex->name = name;
1093     tex->w = w;
1094     tex->h = h;
1095     tex->s = s;
1096     tex->t = t;
1097     tex->r = r;
1098     tex->g = g;
1099     tex->b = b;
1100     tex->a = a;
1101     }
1102 root 1.29 }
1103    
1104 root 1.42 int
1105     ox (CFClient::Map self)
1106     ALIAS:
1107     oy = 1
1108     CODE:
1109     switch (ix)
1110     {
1111     case 0: RETVAL = self->ox; break;
1112     case 1: RETVAL = self->oy; break;
1113     }
1114     OUTPUT:
1115     RETVAL
1116    
1117 root 1.29 void
1118 root 1.43 scroll (CFClient::Map self, int dx, int dy)
1119     CODE:
1120     {
1121 root 1.44 if (dx > 0)
1122     map_blank (self, self->x, self->y, dx - 1, self->h);
1123     else if (dx < 0)
1124     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1125    
1126     if (dy > 0)
1127     map_blank (self, self->x, self->y, self->w, dy - 1);
1128     else if (dy < 0)
1129     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1130 root 1.43
1131 root 1.44 self->ox += dx; self->x += dx;
1132     self->oy += dy; self->y += dy;
1133 root 1.43
1134     while (self->y < 0)
1135     {
1136     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1137    
1138     self->rows += MAP_EXTEND_Y;
1139     self->y += MAP_EXTEND_Y;
1140     }
1141 root 1.44 }
1142 root 1.43
1143 root 1.44 void
1144     map1a_update (CFClient::Map self, SV *data_)
1145     CODE:
1146     {
1147 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1148     uint8_t *data_end = (uint8_t *)SvEND (data_);
1149 root 1.48 mapcell *cell;
1150     int x, y, flags;
1151 root 1.43
1152 root 1.29 while (data < data_end)
1153     {
1154 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1155 root 1.30
1156 root 1.48 x = ((flags >> 10) & 63) + self->x;
1157     y = ((flags >> 4) & 63) + self->y;
1158 root 1.29
1159 root 1.48 cell = map_get_cell (self, x, y);
1160 root 1.29
1161     if (flags & 15)
1162     {
1163 root 1.45 if (cell->darkness < 0)
1164 root 1.29 {
1165     cell->darkness = 0;
1166     cell->face [0] = 0;
1167     cell->face [1] = 0;
1168     cell->face [2] = 0;
1169     }
1170 root 1.45
1171 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1172    
1173 root 1.42 //TODO: don't trust server data to be in-range(!)
1174    
1175 root 1.29 if (flags & 4)
1176     {
1177 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1178 root 1.29 }
1179    
1180     if (flags & 2)
1181     {
1182 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1183 root 1.29 }
1184    
1185     if (flags & 1)
1186     {
1187 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1188 root 1.29 }
1189     }
1190     else
1191 root 1.31 cell->darkness = -1;
1192 root 1.29 }
1193 root 1.28 }
1194    
1195 root 1.40 SV *
1196 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1197 root 1.40 CODE:
1198     {
1199 root 1.55 int x1, x;
1200     int y1, y;
1201 root 1.40 int z;
1202     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1203     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1204    
1205     SvPOK_only (map_sv);
1206     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1207    
1208 root 1.55 x0 += self->x; x1 = x0 + w;
1209     y0 += self->y; y1 = y0 + h;
1210 root 1.40
1211     for (y = y0; y < y1; y++)
1212     {
1213     maprow *row = 0 <= y && y < self->rows
1214     ? self->row + y
1215     : 0;
1216    
1217     for (x = x0; x < x1; x++)
1218     {
1219     int r = 32, g = 32, b = 32, a = 192;
1220    
1221     if (row && row->c0 <= x && x < row->c1)
1222     {
1223     mapcell *cell = row->col + (x - row->c0);
1224    
1225     for (z = 0; z <= 0; z++)
1226     {
1227 root 1.42 mapface face = cell->face [z];
1228 root 1.40
1229     if (face)
1230     {
1231 root 1.42 maptex tex = self->tex [face];
1232 root 1.40 int a0 = 255 - tex.a;
1233     int a1 = tex.a;
1234    
1235     r = (r * a0 + tex.r * a1) / 255;
1236     g = (g * a0 + tex.g * a1) / 255;
1237     b = (b * a0 + tex.b * a1) / 255;
1238     a = (a * a0 + tex.a * a1) / 255;
1239     }
1240     }
1241     }
1242    
1243     *map++ = (r )
1244     | (g << 8)
1245     | (b << 16)
1246     | (a << 24);
1247     }
1248     }
1249    
1250     RETVAL = map_sv;
1251     }
1252     OUTPUT:
1253     RETVAL
1254    
1255 root 1.30 void
1256 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1257 root 1.32 PPCODE:
1258 root 1.30 {
1259 root 1.48 int vx, vy;
1260     int x, y, z;
1261     int last_name;
1262     mapface face;
1263 root 1.32 int sw4 = (sw + 3) & ~3;
1264     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1265 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1266 root 1.48
1267 root 1.42 memset (darkness, 255, sw4 * sh);
1268 root 1.32 SvPOK_only (darkness_sv);
1269     SvCUR_set (darkness_sv, sw4 * sh);
1270    
1271 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1272     vy = self->y + (self->h - sh) / 2 - shift_y;
1273 root 1.38
1274 root 1.42 /*
1275     int vx = self->vx = self->w >= sw
1276     ? self->x + (self->w - sw) / 2
1277     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1278    
1279     int vy = self->vy = self->h >= sh
1280     ? self->y + (self->h - sh) / 2
1281     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1282     */
1283 root 1.30
1284     glColor4ub (255, 255, 255, 255);
1285    
1286     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1287     glEnable (GL_BLEND);
1288     glEnable (GL_TEXTURE_2D);
1289     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1290    
1291 root 1.48 glBegin (GL_QUADS);
1292 root 1.30
1293 root 1.48 last_name = 0;
1294 root 1.30
1295     for (z = 0; z < 3; z++)
1296     for (y = 0; y < sh; y++)
1297     if (0 <= y + vy && y + vy < self->rows)
1298     {
1299     maprow *row = self->row + (y + vy);
1300    
1301     for (x = 0; x < sw; x++)
1302     if (row->c0 <= x + vx && x + vx < row->c1)
1303     {
1304     mapcell *cell = row->col + (x + vx - row->c0);
1305 root 1.32
1306     darkness[y * sw4 + x] = cell->darkness < 0
1307 root 1.33 ? 255 - FOW_DARKNESS
1308 root 1.32 : 255 - cell->darkness;
1309    
1310 root 1.48 face = cell->face [z];
1311 root 1.30
1312     if (face)
1313     {
1314 root 1.42 maptex tex = self->tex [face];
1315 root 1.30
1316     int px = (x + 1) * 32 - tex.w;
1317     int py = (y + 1) * 32 - tex.h;
1318    
1319     if (last_name != tex.name)
1320     {
1321     glEnd ();
1322     last_name = tex.name;
1323     glBindTexture (GL_TEXTURE_2D, last_name);
1324     glBegin (GL_QUADS);
1325     }
1326    
1327     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1328     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1329     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1330     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1331     }
1332     }
1333     }
1334    
1335     glEnd ();
1336 root 1.32
1337 root 1.34 glDisable (GL_TEXTURE_2D);
1338     glDisable (GL_BLEND);
1339    
1340 root 1.32 EXTEND (SP, 3);
1341     PUSHs (sv_2mortal (newSViv (sw4)));
1342     PUSHs (sv_2mortal (newSViv (sh)));
1343     PUSHs (darkness_sv);
1344 root 1.30 }
1345    
1346 root 1.42 SV *
1347     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1348     CODE:
1349     {
1350     int x, y, x1, y1;
1351     SV *data_sv = newSV (w * h * 7 + 5);
1352     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1353    
1354     *data++ = 0; /* version 0 format */
1355     *data++ = w >> 8; *data++ = w;
1356     *data++ = h >> 8; *data++ = h;
1357    
1358     // we need to do this 'cause we don't keep an absolute coord system for rows
1359 root 1.55 // TODO: treat rows as we treat columns
1360 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1361     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1362    
1363     x0 += self->x - self->ox;
1364     y0 += self->y - self->oy;
1365    
1366     x1 = x0 + w;
1367     y1 = y0 + h;
1368    
1369     for (y = y0; y < y1; y++)
1370     {
1371     maprow *row = 0 <= y && y < self->rows
1372     ? self->row + y
1373     : 0;
1374    
1375     for (x = x0; x < x1; x++)
1376     {
1377     if (row && row->c0 <= x && x < row->c1)
1378     {
1379     mapcell *cell = row->col + (x - row->c0);
1380     uint8_t flags = 0;
1381    
1382     if (cell->face [0]) flags |= 1;
1383     if (cell->face [1]) flags |= 2;
1384     if (cell->face [2]) flags |= 4;
1385    
1386     *data++ = flags;
1387    
1388     if (flags & 1)
1389     {
1390     *data++ = cell->face [0] >> 8;
1391     *data++ = cell->face [0];
1392     }
1393    
1394     if (flags & 2)
1395     {
1396     *data++ = cell->face [1] >> 8;
1397     *data++ = cell->face [1];
1398     }
1399    
1400     if (flags & 4)
1401     {
1402     *data++ = cell->face [2] >> 8;
1403     *data++ = cell->face [2];
1404     }
1405     }
1406     else
1407     *data++ = 0;
1408     }
1409     }
1410    
1411     SvPOK_only (data_sv);
1412     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1413     RETVAL = data_sv;
1414     }
1415     OUTPUT:
1416     RETVAL
1417    
1418     void
1419     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1420     PPCODE:
1421     {
1422     int x, y, z;
1423 root 1.48 int w, h;
1424 root 1.42 int x1, y1;
1425    
1426     if (*data++ != 0)
1427     return; /* version mismatch */
1428    
1429 root 1.48 w = *data++ << 8; w |= *data++;
1430     h = *data++ << 8; h |= *data++;
1431 root 1.42
1432     // we need to do this 'cause we don't keep an absolute coord system for rows
1433 root 1.55 // TODO: treat rows as we treat columns
1434 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1435     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1436    
1437     x0 += self->x - self->ox;
1438     y0 += self->y - self->oy;
1439    
1440     x1 = x0 + w;
1441     y1 = y0 + h;
1442    
1443     for (y = y0; y < y1; y++)
1444     {
1445     maprow *row = map_get_row (self, y);
1446    
1447     for (x = x0; x < x1; x++)
1448     {
1449     uint8_t flags = *data++;
1450    
1451     if (flags)
1452     {
1453     mapface face[3] = { 0, 0, 0 };
1454    
1455     mapcell *cell = row_get_cell (row, x);
1456    
1457     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1458     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1459     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1460    
1461     if (cell->darkness <= 0)
1462     {
1463     cell->darkness = -1;
1464    
1465     for (z = 0; z <= 2; z++)
1466     {
1467     cell->face[z] = face[z];
1468    
1469     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1470     XPUSHs (sv_2mortal (newSViv (face[z])));
1471     }
1472     }
1473     }
1474     }
1475     }
1476     }
1477    
1478 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1479    
1480     CFClient::MixChunk
1481     new_from_file (SV *class, char *path)
1482     CODE:
1483     RETVAL = Mix_LoadWAV (path);
1484     OUTPUT:
1485     RETVAL
1486    
1487     void
1488     DESTROY (CFClient::MixChunk self)
1489     CODE:
1490     Mix_FreeChunk (self);
1491    
1492     int
1493     volume (CFClient::MixChunk self, int volume = -1)
1494     CODE:
1495     RETVAL = Mix_VolumeChunk (self, volume);
1496     OUTPUT:
1497     RETVAL
1498    
1499     int
1500     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1501     CODE:
1502     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1503     OUTPUT:
1504     RETVAL
1505    
1506     MODULE = CFClient PACKAGE = CFClient::MixMusic
1507    
1508     int
1509     volume (int volume = -1)
1510     CODE:
1511     RETVAL = Mix_VolumeMusic (volume);
1512     OUTPUT:
1513     RETVAL
1514    
1515     CFClient::MixMusic
1516     new_from_file (SV *class, char *path)
1517     CODE:
1518     RETVAL = Mix_LoadMUS (path);
1519     OUTPUT:
1520     RETVAL
1521    
1522     void
1523     DESTROY (CFClient::MixMusic self)
1524     CODE:
1525     Mix_FreeMusic (self);
1526    
1527     int
1528     play (CFClient::MixMusic self, int loops = -1)
1529     CODE:
1530     RETVAL = Mix_PlayMusic (self, loops);
1531     OUTPUT:
1532     RETVAL
1533    
1534 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1535    
1536     BOOT:
1537     {
1538     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1539     static const struct {
1540     const char *name;
1541     IV iv;
1542     } *civ, const_iv[] = {
1543     # define const_iv(name) { # name, (IV)name }
1544     const_iv (GL_COLOR_MATERIAL),
1545     const_iv (GL_SMOOTH),
1546     const_iv (GL_FLAT),
1547 root 1.69 const_iv (GL_DITHER),
1548 root 1.54 const_iv (GL_BLEND),
1549 root 1.89 const_iv (GL_CULL_FACE),
1550 root 1.69 const_iv (GL_SCISSOR_TEST),
1551 root 1.89 const_iv (GL_DEPTH_TEST),
1552     const_iv (GL_ALPHA_TEST),
1553     const_iv (GL_NORMALIZE),
1554     const_iv (GL_RESCALE_NORMAL),
1555 root 1.54 const_iv (GL_AND),
1556 root 1.67 const_iv (GL_ONE),
1557     const_iv (GL_ZERO),
1558 root 1.54 const_iv (GL_SRC_ALPHA),
1559 root 1.67 const_iv (GL_SRC_ALPHA_SATURATE),
1560 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1561 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1562 root 1.54 const_iv (GL_RGB),
1563     const_iv (GL_RGBA),
1564     const_iv (GL_UNSIGNED_BYTE),
1565 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1566     const_iv (GL_UNSIGNED_INT),
1567 root 1.54 const_iv (GL_ALPHA),
1568 root 1.86 const_iv (GL_INTENSITY),
1569 root 1.76 const_iv (GL_LUMINANCE),
1570 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1571 root 1.54 const_iv (GL_FLOAT),
1572     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1573     const_iv (GL_COMPILE),
1574     const_iv (GL_TEXTURE_1D),
1575     const_iv (GL_TEXTURE_2D),
1576     const_iv (GL_TEXTURE_ENV),
1577     const_iv (GL_TEXTURE_MAG_FILTER),
1578     const_iv (GL_TEXTURE_MIN_FILTER),
1579     const_iv (GL_TEXTURE_ENV_MODE),
1580     const_iv (GL_TEXTURE_WRAP_S),
1581     const_iv (GL_TEXTURE_WRAP_T),
1582     const_iv (GL_CLAMP),
1583     const_iv (GL_REPEAT),
1584     const_iv (GL_NEAREST),
1585     const_iv (GL_LINEAR),
1586 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1587     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1588     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1589     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1590     const_iv (GL_GENERATE_MIPMAP),
1591 root 1.54 const_iv (GL_MODULATE),
1592 root 1.69 const_iv (GL_DECAL),
1593 root 1.54 const_iv (GL_REPLACE),
1594 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1595 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1596     const_iv (GL_PROJECTION),
1597     const_iv (GL_MODELVIEW),
1598     const_iv (GL_COLOR_LOGIC_OP),
1599 root 1.69 const_iv (GL_SEPARABLE_2D),
1600 root 1.54 const_iv (GL_CONVOLUTION_2D),
1601     const_iv (GL_CONVOLUTION_BORDER_MODE),
1602     const_iv (GL_CONSTANT_BORDER),
1603     const_iv (GL_LINES),
1604 root 1.89 const_iv (GL_LINE_LOOP),
1605 root 1.54 const_iv (GL_QUADS),
1606 root 1.89 const_iv (GL_QUAD_STRIP),
1607     const_iv (GL_TRIANGLES),
1608     const_iv (GL_TRIANGLE_STRIP),
1609     const_iv (GL_TRIANGLE_FAN),
1610 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1611     const_iv (GL_FASTEST),
1612 root 1.89 const_iv (GL_V2F),
1613     const_iv (GL_V3F),
1614     const_iv (GL_T2F_V3F),
1615     const_iv (GL_T2F_N3F_V3F),
1616 root 1.54 # undef const_iv
1617     };
1618    
1619     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1620     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1621     }
1622    
1623     int glGetError ()
1624    
1625     void glClear (int mask)
1626    
1627     void glClearColor (float r, float g, float b, float a = 1.0)
1628     PROTOTYPE: @
1629    
1630     void glEnable (int cap)
1631    
1632     void glDisable (int cap)
1633    
1634     void glShadeModel (int mode)
1635    
1636     void glHint (int target, int mode)
1637    
1638     void glBlendFunc (int sfactor, int dfactor)
1639    
1640 root 1.89 void glDepthMask (int flag)
1641    
1642 root 1.54 void glLogicOp (int opcode)
1643    
1644 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1645    
1646 root 1.54 void glMatrixMode (int mode)
1647    
1648     void glPushMatrix ()
1649    
1650     void glPopMatrix ()
1651    
1652     void glLoadIdentity ()
1653    
1654 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1655     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1656    
1657     # near_ and far_ are due to microsofts buggy "c" compiler
1658 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1659 root 1.54
1660     void glViewport (int x, int y, int width, int height)
1661    
1662 root 1.69 void glScissor (int x, int y, int width, int height)
1663    
1664 root 1.54 void glTranslate (float x, float y, float z = 0.)
1665     CODE:
1666     glTranslatef (x, y, z);
1667    
1668 root 1.62 void glScale (float x, float y, float z = 1.)
1669 root 1.54 CODE:
1670     glScalef (x, y, z);
1671    
1672     void glRotate (float angle, float x, float y, float z)
1673     CODE:
1674     glRotatef (angle, x, y, z);
1675    
1676     void glBegin (int mode)
1677    
1678     void glEnd ()
1679    
1680     void glColor (float r, float g, float b, float a = 1.0)
1681     PROTOTYPE: @
1682     CODE:
1683 root 1.90 // microsoft visual "c" rounds instead of truncating...
1684 root 1.81 glColor4ub (MIN ((int)(r * 255.f), 255),
1685     MIN ((int)(g * 255.f), 255),
1686     MIN ((int)(b * 255.f), 255),
1687     MIN ((int)(a * 255.f), 255));
1688 root 1.54
1689 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1690    
1691     void glDrawElements (int mode, int count, int type, char *indices)
1692    
1693     # 1.2 void glDrawRangeElements (int mode, int start, int end
1694    
1695 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1696     CODE:
1697     glRasterPos3f (0, 0, z);
1698     glBitmap (0, 0, 0, 0, x, y, 0);
1699    
1700 root 1.54 void glVertex (float x, float y, float z = 0.)
1701     CODE:
1702     glVertex3f (x, y, z);
1703    
1704     void glTexCoord (float s, float t)
1705     CODE:
1706     glTexCoord2f (s, t);
1707    
1708     void glTexEnv (int target, int pname, float param)
1709     CODE:
1710     glTexEnvf (target, pname, param);
1711    
1712     void glTexParameter (int target, int pname, float param)
1713     CODE:
1714     glTexParameterf (target, pname, param);
1715    
1716     void glBindTexture (int target, int name)
1717    
1718     void glConvolutionParameter (int target, int pname, float params)
1719     CODE:
1720 root 1.64 GL_CALL (PFNGLCONVOLUTIONPARAMETERFEXTPROC, glConvolutionParameterf, (target, pname, params));
1721 root 1.54
1722     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1723 root 1.64 CODE:
1724     GL_CALL (PFNGLCONVOLUTIONFILTER2DEXTPROC, glConvolutionFilter2D,
1725     (target, internalformat, width, height, format, type, data));
1726 root 1.54
1727 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1728     CODE:
1729     GL_CALL (PFNGLSEPARABLEFILTER2DEXTPROC, glSeparableFilter2D,
1730     (target, internalformat, width, height, format, type, row, column));
1731    
1732 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1733    
1734     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1735    
1736 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1737 root 1.68
1738     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1739    
1740 root 1.54 int glGenTexture ()
1741     CODE:
1742     {
1743     GLuint name;
1744     glGenTextures (1, &name);
1745     RETVAL = name;
1746     }
1747     OUTPUT:
1748     RETVAL
1749    
1750     void glDeleteTexture (int name)
1751     CODE:
1752     {
1753     GLuint name_ = name;
1754     glDeleteTextures (1, &name_);
1755     }
1756    
1757     int glGenList ()
1758     CODE:
1759     RETVAL = glGenLists (1);
1760     OUTPUT:
1761     RETVAL
1762    
1763     void glDeleteList (int list)
1764     CODE:
1765     glDeleteLists (list, 1);
1766    
1767     void glNewList (int list, int mode = GL_COMPILE)
1768    
1769     void glEndList ()
1770    
1771     void glCallList (int list)
1772    
1773 root 1.89