ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.89
Committed: Sun May 21 00:02:01 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.88: +27 -2 lines
Log Message:
very alpha code for model drawing hacked in

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