ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.88
Committed: Fri May 19 23:18:40 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.87: +5 -2 lines
Log Message:
implement face animation, fix inventory layout

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.85 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
450    
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.69 const_iv (GL_SCISSOR_TEST),
1536 root 1.54 const_iv (GL_AND),
1537 root 1.67 const_iv (GL_ONE),
1538     const_iv (GL_ZERO),
1539 root 1.54 const_iv (GL_SRC_ALPHA),
1540 root 1.67 const_iv (GL_SRC_ALPHA_SATURATE),
1541 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1542 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1543 root 1.54 const_iv (GL_RGB),
1544     const_iv (GL_RGBA),
1545     const_iv (GL_UNSIGNED_BYTE),
1546     const_iv (GL_ALPHA),
1547 root 1.86 const_iv (GL_INTENSITY),
1548 root 1.76 const_iv (GL_LUMINANCE),
1549 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1550 root 1.54 const_iv (GL_FLOAT),
1551     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1552     const_iv (GL_COMPILE),
1553     const_iv (GL_TEXTURE_1D),
1554     const_iv (GL_TEXTURE_2D),
1555     const_iv (GL_TEXTURE_ENV),
1556     const_iv (GL_TEXTURE_MAG_FILTER),
1557     const_iv (GL_TEXTURE_MIN_FILTER),
1558     const_iv (GL_TEXTURE_ENV_MODE),
1559     const_iv (GL_TEXTURE_WRAP_S),
1560     const_iv (GL_TEXTURE_WRAP_T),
1561     const_iv (GL_CLAMP),
1562     const_iv (GL_REPEAT),
1563     const_iv (GL_NEAREST),
1564     const_iv (GL_LINEAR),
1565 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1566     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1567     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1568     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1569     const_iv (GL_GENERATE_MIPMAP),
1570 root 1.54 const_iv (GL_MODULATE),
1571 root 1.69 const_iv (GL_DECAL),
1572 root 1.54 const_iv (GL_REPLACE),
1573     const_iv (GL_COLOR_BUFFER_BIT),
1574     const_iv (GL_PROJECTION),
1575     const_iv (GL_MODELVIEW),
1576     const_iv (GL_COLOR_LOGIC_OP),
1577 root 1.69 const_iv (GL_SEPARABLE_2D),
1578 root 1.54 const_iv (GL_CONVOLUTION_2D),
1579     const_iv (GL_CONVOLUTION_BORDER_MODE),
1580     const_iv (GL_CONSTANT_BORDER),
1581     const_iv (GL_LINES),
1582     const_iv (GL_QUADS),
1583 root 1.55 const_iv (GL_LINE_LOOP),
1584 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1585     const_iv (GL_FASTEST),
1586     # undef const_iv
1587     };
1588    
1589     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1590     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1591     }
1592    
1593     int glGetError ()
1594    
1595     void glClear (int mask)
1596    
1597     void glClearColor (float r, float g, float b, float a = 1.0)
1598     PROTOTYPE: @
1599    
1600     void glEnable (int cap)
1601    
1602     void glDisable (int cap)
1603    
1604     void glShadeModel (int mode)
1605    
1606     void glHint (int target, int mode)
1607    
1608     void glBlendFunc (int sfactor, int dfactor)
1609    
1610     void glLogicOp (int opcode)
1611    
1612 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1613    
1614 root 1.54 void glMatrixMode (int mode)
1615    
1616     void glPushMatrix ()
1617    
1618     void glPopMatrix ()
1619    
1620     void glLoadIdentity ()
1621    
1622 root 1.64 # near and far are due to microsofts buggy c compiler
1623     void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1624 root 1.54
1625     void glViewport (int x, int y, int width, int height)
1626    
1627 root 1.69 void glScissor (int x, int y, int width, int height)
1628    
1629 root 1.54 void glTranslate (float x, float y, float z = 0.)
1630     CODE:
1631     glTranslatef (x, y, z);
1632    
1633 root 1.62 void glScale (float x, float y, float z = 1.)
1634 root 1.54 CODE:
1635     glScalef (x, y, z);
1636    
1637     void glRotate (float angle, float x, float y, float z)
1638     CODE:
1639     glRotatef (angle, x, y, z);
1640    
1641     void glBegin (int mode)
1642    
1643     void glEnd ()
1644    
1645     void glColor (float r, float g, float b, float a = 1.0)
1646     PROTOTYPE: @
1647     CODE:
1648 root 1.81 glColor4ub (MIN ((int)(r * 255.f), 255),
1649     MIN ((int)(g * 255.f), 255),
1650     MIN ((int)(b * 255.f), 255),
1651     MIN ((int)(a * 255.f), 255));
1652 root 1.54
1653     void glVertex (float x, float y, float z = 0.)
1654     CODE:
1655     glVertex3f (x, y, z);
1656    
1657     void glTexCoord (float s, float t)
1658     CODE:
1659     glTexCoord2f (s, t);
1660    
1661     void glTexEnv (int target, int pname, float param)
1662     CODE:
1663     glTexEnvf (target, pname, param);
1664    
1665     void glTexParameter (int target, int pname, float param)
1666     CODE:
1667     glTexParameterf (target, pname, param);
1668    
1669     void glBindTexture (int target, int name)
1670    
1671     void glConvolutionParameter (int target, int pname, float params)
1672     CODE:
1673 root 1.64 GL_CALL (PFNGLCONVOLUTIONPARAMETERFEXTPROC, glConvolutionParameterf, (target, pname, params));
1674 root 1.54
1675     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1676 root 1.64 CODE:
1677     GL_CALL (PFNGLCONVOLUTIONFILTER2DEXTPROC, glConvolutionFilter2D,
1678     (target, internalformat, width, height, format, type, data));
1679 root 1.54
1680 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1681     CODE:
1682     GL_CALL (PFNGLSEPARABLEFILTER2DEXTPROC, glSeparableFilter2D,
1683     (target, internalformat, width, height, format, type, row, column));
1684    
1685 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1686    
1687     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1688    
1689 root 1.68 void glRasterPos (int x, int y)
1690     CODE:
1691     glRasterPos2i (x, y);
1692    
1693     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1694    
1695 root 1.54 int glGenTexture ()
1696     CODE:
1697     {
1698     GLuint name;
1699     glGenTextures (1, &name);
1700     RETVAL = name;
1701     }
1702     OUTPUT:
1703     RETVAL
1704    
1705     void glDeleteTexture (int name)
1706     CODE:
1707     {
1708     GLuint name_ = name;
1709     glDeleteTextures (1, &name_);
1710     }
1711    
1712     int glGenList ()
1713     CODE:
1714     RETVAL = glGenLists (1);
1715     OUTPUT:
1716     RETVAL
1717    
1718     void glDeleteList (int list)
1719     CODE:
1720     glDeleteLists (list, 1);
1721    
1722     void glNewList (int list, int mode = GL_COMPILE)
1723    
1724     void glEndList ()
1725    
1726     void glCallList (int list)
1727