ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.236
Committed: Mon Oct 8 16:10:14 2007 UTC (16 years, 7 months ago) by root
Branch: MAIN
Changes since 1.235: +19 -1 lines
Log Message:
- create audio settings for frequency, channels, mixer voices and chunksize
- tune audio defaults ot be much less demanding

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.170 # define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.157 # include <wininet.h>
7 root 1.75 # pragma warning(disable:4244)
8 root 1.162 # pragma warning(disable:4761)
9 root 1.48 #endif
10    
11 root 1.193 //#define DEBUG 1
12     #if DEBUG
13     # include <valgrind/memcheck.h>
14     #endif
15    
16 root 1.1 #include "EXTERN.h"
17     #include "perl.h"
18     #include "XSUB.h"
19    
20 root 1.131 #ifdef _WIN32
21     # undef pipe
22 root 1.222 // microsoft vs. C
23     # define sqrtf(x) sqrt(x)
24     # define roundf(x) (int)(x)
25     # define atan2f(x,y) atan2(x,y)
26     # define M_PI 3.14159265f
27 root 1.131 #endif
28    
29 root 1.168 #include <assert.h>
30 root 1.80 #include <math.h>
31 root 1.5 #include <string.h>
32 root 1.25 #include <stdio.h>
33 root 1.111 #include <stdlib.h>
34 root 1.5
35 root 1.212 #define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
36    
37 root 1.2 #include <SDL.h>
38 root 1.202 #include <SDL_thread.h>
39 root 1.76 #include <SDL_endian.h>
40 root 1.23 #include <SDL_image.h>
41 root 1.52 #include <SDL_mixer.h>
42 root 1.3 #include <SDL_opengl.h>
43 root 1.5
44 root 1.124 #define PANGO_ENABLE_BACKEND
45     #define G_DISABLE_CAST_CHECKS
46    
47 root 1.30 #include <glib/gmacros.h>
48    
49 root 1.5 #include <pango/pango.h>
50    
51 root 1.48 #ifndef _WIN32
52     # include <sys/types.h>
53     # include <sys/socket.h>
54     # include <netinet/in.h>
55     # include <netinet/tcp.h>
56     # include <inttypes.h>
57     #endif
58 root 1.28
59 root 1.162 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
60 root 1.121
61 root 1.29 #define FOW_DARKNESS 32
62    
63     #define MAP_EXTEND_X 32
64     #define MAP_EXTEND_Y 512
65    
66 root 1.63 #define MIN_FONT_HEIGHT 10
67 root 1.58
68 root 1.127 #if 0
69 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
70     #else
71     # define PARACHUTE 0
72     #endif
73    
74 root 1.188 static AV *texture_av;
75    
76 root 1.103 static struct
77     {
78     #define GL_FUNC(ptr,name) ptr name;
79     #include "glfunc.h"
80     #undef GL_FUNC
81     } gl;
82    
83 root 1.192 static void
84     gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
85 root 1.103 {
86     if (gl.BlendFuncSeparate)
87     gl.BlendFuncSeparate (sa, da, saa, daa);
88     else if (gl.BlendFuncSeparateEXT)
89     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
90     else
91     glBlendFunc (sa, da);
92     }
93 root 1.64
94 root 1.192 static GLuint
95     gen_texture ()
96     {
97     GLuint name;
98    
99     if (AvFILL (texture_av) >= 0)
100     name = (GLuint)(size_t)av_pop (texture_av);
101     else
102     glGenTextures (1, &name);
103    
104     return name;
105     }
106    
107     static void
108     del_texture (GLuint name)
109     {
110     /* make a half-assed attempt at returning the memory used by the texture */
111     /* textures are frequently being reused by cfplus anyway */
112     /*glBindTexture (GL_TEXTURE_2D, name);*/
113     /*glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);*/
114     av_push (texture_av, (SV *)(size_t)name);
115     glDeleteTextures (1, &name);
116     }
117    
118 root 1.124 #include "texcache.c"
119 root 1.223 #include "rendercache.c"
120 root 1.124
121     #include "pango-font.c"
122     #include "pango-fontmap.c"
123     #include "pango-render.c"
124    
125 root 1.212 typedef IV CFPlus__Channel;
126     typedef SDL_RWops *CFPlus__RW;
127 root 1.133 typedef Mix_Chunk *CFPlus__MixChunk;
128     typedef Mix_Music *CFPlus__MixMusic;
129 root 1.52
130 root 1.133 typedef PangoFontDescription *CFPlus__Font;
131 root 1.2
132 root 1.121 static int
133     shape_attr_p (PangoLayoutRun *run)
134     {
135     GSList *attrs = run->item->analysis.extra_attrs;
136    
137     while (attrs)
138     {
139     PangoAttribute *attr = attrs->data;
140    
141     if (attr->klass->type == PANGO_ATTR_SHAPE)
142     return 1;
143    
144     attrs = attrs->next;
145     }
146    
147     return 0;
148     }
149    
150 root 1.14 typedef struct cf_layout {
151 root 1.124 PangoLayout *pl;
152 root 1.76 float r, g, b, a; // default color for rgba mode
153 root 1.14 int base_height;
154 root 1.133 CFPlus__Font font;
155 root 1.225 rc_t *rc;
156 root 1.133 } *CFPlus__Layout;
157 root 1.14
158 root 1.133 static CFPlus__Font default_font;
159 root 1.124 static PangoContext *opengl_context;
160     static PangoFontMap *opengl_fontmap;
161 root 1.61
162 root 1.14 static void
163 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
164     {
165 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
166 root 1.110 #ifdef FC_HINT_STYLE
167 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
168 root 1.110 #endif
169 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
170 root 1.19 }
171    
172     static void
173 root 1.133 layout_update_font (CFPlus__Layout self)
174 root 1.17 {
175 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
176     * reasonably well with bitstream vera
177     */
178 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
179 root 1.46
180 root 1.61 pango_font_description_set_absolute_size (font,
181     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
182 root 1.58
183 root 1.61 pango_layout_set_font_description (self->pl, font);
184 root 1.17 }
185    
186     static void
187 root 1.133 layout_get_pixel_size (CFPlus__Layout self, int *w, int *h)
188 root 1.14 {
189 root 1.139 PangoRectangle rect;
190 root 1.14
191 root 1.139 // get_pixel_* wrongly rounds down
192     pango_layout_get_extents (self->pl, 0, &rect);
193 root 1.76
194 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
195     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
196    
197     if (!rect.width) rect.width = 1;
198     if (!rect.height) rect.height = 1;
199    
200     *w = rect.width;
201     *h = rect.height;
202 root 1.14 }
203    
204 root 1.174 typedef uint16_t tileid;
205     typedef uint16_t faceid;
206 root 1.42
207 root 1.28 typedef struct {
208 root 1.228 GLuint name;
209 root 1.30 int w, h;
210     float s, t;
211 root 1.39 uint8_t r, g, b, a;
212 root 1.176 tileid smoothtile;
213     uint8_t smoothlevel;
214 root 1.42 } maptex;
215 root 1.30
216     typedef struct {
217 root 1.153 uint32_t player;
218 root 1.174 tileid tile[3];
219 root 1.142 uint16_t darkness;
220 root 1.176 uint8_t stat_width, stat_hp, flags, smoothmax;
221 root 1.28 } mapcell;
222    
223     typedef struct {
224 root 1.30 int32_t c0, c1;
225 root 1.28 mapcell *col;
226     } maprow;
227    
228     typedef struct map {
229     int x, y, w, h;
230 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
231 root 1.174 int faces; tileid *face2tile; // [faceid]
232     int texs; maptex *tex; // [tileid]
233 root 1.42
234 root 1.48 int32_t rows;
235 root 1.28 maprow *row;
236 root 1.133 } *CFPlus__Map;
237 root 1.28
238 root 1.30 static char *
239     prepend (char *ptr, int sze, int inc)
240     {
241     char *p;
242    
243     New (0, p, sze + inc, char);
244     Zero (p, inc, char);
245     Move (ptr, p + inc, sze, char);
246     Safefree (ptr);
247    
248     return p;
249     }
250    
251     static char *
252     append (char *ptr, int sze, int inc)
253     {
254     Renew (ptr, sze + inc, char);
255     Zero (ptr + sze, inc, char);
256    
257     return ptr;
258     }
259    
260     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
261     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
262    
263 root 1.174 static void
264     need_facenum (struct map *self, faceid face)
265     {
266     while (self->faces <= face)
267     {
268     Append (tileid, self->face2tile, self->faces, self->faces);
269     self->faces *= 2;
270     }
271     }
272    
273     static void
274     need_texid (struct map *self, int texid)
275     {
276     while (self->texs <= texid)
277     {
278     Append (maptex, self->tex, self->texs, self->texs);
279     self->texs *= 2;
280     }
281     }
282    
283 root 1.42 static maprow *
284 root 1.133 map_get_row (CFPlus__Map self, int y)
285 root 1.42 {
286     if (0 > y)
287     {
288     int extend = - y + MAP_EXTEND_Y;
289     Prepend (maprow, self->row, self->rows, extend);
290    
291     self->rows += extend;
292     self->y += extend;
293     y += extend;
294     }
295     else if (y >= self->rows)
296     {
297     int extend = y - self->rows + MAP_EXTEND_Y;
298     Append (maprow, self->row, self->rows, extend);
299     self->rows += extend;
300     }
301    
302     return self->row + y;
303     }
304    
305     static mapcell *
306     row_get_cell (maprow *row, int x)
307     {
308     if (!row->col)
309     {
310     Newz (0, row->col, MAP_EXTEND_X, mapcell);
311     row->c0 = x - MAP_EXTEND_X / 4;
312     row->c1 = row->c0 + MAP_EXTEND_X;
313     }
314    
315     if (row->c0 > x)
316     {
317     int extend = row->c0 - x + MAP_EXTEND_X;
318     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
319     row->c0 -= extend;
320     }
321     else if (x >= row->c1)
322     {
323     int extend = x - row->c1 + MAP_EXTEND_X;
324     Append (mapcell, row->col, row->c1 - row->c0, extend);
325     row->c1 += extend;
326     }
327    
328     return row->col + (x - row->c0);
329     }
330    
331     static mapcell *
332 root 1.133 map_get_cell (CFPlus__Map self, int x, int y)
333 root 1.42 {
334     return row_get_cell (map_get_row (self, y), x);
335     }
336    
337 root 1.30 static void
338 root 1.133 map_clear (CFPlus__Map self)
339 root 1.30 {
340     int r;
341    
342     for (r = 0; r < self->rows; r++)
343     Safefree (self->row[r].col);
344    
345     Safefree (self->row);
346    
347     self->x = 0;
348     self->y = 0;
349 root 1.42 self->ox = 0;
350     self->oy = 0;
351 root 1.30 self->row = 0;
352     self->rows = 0;
353     }
354    
355 root 1.29 static void
356 root 1.133 map_blank (CFPlus__Map self, int x0, int y0, int w, int h)
357 root 1.29 {
358     int x, y;
359 root 1.48 maprow *row;
360 root 1.146 mapcell *cell;
361 root 1.29
362     for (y = y0; y < y0 + h; y++)
363 root 1.30 if (y >= 0)
364     {
365     if (y >= self->rows)
366     break;
367    
368 root 1.48 row = self->row + y;
369 root 1.30
370     for (x = x0; x < x0 + w; x++)
371     if (x >= row->c0)
372     {
373     if (x >= row->c1)
374     break;
375 root 1.29
376 root 1.146 cell = row->col + x - row->c0;
377    
378     cell->darkness = 0;
379     cell->stat_hp = 0;
380 root 1.154 cell->flags = 0;
381     cell->player = 0;
382 root 1.30 }
383     }
384 root 1.29 }
385    
386 root 1.176 typedef struct {
387     tileid tile;
388     uint8_t x, y, level;
389     } smooth_key;
390    
391     static void
392     smooth_or_bits (HV *hv, smooth_key *key, IV bits)
393     {
394 root 1.181 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1);
395 root 1.176
396     if (SvIOK (*sv))
397     SvIV_set (*sv, SvIVX (*sv) | bits);
398     else
399     sv_setiv (*sv, bits);
400     }
401    
402 root 1.56 static void
403 root 1.75 music_finished (void)
404 root 1.56 {
405     SDL_UserEvent ev;
406    
407     ev.type = SDL_USEREVENT;
408     ev.code = 0;
409     ev.data1 = 0;
410     ev.data2 = 0;
411    
412 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
413 root 1.56 }
414    
415 root 1.71 static void
416     channel_finished (int channel)
417     {
418     SDL_UserEvent ev;
419    
420     ev.type = SDL_USEREVENT;
421     ev.code = 1;
422 root 1.74 ev.data1 = (void *)(long)channel;
423 root 1.71 ev.data2 = 0;
424    
425     SDL_PushEvent ((SDL_Event *)&ev);
426     }
427    
428 root 1.113 static unsigned int
429     minpot (unsigned int n)
430     {
431     if (!n)
432     return 0;
433    
434     --n;
435    
436     n |= n >> 1;
437     n |= n >> 2;
438     n |= n >> 4;
439     n |= n >> 8;
440     n |= n >> 16;
441    
442     return n + 1;
443     }
444    
445 root 1.235 static unsigned int
446     popcount (unsigned int n)
447     {
448     n -= (n >> 1) & 0x55555555U;
449     n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U);
450     n = ((n >> 4) + n) & 0x0f0f0f0fU;
451     n *= 0x01010101U;
452    
453     return n >> 24;
454     }
455    
456 root 1.167 /* SDL should provide this, really. */
457     #define SDLK_MODIFIER_MIN 300
458     #define SDLK_MODIFIER_MAX 314
459    
460 root 1.207 /******************************************************************************/
461    
462 root 1.209 static GV *draw_x_gv, *draw_y_gv, *draw_w_gv, *draw_h_gv;
463     static GV *hover_gv;
464    
465 root 1.207 static int
466     within_widget (SV *widget, NV x, NV y)
467     {
468     HV *self;
469     SV **svp;
470     NV wx, ww, wy, wh;
471    
472     if (!SvROK (widget))
473     return 0;
474    
475     self = (HV *)SvRV (widget);
476    
477     if (SvTYPE (self) != SVt_PVHV)
478     return 0;
479    
480     svp = hv_fetch (self, "y", 1, 0); wy = svp ? SvNV (*svp) : 0.;
481     if (y < wy)
482     return 0;
483    
484     svp = hv_fetch (self, "h", 1, 0); wh = svp ? SvNV (*svp) : 0.;
485     if (y >= wy + wh)
486     return 0;
487    
488     svp = hv_fetch (self, "x", 1, 0); wx = svp ? SvNV (*svp) : 0.;
489     if (x < wx)
490     return 0;
491    
492     svp = hv_fetch (self, "w", 1, 0); ww = svp ? SvNV (*svp) : 0.;
493     if (x >= wx + ww)
494     return 0;
495    
496     svp = hv_fetch (self, "can_events", sizeof ("can_events") - 1, 0);
497     if (!svp || !SvTRUE (*svp))
498     return 0;
499    
500     return 1;
501     }
502    
503 root 1.133 MODULE = CFPlus PACKAGE = CFPlus
504 root 1.1
505 root 1.11 PROTOTYPES: ENABLE
506    
507 root 1.5 BOOT:
508     {
509 root 1.133 HV *stash = gv_stashpv ("CFPlus", 1);
510 root 1.51 static const struct {
511     const char *name;
512     IV iv;
513     } *civ, const_iv[] = {
514     # define const_iv(name) { # name, (IV)name }
515 root 1.167 const_iv (SDLK_MODIFIER_MIN),
516     const_iv (SDLK_MODIFIER_MAX),
517    
518 root 1.51 const_iv (SDL_ACTIVEEVENT),
519     const_iv (SDL_KEYDOWN),
520     const_iv (SDL_KEYUP),
521     const_iv (SDL_MOUSEMOTION),
522     const_iv (SDL_MOUSEBUTTONDOWN),
523     const_iv (SDL_MOUSEBUTTONUP),
524     const_iv (SDL_JOYAXISMOTION),
525     const_iv (SDL_JOYBALLMOTION),
526     const_iv (SDL_JOYHATMOTION),
527     const_iv (SDL_JOYBUTTONDOWN),
528     const_iv (SDL_JOYBUTTONUP),
529     const_iv (SDL_QUIT),
530     const_iv (SDL_SYSWMEVENT),
531     const_iv (SDL_EVENT_RESERVEDA),
532     const_iv (SDL_EVENT_RESERVEDB),
533     const_iv (SDL_VIDEORESIZE),
534     const_iv (SDL_VIDEOEXPOSE),
535     const_iv (SDL_USEREVENT),
536 root 1.167
537     const_iv (SDL_APPINPUTFOCUS),
538     const_iv (SDL_APPMOUSEFOCUS),
539     const_iv (SDL_APPACTIVE),
540    
541 root 1.235 const_iv (SDLK_FIRST),
542     const_iv (SDLK_LAST),
543 root 1.51 const_iv (SDLK_KP0),
544     const_iv (SDLK_KP1),
545     const_iv (SDLK_KP2),
546     const_iv (SDLK_KP3),
547     const_iv (SDLK_KP4),
548     const_iv (SDLK_KP5),
549     const_iv (SDLK_KP6),
550     const_iv (SDLK_KP7),
551     const_iv (SDLK_KP8),
552     const_iv (SDLK_KP9),
553     const_iv (SDLK_KP_PERIOD),
554     const_iv (SDLK_KP_DIVIDE),
555     const_iv (SDLK_KP_MULTIPLY),
556     const_iv (SDLK_KP_MINUS),
557     const_iv (SDLK_KP_PLUS),
558     const_iv (SDLK_KP_ENTER),
559     const_iv (SDLK_KP_EQUALS),
560     const_iv (SDLK_UP),
561     const_iv (SDLK_DOWN),
562     const_iv (SDLK_RIGHT),
563     const_iv (SDLK_LEFT),
564     const_iv (SDLK_INSERT),
565     const_iv (SDLK_HOME),
566     const_iv (SDLK_END),
567     const_iv (SDLK_PAGEUP),
568     const_iv (SDLK_PAGEDOWN),
569     const_iv (SDLK_F1),
570     const_iv (SDLK_F2),
571     const_iv (SDLK_F3),
572     const_iv (SDLK_F4),
573     const_iv (SDLK_F5),
574     const_iv (SDLK_F6),
575     const_iv (SDLK_F7),
576     const_iv (SDLK_F8),
577     const_iv (SDLK_F9),
578     const_iv (SDLK_F10),
579     const_iv (SDLK_F11),
580     const_iv (SDLK_F12),
581     const_iv (SDLK_F13),
582     const_iv (SDLK_F14),
583     const_iv (SDLK_F15),
584     const_iv (SDLK_NUMLOCK),
585     const_iv (SDLK_CAPSLOCK),
586     const_iv (SDLK_SCROLLOCK),
587     const_iv (SDLK_RSHIFT),
588     const_iv (SDLK_LSHIFT),
589     const_iv (SDLK_RCTRL),
590     const_iv (SDLK_LCTRL),
591     const_iv (SDLK_RALT),
592     const_iv (SDLK_LALT),
593     const_iv (SDLK_RMETA),
594     const_iv (SDLK_LMETA),
595     const_iv (SDLK_LSUPER),
596     const_iv (SDLK_RSUPER),
597     const_iv (SDLK_MODE),
598     const_iv (SDLK_COMPOSE),
599     const_iv (SDLK_HELP),
600     const_iv (SDLK_PRINT),
601     const_iv (SDLK_SYSREQ),
602     const_iv (SDLK_BREAK),
603     const_iv (SDLK_MENU),
604     const_iv (SDLK_POWER),
605     const_iv (SDLK_EURO),
606     const_iv (SDLK_UNDO),
607 root 1.167
608 root 1.51 const_iv (KMOD_NONE),
609 root 1.167 const_iv (KMOD_SHIFT),
610 root 1.51 const_iv (KMOD_LSHIFT),
611     const_iv (KMOD_RSHIFT),
612 root 1.167 const_iv (KMOD_CTRL),
613 root 1.51 const_iv (KMOD_LCTRL),
614     const_iv (KMOD_RCTRL),
615 root 1.167 const_iv (KMOD_ALT),
616 root 1.51 const_iv (KMOD_LALT),
617     const_iv (KMOD_RALT),
618 root 1.167 const_iv (KMOD_META),
619 root 1.51 const_iv (KMOD_LMETA),
620     const_iv (KMOD_RMETA),
621     const_iv (KMOD_NUM),
622     const_iv (KMOD_CAPS),
623     const_iv (KMOD_MODE),
624 root 1.236
625     const_iv (MIX_DEFAULT_FORMAT),
626 root 1.51 # undef const_iv
627     };
628    
629     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
630     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
631 root 1.167
632     assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
633     assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
634 root 1.79 }
635 root 1.51
636 root 1.168 void
637     weaken (SV *rv)
638     PROTOTYPE: $
639     CODE:
640     sv_rvweaken (rv);
641    
642 root 1.129 int
643     in_destruct ()
644     CODE:
645     RETVAL = PL_main_cv == Nullcv;
646     OUTPUT:
647     RETVAL
648    
649 root 1.116 NV floor (NV x)
650    
651     NV ceil (NV x)
652    
653 root 1.235 IV minpot (UV n)
654    
655     IV popcount (UV n)
656    
657 root 1.79 void
658     pango_init ()
659     CODE:
660     {
661 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
662     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
663     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
664 root 1.5 }
665    
666 root 1.200 char *
667     SDL_GetError ()
668    
669 root 1.51 int
670 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
671 root 1.51
672     void
673     SDL_Quit ()
674    
675     void
676 root 1.200 SDL_ListModes (int rgb, int alpha)
677 root 1.51 PPCODE:
678     {
679     SDL_Rect **m;
680    
681 root 1.200 SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
682     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
683     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
684     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
685 root 1.51
686 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
687 root 1.200 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE , 0);
688 root 1.85
689 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE , 0);
690 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
691 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
692 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
693    
694     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
695 root 1.134 #if SDL_VERSION_ATLEAST(1,2,10)
696 root 1.131 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
697     SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
698 root 1.134 #endif
699 root 1.51
700     m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
701    
702     if (m && m != (SDL_Rect **)-1)
703     while (*m)
704     {
705 root 1.200 if ((*m)->w >= 640 && (*m)->h >= 480)
706     {
707     AV *av = newAV ();
708     av_push (av, newSViv ((*m)->w));
709     av_push (av, newSViv ((*m)->h));
710     av_push (av, newSViv (rgb));
711     av_push (av, newSViv (alpha));
712     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
713     }
714 root 1.51
715     ++m;
716     }
717     }
718    
719     int
720 root 1.200 SDL_SetVideoMode (int w, int h, int rgb, int alpha, int fullscreen)
721 root 1.51 CODE:
722 root 1.200 {
723     SDL_EnableUNICODE (1);
724     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
725    
726     SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
727     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
728     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
729     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
730    
731 root 1.51 RETVAL = !!SDL_SetVideoMode (
732     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
733     );
734 root 1.200
735 root 1.103 if (RETVAL)
736     {
737 root 1.188 av_clear (texture_av);
738    
739 root 1.229 SDL_WM_SetCaption ("Crossfire TRT Client " VERSION, "Crossfire TRT");
740 root 1.200 #define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
741     #include "glfunc.h"
742     #undef GL_FUNC
743 root 1.103 }
744 root 1.200 }
745 root 1.51 OUTPUT:
746     RETVAL
747    
748 root 1.53 void
749 root 1.54 SDL_GL_SwapBuffers ()
750    
751 root 1.94 char *
752     SDL_GetKeyName (int sym)
753    
754 root 1.198 int
755     SDL_GetAppState ()
756    
757 root 1.54 void
758 root 1.197 poll_events ()
759 root 1.53 PPCODE:
760     {
761     SDL_Event ev;
762    
763 root 1.197 SDL_PumpEvents ();
764     while (SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0)
765 root 1.53 {
766     HV *hv = newHV ();
767     hv_store (hv, "type", 4, newSViv (ev.type), 0);
768 root 1.70
769 root 1.53 switch (ev.type)
770     {
771     case SDL_KEYDOWN:
772     case SDL_KEYUP:
773     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
774     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
775     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
776 root 1.167 hv_store (hv, "cmod", 4, newSViv (SDL_GetModState ()), 0); /* current mode */
777 root 1.53 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
778     break;
779    
780     case SDL_ACTIVEEVENT:
781     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
782     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
783     break;
784    
785     case SDL_MOUSEMOTION:
786 root 1.196 {
787     int state = ev.motion.state;
788     int x = ev.motion.x;
789     int y = ev.motion.y;
790     int xrel = ev.motion.xrel;
791     int yrel = ev.motion.yrel;
792    
793     /* do simplistic event compression */
794     while (SDL_PeepEvents (&ev, 1, SDL_PEEKEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0
795     && state == ev.motion.state)
796     {
797     xrel += ev.motion.xrel;
798     yrel += ev.motion.yrel;
799     x = ev.motion.x;
800     y = ev.motion.y;
801     SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
802     }
803 root 1.93
804 root 1.196 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
805     hv_store (hv, "state", 5, newSViv (state), 0);
806     hv_store (hv, "x", 1, newSViv (x), 0);
807     hv_store (hv, "y", 1, newSViv (y), 0);
808     hv_store (hv, "xrel", 4, newSViv (xrel), 0);
809     hv_store (hv, "yrel", 4, newSViv (yrel), 0);
810     }
811 root 1.53 break;
812    
813     case SDL_MOUSEBUTTONDOWN:
814     case SDL_MOUSEBUTTONUP:
815 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
816 root 1.93
817 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
818     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
819     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
820     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
821 root 1.70 break;
822 root 1.72
823     case SDL_USEREVENT:
824     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
825     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
826     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
827     break;
828 root 1.53 }
829    
830 root 1.133 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
831 root 1.53 }
832     }
833 root 1.52
834     int
835 root 1.236 Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
836 root 1.56 POSTCALL:
837     Mix_HookMusicFinished (music_finished);
838 root 1.71 Mix_ChannelFinished (channel_finished);
839 root 1.52
840     void
841 root 1.236 Mix_QuerySpec ()
842     PPCODE:
843     {
844     int freq, channels;
845     Uint16 format;
846    
847     if (Mix_QuerySpec (&freq, &format, &channels))
848     {
849     EXTEND (SP, 3);
850     PUSHs (sv_2mortal (newSViv (freq)));
851     PUSHs (sv_2mortal (newSViv (format)));
852     PUSHs (sv_2mortal (newSViv (channels)));
853     }
854     }
855    
856     void
857 root 1.52 Mix_CloseAudio ()
858    
859     int
860     Mix_AllocateChannels (int numchans = -1)
861    
862 root 1.214 const char *
863     Mix_GetError ()
864    
865 root 1.10 void
866     lowdelay (int fd, int val = 1)
867     CODE:
868 root 1.179 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
869 root 1.10
870 root 1.5 void
871 root 1.157 win32_proxy_info ()
872     PPCODE:
873     {
874     #ifdef _WIN32
875     char buffer[2048];
876     DWORD buflen;
877    
878     EXTEND (SP, 3);
879    
880     buflen = sizeof (buffer);
881     if (InternetQueryOption (0, INTERNET_OPTION_PROXY, (void *)buffer, &buflen))
882     if (((INTERNET_PROXY_INFO *)buffer)->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
883     {
884     PUSHs (newSVpv (((INTERNET_PROXY_INFO *)buffer)->lpszProxy, 0));
885    
886     buflen = sizeof (buffer);
887     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_USERNAME, (void *)buffer, &buflen))
888     {
889     PUSHs (newSVpv (buffer, 0));
890    
891     buflen = sizeof (buffer);
892     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_PASSWORD, (void *)buffer, &buflen))
893     PUSHs (newSVpv (buffer, 0));
894     }
895     }
896     #endif
897     }
898    
899     void
900 root 1.13 add_font (char *file)
901     CODE:
902 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
903 root 1.13
904     void
905 root 1.23 load_image_inline (SV *image_)
906     ALIAS:
907     load_image_file = 1
908     PPCODE:
909     {
910     STRLEN image_len;
911     char *image = (char *)SvPVbyte (image_, image_len);
912     SDL_Surface *surface, *surface2;
913     SDL_PixelFormat fmt;
914     SDL_RWops *rw = ix
915 root 1.212 ? SDL_RWFromFile (image, "rb")
916 root 1.23 : SDL_RWFromConstMem (image, image_len);
917    
918     if (!rw)
919 root 1.41 croak ("load_image: %s", SDL_GetError ());
920 root 1.23
921     surface = IMG_Load_RW (rw, 1);
922     if (!surface)
923 root 1.41 croak ("load_image: %s", SDL_GetError ());
924 root 1.23
925     fmt.palette = NULL;
926     fmt.BitsPerPixel = 32;
927     fmt.BytesPerPixel = 4;
928 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
929 root 1.23 fmt.Rmask = 0x000000ff;
930     fmt.Gmask = 0x0000ff00;
931     fmt.Bmask = 0x00ff0000;
932     fmt.Amask = 0xff000000;
933 root 1.49 #else
934     fmt.Rmask = 0xff000000;
935     fmt.Gmask = 0x00ff0000;
936     fmt.Bmask = 0x0000ff00;
937     fmt.Amask = 0x000000ff;
938     #endif
939 root 1.23 fmt.Rloss = 0;
940     fmt.Gloss = 0;
941     fmt.Bloss = 0;
942     fmt.Aloss = 0;
943     fmt.Rshift = 0;
944     fmt.Gshift = 8;
945     fmt.Bshift = 16;
946     fmt.Ashift = 24;
947     fmt.colorkey = 0;
948     fmt.alpha = 0;
949    
950     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
951    
952 root 1.39 assert (surface2->pitch == surface2->w * 4);
953    
954 root 1.129 SDL_LockSurface (surface2);
955     EXTEND (SP, 6);
956 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
957     PUSHs (sv_2mortal (newSViv (surface2->h)));
958     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
959 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
960 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
961 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
962 root 1.129 SDL_UnlockSurface (surface2);
963 root 1.23
964     SDL_FreeSurface (surface);
965     SDL_FreeSurface (surface2);
966     }
967    
968 root 1.25 void
969 root 1.39 average (int x, int y, uint32_t *data)
970     PPCODE:
971     {
972     uint32_t r = 0, g = 0, b = 0, a = 0;
973    
974     x = y = x * y;
975    
976     while (x--)
977     {
978     uint32_t p = *data++;
979    
980     r += (p ) & 255;
981     g += (p >> 8) & 255;
982     b += (p >> 16) & 255;
983     a += (p >> 24) & 255;
984     }
985    
986     EXTEND (SP, 4);
987 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
988     PUSHs (sv_2mortal (newSViv (g / y)));
989     PUSHs (sv_2mortal (newSViv (b / y)));
990     PUSHs (sv_2mortal (newSViv (a / y)));
991 root 1.39 }
992    
993     void
994 root 1.66 error (char *message)
995     CODE:
996 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
997 root 1.66 #ifdef _WIN32
998 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
999 root 1.66 #endif
1000    
1001     void
1002 root 1.25 fatal (char *message)
1003     CODE:
1004 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
1005 root 1.50 #ifdef _WIN32
1006 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
1007 root 1.25 #endif
1008 root 1.112 _exit (1);
1009 root 1.111
1010     void
1011 root 1.158 _exit (int retval = 0)
1012 root 1.111 CODE:
1013 root 1.161 #ifdef WIN32
1014     ExitThread (retval); // unclean, please beam me up
1015     #else
1016 root 1.112 _exit (retval);
1017 root 1.161 #endif
1018 root 1.25
1019 root 1.193 void
1020     debug ()
1021     CODE:
1022     {
1023     #if DEBUG
1024     VALGRIND_DO_LEAK_CHECK;
1025     #endif
1026     }
1027    
1028 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
1029 root 1.61
1030 root 1.205 PROTOTYPES: DISABLE
1031    
1032 root 1.133 CFPlus::Font
1033 root 1.70 new_from_file (SV *class, char *path, int id = 0)
1034 root 1.61 CODE:
1035     {
1036     int count;
1037 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1038 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1039     FcPatternDestroy (pattern);
1040     }
1041     OUTPUT:
1042     RETVAL
1043    
1044     void
1045 root 1.133 DESTROY (CFPlus::Font self)
1046 root 1.61 CODE:
1047     pango_font_description_free (self);
1048    
1049     void
1050 root 1.133 make_default (CFPlus::Font self)
1051 root 1.205 PROTOTYPE: $
1052 root 1.61 CODE:
1053     default_font = self;
1054    
1055 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
1056 root 1.14
1057 root 1.205 PROTOTYPES: DISABLE
1058    
1059 root 1.124 void
1060 root 1.129 reset_glyph_cache ()
1061 root 1.205 PROTOTYPE:
1062 root 1.124 CODE:
1063     tc_clear ();
1064    
1065 root 1.133 CFPlus::Layout
1066 root 1.128 new (SV *class)
1067 root 1.14 CODE:
1068     New (0, RETVAL, 1, struct cf_layout);
1069 root 1.76
1070 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
1071 root 1.76 RETVAL->r = 1.;
1072     RETVAL->g = 1.;
1073     RETVAL->b = 1.;
1074     RETVAL->a = 1.;
1075     RETVAL->base_height = MIN_FONT_HEIGHT;
1076     RETVAL->font = 0;
1077 root 1.225 RETVAL->rc = rc_alloc ();
1078 root 1.76
1079 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1080 root 1.76 layout_update_font (RETVAL);
1081 root 1.14 OUTPUT:
1082     RETVAL
1083    
1084     void
1085 root 1.133 DESTROY (CFPlus::Layout self)
1086 root 1.14 CODE:
1087     g_object_unref (self->pl);
1088 root 1.225 rc_free (self->rc);
1089 root 1.14 Safefree (self);
1090 root 1.13
1091 root 1.8 void
1092 root 1.133 set_text (CFPlus::Layout self, SV *text_)
1093 root 1.35 CODE:
1094     {
1095     STRLEN textlen;
1096     char *text = SvPVutf8 (text_, textlen);
1097    
1098     pango_layout_set_text (self->pl, text, textlen);
1099     }
1100    
1101     void
1102 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
1103 root 1.14 CODE:
1104 root 1.5 {
1105     STRLEN textlen;
1106     char *text = SvPVutf8 (text_, textlen);
1107 root 1.14
1108     pango_layout_set_markup (self->pl, text, textlen);
1109     }
1110    
1111 root 1.121 void
1112 root 1.133 set_shapes (CFPlus::Layout self, ...)
1113 root 1.121 CODE:
1114     {
1115     PangoAttrList *attrs = 0;
1116     const char *text = pango_layout_get_text (self->pl);
1117     const char *pos = text;
1118 root 1.122 int arg = 4;
1119 root 1.121
1120     while (arg < items && (pos = strstr (pos, OBJ_STR)))
1121     {
1122 root 1.122 PangoRectangle inkrect, rect;
1123 root 1.121 PangoAttribute *attr;
1124    
1125 root 1.122 int x = SvIV (ST (arg - 3));
1126     int y = SvIV (ST (arg - 2));
1127 root 1.121 int w = SvIV (ST (arg - 1));
1128 root 1.122 int h = SvIV (ST (arg ));
1129 root 1.121
1130 root 1.122 inkrect.x = 0;
1131     inkrect.y = 0;
1132     inkrect.width = 0;
1133     inkrect.height = 0;
1134    
1135     rect.x = x * PANGO_SCALE;
1136     rect.y = y * PANGO_SCALE;
1137     rect.width = w * PANGO_SCALE;
1138 root 1.121 rect.height = h * PANGO_SCALE;
1139    
1140     if (!attrs)
1141     attrs = pango_layout_get_attributes (self->pl);
1142    
1143 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
1144 root 1.121 attr->start_index = pos - text;
1145     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
1146     pango_attr_list_insert (attrs, attr);
1147    
1148 root 1.122 arg += 4;
1149 root 1.121 pos += sizeof (OBJ_STR) - 1;
1150     }
1151    
1152     if (attrs)
1153     pango_layout_set_attributes (self->pl, attrs);
1154     }
1155    
1156     void
1157 root 1.133 get_shapes (CFPlus::Layout self)
1158 root 1.121 PPCODE:
1159     {
1160     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
1161    
1162     do
1163     {
1164     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
1165    
1166     if (run && shape_attr_p (run))
1167     {
1168     PangoRectangle extents;
1169     pango_layout_iter_get_run_extents (iter, 0, &extents);
1170    
1171 root 1.129 EXTEND (SP, 2);
1172 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
1173     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
1174     }
1175     }
1176     while (pango_layout_iter_next_run (iter));
1177    
1178     pango_layout_iter_free (iter);
1179     }
1180    
1181     int
1182 root 1.133 has_wrapped (CFPlus::Layout self)
1183 root 1.121 CODE:
1184     {
1185     int lines = 1;
1186     const char *text = pango_layout_get_text (self->pl);
1187    
1188     while (*text)
1189     lines += *text++ == '\n';
1190    
1191     RETVAL = lines < pango_layout_get_line_count (self->pl);
1192     }
1193     OUTPUT:
1194     RETVAL
1195    
1196 root 1.46 SV *
1197 root 1.133 get_text (CFPlus::Layout self)
1198 root 1.46 CODE:
1199 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
1200 root 1.107 sv_utf8_decode (RETVAL);
1201 root 1.46 OUTPUT:
1202     RETVAL
1203    
1204 root 1.14 void
1205 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
1206 root 1.76 CODE:
1207     self->r = r;
1208     self->g = g;
1209     self->b = b;
1210     self->a = a;
1211    
1212     void
1213 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
1214 root 1.61 CODE:
1215     if (self->font != font)
1216     {
1217     self->font = font;
1218     layout_update_font (self);
1219     }
1220    
1221     void
1222 root 1.133 set_height (CFPlus::Layout self, int base_height)
1223 root 1.16 CODE:
1224 root 1.61 if (self->base_height != base_height)
1225     {
1226     self->base_height = base_height;
1227     layout_update_font (self);
1228     }
1229 root 1.16
1230     void
1231 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
1232 root 1.14 CODE:
1233     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
1234    
1235     void
1236 root 1.133 set_indent (CFPlus::Layout self, int indent)
1237 root 1.84 CODE:
1238     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
1239    
1240     void
1241 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
1242 root 1.84 CODE:
1243     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
1244    
1245     void
1246 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
1247 root 1.84 CODE:
1248     pango_layout_set_ellipsize (self->pl,
1249     ellipsise == 1 ? PANGO_ELLIPSIZE_START
1250     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
1251     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
1252     : PANGO_ELLIPSIZE_NONE
1253     );
1254    
1255     void
1256 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
1257 root 1.84 CODE:
1258     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
1259    
1260     void
1261 root 1.133 size (CFPlus::Layout self)
1262 root 1.14 PPCODE:
1263     {
1264     int w, h;
1265    
1266     layout_get_pixel_size (self, &w, &h);
1267    
1268     EXTEND (SP, 2);
1269     PUSHs (sv_2mortal (newSViv (w)));
1270     PUSHs (sv_2mortal (newSViv (h)));
1271     }
1272    
1273 root 1.17 int
1274 root 1.133 descent (CFPlus::Layout self)
1275 root 1.122 CODE:
1276     {
1277     PangoRectangle rect;
1278     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1279     pango_layout_line_get_pixel_extents (line, 0, &rect);
1280     RETVAL = PANGO_DESCENT (rect);
1281     }
1282     OUTPUT:
1283     RETVAL
1284    
1285     int
1286 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1287 root 1.17 CODE:
1288     {
1289     int index, trailing;
1290     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1291 root 1.165 RETVAL = index + trailing;
1292 root 1.17 }
1293     OUTPUT:
1294     RETVAL
1295    
1296     void
1297 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1298 root 1.17 PPCODE:
1299     {
1300     PangoRectangle strong_pos;
1301     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1302 root 1.30
1303 root 1.17 EXTEND (SP, 3);
1304     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1305     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1306     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1307     }
1308    
1309 root 1.14 void
1310 root 1.165 index_to_line_x (CFPlus::Layout self, int index, int trailing = 0)
1311     PPCODE:
1312     {
1313     int line, x;
1314    
1315     pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x);
1316     /* pango bug: line is between 1..numlines, not 0..numlines-1 */
1317    
1318     EXTEND (SP, 2);
1319     PUSHs (sv_2mortal (newSViv (line - 1)));
1320     PUSHs (sv_2mortal (newSViv (x / PANGO_SCALE)));
1321     }
1322    
1323     void
1324     line_x_to_index (CFPlus::Layout self, int line, int x)
1325     PPCODE:
1326     {
1327     PangoLayoutLine *lp;
1328     int index, trailing;
1329    
1330     if (line < 0)
1331     XSRETURN_EMPTY;
1332    
1333     if (!(lp = pango_layout_get_line (self->pl, line)))
1334     XSRETURN_EMPTY; /* do better */
1335    
1336 root 1.166 pango_layout_line_x_to_index (lp, x * PANGO_SCALE, &index, &trailing);
1337 root 1.165
1338     EXTEND (SP, 2);
1339     if (GIMME_V == G_SCALAR)
1340     PUSHs (sv_2mortal (newSViv (index + trailing)));
1341     else
1342     {
1343     PUSHs (sv_2mortal (newSViv (index)));
1344     PUSHs (sv_2mortal (newSViv (trailing)));
1345     }
1346     }
1347    
1348     void
1349 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1350 root 1.225 CODE:
1351     rc_clear (self->rc);
1352 root 1.124 pango_opengl_render_layout_subpixel (
1353     self->pl,
1354 root 1.225 self->rc,
1355 root 1.124 x * PANGO_SCALE, y * PANGO_SCALE,
1356 root 1.135 self->r, self->g, self->b, self->a,
1357     flags
1358 root 1.124 );
1359 root 1.225 // we assume that context_change actually clears/frees stuff
1360     // and does not do any recomputation...
1361     pango_layout_context_changed (self->pl);
1362    
1363     void
1364     draw (CFPlus::Layout self)
1365     CODE:
1366     {
1367     glEnable (GL_TEXTURE_2D);
1368     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1369     glEnable (GL_BLEND);
1370     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1371     GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1372     glEnable (GL_ALPHA_TEST);
1373     glAlphaFunc (GL_GREATER, 7.f / 255.f);
1374    
1375     rc_draw (self->rc);
1376    
1377     glDisable (GL_ALPHA_TEST);
1378     glDisable (GL_BLEND);
1379     glDisable (GL_TEXTURE_2D);
1380     }
1381 root 1.11
1382 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1383 root 1.11
1384 root 1.205 PROTOTYPES: ENABLE
1385    
1386 root 1.11 void
1387 root 1.203 pad (SV *data_, int ow, int oh, int nw, int nh)
1388 root 1.113 CODE:
1389     {
1390 root 1.203 if ((nw != ow || nh != oh) && SvOK (data_))
1391 root 1.113 {
1392 root 1.203 STRLEN datalen;
1393     char *data = SvPVbyte (data_, datalen);
1394     int bpp = datalen / (ow * oh);
1395     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1396    
1397     SvPOK_only (result_);
1398     SvCUR_set (result_, nw * nh * bpp);
1399    
1400     memset (SvPVX (result_), 0, nw * nh * bpp);
1401     while (oh--)
1402     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1403 root 1.113
1404 root 1.203 sv_setsv (data_, result_);
1405 root 1.113 }
1406     }
1407    
1408     void
1409 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1410 root 1.12 PROTOTYPE: $$$;$$
1411 root 1.76 ALIAS:
1412     draw_quad_alpha = 1
1413     draw_quad_alpha_premultiplied = 2
1414 root 1.11 CODE:
1415     {
1416 root 1.12 HV *hv = (HV *)SvRV (self);
1417 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1418     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1419 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1420    
1421 root 1.219 if (name <= 0)
1422     XSRETURN_EMPTY;
1423    
1424 root 1.12 if (items < 5)
1425     {
1426 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1427     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1428 root 1.12 }
1429    
1430 root 1.76 if (ix)
1431     {
1432     glEnable (GL_BLEND);
1433 root 1.103
1434     if (ix == 2)
1435     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1436     else
1437     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1438 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1439 root 1.103
1440 root 1.86 glEnable (GL_ALPHA_TEST);
1441     glAlphaFunc (GL_GREATER, 0.01f);
1442 root 1.76 }
1443    
1444 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1445 root 1.76
1446 root 1.12 glBegin (GL_QUADS);
1447 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1448     glTexCoord2f (0, t); glVertex2f (x , y + h);
1449     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1450     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1451 root 1.12 glEnd ();
1452 root 1.76
1453     if (ix)
1454 root 1.86 {
1455     glDisable (GL_ALPHA_TEST);
1456     glDisable (GL_BLEND);
1457     }
1458 root 1.11 }
1459 root 1.28
1460 root 1.199 IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1461     CODE:
1462     {
1463     GLint width;
1464     glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1465     glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
1466     RETVAL = width > 0;
1467     }
1468     OUTPUT:
1469     RETVAL
1470    
1471 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1472 root 1.28
1473 root 1.205 PROTOTYPES: DISABLE
1474    
1475 root 1.133 CFPlus::Map
1476 root 1.164 new (SV *class)
1477 root 1.28 CODE:
1478     New (0, RETVAL, 1, struct map);
1479 root 1.42 RETVAL->x = 0;
1480     RETVAL->y = 0;
1481 root 1.164 RETVAL->w = 0;
1482     RETVAL->h = 0;
1483 root 1.42 RETVAL->ox = 0;
1484     RETVAL->oy = 0;
1485 root 1.174 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1486     RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1487 root 1.28 RETVAL->rows = 0;
1488     RETVAL->row = 0;
1489     OUTPUT:
1490     RETVAL
1491    
1492     void
1493 root 1.133 DESTROY (CFPlus::Map self)
1494 root 1.28 CODE:
1495     {
1496 root 1.30 map_clear (self);
1497 root 1.174 Safefree (self->face2tile);
1498 root 1.111 Safefree (self->tex);
1499 root 1.29 Safefree (self);
1500     }
1501    
1502     void
1503 root 1.164 resize (CFPlus::Map self, int map_width, int map_height)
1504     CODE:
1505     self->w = map_width;
1506     self->h = map_height;
1507    
1508     void
1509 root 1.133 clear (CFPlus::Map self)
1510 root 1.30 CODE:
1511     map_clear (self);
1512    
1513     void
1514 root 1.174 set_tileid (CFPlus::Map self, int face, int tile)
1515 root 1.29 CODE:
1516     {
1517 root 1.174 need_facenum (self, face); self->face2tile [face] = tile;
1518     need_texid (self, tile);
1519 root 1.42 }
1520    
1521     void
1522 root 1.176 set_smooth (CFPlus::Map self, int face, int smooth, int level)
1523     CODE:
1524     {
1525     tileid texid;
1526     maptex *tex;
1527    
1528     if (face < 0 || face >= self->faces)
1529     return;
1530    
1531     if (smooth < 0 || smooth >= self->faces)
1532     return;
1533    
1534     texid = self->face2tile [face];
1535    
1536     if (!texid)
1537     return;
1538    
1539     tex = self->tex + texid;
1540     tex->smoothtile = self->face2tile [smooth];
1541     tex->smoothlevel = level;
1542     }
1543    
1544     void
1545 root 1.133 set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1546 root 1.42 CODE:
1547     {
1548 root 1.174 need_texid (self, texid);
1549 root 1.42
1550 root 1.48 {
1551     maptex *tex = self->tex + texid;
1552 root 1.39
1553 root 1.48 tex->name = name;
1554     tex->w = w;
1555     tex->h = h;
1556     tex->s = s;
1557     tex->t = t;
1558     tex->r = r;
1559     tex->g = g;
1560     tex->b = b;
1561     tex->a = a;
1562     }
1563 root 1.95
1564     // somewhat hackish, but for textures that require it, it really
1565     // improves the look, and most others don't suffer.
1566     glBindTexture (GL_TEXTURE_2D, name);
1567 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1568     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1569     // use uglier nearest interpolation because linear suffers
1570     // from transparent color bleeding and ugly wrapping effects.
1571     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1572 root 1.29 }
1573    
1574 root 1.42 int
1575 root 1.133 ox (CFPlus::Map self)
1576 root 1.42 ALIAS:
1577     oy = 1
1578 root 1.101 x = 2
1579     y = 3
1580 root 1.102 w = 4
1581     h = 5
1582 root 1.42 CODE:
1583     switch (ix)
1584     {
1585     case 0: RETVAL = self->ox; break;
1586     case 1: RETVAL = self->oy; break;
1587 root 1.101 case 2: RETVAL = self->x; break;
1588     case 3: RETVAL = self->y; break;
1589 root 1.102 case 4: RETVAL = self->w; break;
1590     case 5: RETVAL = self->h; break;
1591 root 1.42 }
1592     OUTPUT:
1593     RETVAL
1594    
1595 root 1.29 void
1596 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1597 root 1.43 CODE:
1598     {
1599 root 1.44 if (dx > 0)
1600 root 1.154 map_blank (self, self->x, self->y, dx, self->h);
1601 root 1.44 else if (dx < 0)
1602 root 1.187 map_blank (self, self->x + self->w + dx, self->y, -dx, self->h);
1603 root 1.44
1604     if (dy > 0)
1605 root 1.154 map_blank (self, self->x, self->y, self->w, dy);
1606 root 1.44 else if (dy < 0)
1607 root 1.187 map_blank (self, self->x, self->y + self->h + dy, self->w, -dy);
1608 root 1.43
1609 root 1.44 self->ox += dx; self->x += dx;
1610     self->oy += dy; self->y += dy;
1611 root 1.43
1612     while (self->y < 0)
1613     {
1614     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1615    
1616     self->rows += MAP_EXTEND_Y;
1617     self->y += MAP_EXTEND_Y;
1618     }
1619 root 1.44 }
1620 root 1.43
1621 root 1.221 SV *
1622 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1623 root 1.44 CODE:
1624     {
1625 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1626     uint8_t *data_end = (uint8_t *)SvEND (data_);
1627 root 1.48 mapcell *cell;
1628 root 1.221 int x, y, z, flags;
1629     AV *missing = newAV ();
1630     RETVAL = newRV_noinc ((SV *)missing);
1631 root 1.43
1632 root 1.150 while (data < data_end - 1)
1633 root 1.29 {
1634 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1635 root 1.30
1636 root 1.120 x = self->x + ((flags >> 10) & 63);
1637     y = self->y + ((flags >> 4) & 63);
1638 root 1.29
1639 root 1.48 cell = map_get_cell (self, x, y);
1640 root 1.29
1641     if (flags & 15)
1642     {
1643 root 1.142 if (!cell->darkness)
1644 root 1.29 {
1645 root 1.154 memset (cell, 0, sizeof (*cell));
1646 root 1.142 cell->darkness = 256;
1647 root 1.29 }
1648 root 1.45
1649 root 1.142 //TODO: don't trust server data to be in-range(!)
1650    
1651 root 1.141 if (flags & 8)
1652     {
1653     if (extmap)
1654     {
1655     uint8_t ext, cmd;
1656    
1657     do
1658     {
1659     ext = *data++;
1660 root 1.144 cmd = ext & 0x3f;
1661 root 1.141
1662 root 1.147 if (cmd < 4)
1663 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1664 root 1.147 else if (cmd == 5) // health
1665     {
1666     cell->stat_width = 1;
1667     cell->stat_hp = *data++;
1668     }
1669     else if (cmd == 6) // monster width
1670     cell->stat_width = *data++ + 1;
1671 root 1.169 else if (cmd == 0x47)
1672 root 1.153 {
1673 root 1.182 if (*data == 4)
1674     ; // decode player count
1675 root 1.153
1676     data += *data + 1;
1677     }
1678     else if (cmd == 8) // cell flags
1679     cell->flags = *data++;
1680 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1681     data += *data + 1;
1682 root 1.147 else
1683     data++;
1684 root 1.141 }
1685 root 1.147 while (ext & 0x80);
1686 root 1.141 }
1687     else
1688 root 1.142 cell->darkness = *data++ + 1;
1689 root 1.141 }
1690 root 1.29
1691 root 1.221 for (z = 0; z <= 2; ++z)
1692     if (flags & (4 >> z))
1693     {
1694     faceid face = (data [0] << 8) + data [1]; data += 2;
1695     need_facenum (self, face);
1696     cell->tile [z] = self->face2tile [face];
1697 root 1.29
1698 root 1.221 if (cell->tile [z])
1699     {
1700     maptex *tex = self->tex + cell->tile [z];
1701     if (!tex->name)
1702     av_push (missing, newSViv (cell->tile [z]));
1703 root 1.29
1704 root 1.221 if (tex->smoothtile)
1705     {
1706     maptex *smooth = self->tex + tex->smoothtile;
1707     if (!smooth->name)
1708     av_push (missing, newSViv (tex->smoothtile));
1709     }
1710     }
1711     }
1712 root 1.29 }
1713     else
1714 root 1.155 cell->darkness = 0;
1715 root 1.29 }
1716 root 1.28 }
1717 root 1.221 OUTPUT:
1718     RETVAL
1719 root 1.28
1720 root 1.40 SV *
1721 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1722 root 1.40 CODE:
1723     {
1724 root 1.55 int x1, x;
1725     int y1, y;
1726 root 1.40 int z;
1727     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1728     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1729    
1730     SvPOK_only (map_sv);
1731     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1732    
1733 root 1.55 x0 += self->x; x1 = x0 + w;
1734     y0 += self->y; y1 = y0 + h;
1735 root 1.40
1736     for (y = y0; y < y1; y++)
1737     {
1738     maprow *row = 0 <= y && y < self->rows
1739     ? self->row + y
1740     : 0;
1741    
1742     for (x = x0; x < x1; x++)
1743     {
1744     int r = 32, g = 32, b = 32, a = 192;
1745    
1746     if (row && row->c0 <= x && x < row->c1)
1747     {
1748     mapcell *cell = row->col + (x - row->c0);
1749    
1750     for (z = 0; z <= 0; z++)
1751     {
1752 root 1.174 maptex tex = self->tex [cell->tile [z]];
1753     int a0 = 255 - tex.a;
1754     int a1 = tex.a;
1755    
1756     r = (r * a0 + tex.r * a1) / 255;
1757     g = (g * a0 + tex.g * a1) / 255;
1758     b = (b * a0 + tex.b * a1) / 255;
1759     a = (a * a0 + tex.a * a1) / 255;
1760 root 1.40 }
1761     }
1762    
1763     *map++ = (r )
1764     | (g << 8)
1765     | (b << 16)
1766     | (a << 24);
1767     }
1768     }
1769    
1770     RETVAL = map_sv;
1771     }
1772     OUTPUT:
1773     RETVAL
1774    
1775 root 1.221 void
1776 root 1.171 draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1777 root 1.116 CODE:
1778 root 1.30 {
1779 root 1.223 int x, y, z;
1780    
1781 root 1.176 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1782     uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1783 root 1.226 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k)
1784 root 1.176 smooth_key skey;
1785 root 1.223
1786     rc_t *rc = rc_alloc ();
1787     rc_key_t key;
1788     rc_array_t *arr;
1789 root 1.48
1790 root 1.176 // thats current max. sorry.
1791     if (sw > 255) sw = 255;
1792     if (sh > 255) sh = 255;
1793    
1794     // clear key, in case of extra padding
1795     memset (&skey, 0, sizeof (skey));
1796    
1797 root 1.223 memset (&key, 0, sizeof (key));
1798     key.r = 255;
1799     key.g = 255;
1800     key.b = 255;
1801     key.a = 255;
1802     key.mode = GL_QUADS;
1803     key.format = GL_T2F_V3F;
1804     key.texname = -1;
1805 root 1.30
1806 root 1.164 mx += self->x;
1807     my += self->y;
1808    
1809 root 1.176 // first pass: determine smooth_max
1810     // rather ugly, if you ask me
1811     // could also be stored inside mapcell and updated on change
1812     memset (smooth_max, 0, sizeof (smooth_max));
1813    
1814     for (y = 0; y < sh; y++)
1815     if (0 <= y + my && y + my < self->rows)
1816     {
1817     maprow *row = self->row + (y + my);
1818    
1819     for (x = 0; x < sw; x++)
1820     if (row->c0 <= x + mx && x + mx < row->c1)
1821     {
1822     mapcell *cell = row->col + (x + mx - row->c0);
1823    
1824 root 1.177 smooth_max[x + 1][y + 1] =
1825     MAX (self->tex [cell->tile [0]].smoothlevel,
1826     MAX (self->tex [cell->tile [1]].smoothlevel,
1827     self->tex [cell->tile [2]].smoothlevel));
1828 root 1.176 }
1829     }
1830    
1831 root 1.223 glEnable (GL_BLEND);
1832     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1833     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1834    
1835 root 1.176 for (z = 0; z <= 2; z++)
1836     {
1837 root 1.186 memset (smooth_level, 0, sizeof (smooth_level));
1838    
1839 root 1.176 for (y = 0; y < sh; y++)
1840     if (0 <= y + my && y + my < self->rows)
1841     {
1842     maprow *row = self->row + (y + my);
1843    
1844     for (x = 0; x < sw; x++)
1845     if (row->c0 <= x + mx && x + mx < row->c1)
1846     {
1847     mapcell *cell = row->col + (x + mx - row->c0);
1848     tileid tile = cell->tile [z];
1849    
1850     if (tile)
1851     {
1852     maptex tex = self->tex [tile];
1853 root 1.219 int px, py;
1854 root 1.176
1855 root 1.223 if (key.texname != tex.name)
1856 root 1.176 {
1857     if (!tex.name)
1858 root 1.221 tex = self->tex [2]; /* missing, replace by noface */
1859 root 1.176
1860 root 1.223 key.texname = tex.name;
1861     arr = rc_array (rc, &key);
1862 root 1.176 }
1863    
1864 root 1.219 px = (x + 1) * T - tex.w;
1865     py = (y + 1) * T - tex.h;
1866    
1867 root 1.223 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1868     rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
1869     rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
1870     rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
1871 root 1.176
1872     if (cell->flags && z == 2)
1873     {
1874 root 1.223 // overlays such as the speech bubble, probably more to come
1875 root 1.176 if (cell->flags & 1)
1876     {
1877     maptex tex = self->tex [1];
1878     int px = x * T + T * 2 / 32;
1879     int py = y * T - T * 6 / 32;
1880    
1881 root 1.223 if (tex.name)
1882     {
1883     if (key.texname != tex.name)
1884     {
1885     key.texname = tex.name;
1886     arr = rc_array (rc, &key);
1887     }
1888    
1889     rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1890     rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
1891     rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
1892     rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1893     }
1894 root 1.176 }
1895     }
1896    
1897     // update smooth hash
1898     if (tex.smoothtile)
1899     {
1900     skey.tile = tex.smoothtile;
1901     skey.level = tex.smoothlevel;
1902    
1903     smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
1904 root 1.30
1905 root 1.176 // add bits to current tile and all neighbours. skey.x|y is
1906     // shifted +1|+1 so we always stay positive.
1907 root 1.30
1908 root 1.180 // bits is ___n cccc CCCC bbbb
1909     // n do not draw borders&corners
1910     // c draw these corners, but...
1911     // C ... not these
1912     // b draw these borders
1913    
1914     // borders: 1 ┃· 2 ━━ 4 ·┃ 8 ··
1915     // ┃· ·· ·┃ ━━
1916    
1917     // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1918     // ·· ·· ·┏ ┓·
1919    
1920 root 1.176 // full tile
1921     skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
1922    
1923     // borders
1924 root 1.180 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091);
1925     skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032);
1926 root 1.176 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
1927     skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
1928    
1929     // corners
1930     skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1931     skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1932     skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1933     skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1934     }
1935     }
1936     }
1937     }
1938 root 1.174
1939 root 1.224 rc_draw (rc);
1940     rc_clear (rc);
1941    
1942 root 1.186 // go through all smoothlevels, lowest to highest, then draw.
1943     // this is basically counting sort
1944 root 1.176 {
1945 root 1.186 int w, b;
1946 root 1.30
1947 root 1.226 glEnable (GL_TEXTURE_2D);
1948     glBegin (GL_QUADS);
1949 root 1.186 for (w = 0; w < 256 / 32; ++w)
1950     {
1951     uint32_t smask = smooth_level [w];
1952     if (smask)
1953     for (b = 0; b < 32; ++b)
1954     if (smask & (((uint32_t)1) << b))
1955 root 1.176 {
1956 root 1.186 int level = (w << 5) | b;
1957     HE *he;
1958 root 1.153
1959 root 1.186 hv_iterinit (smooth);
1960     while ((he = hv_iternext (smooth)))
1961 root 1.153 {
1962 root 1.186 smooth_key *skey = (smooth_key *)HeKEY (he);
1963     IV bits = SvIVX (HeVAL (he));
1964 root 1.176
1965 root 1.186 if (!(bits & 0x1000)
1966     && skey->level == level
1967 root 1.191 && level > smooth_max [skey->x][skey->y])
1968 root 1.174 {
1969 root 1.186 maptex tex = self->tex [skey->tile];
1970     int px = (((int)skey->x) - 1) * T;
1971     int py = (((int)skey->y) - 1) * T;
1972     int border = bits & 15;
1973     int corner = (bits >> 8) & ~(bits >> 4) & 15;
1974     float dx = tex.s * .0625f; // 16 images/row
1975     float dy = tex.t * .5f ; // 2 images/column
1976    
1977 root 1.223 if (tex.name)
1978 root 1.186 {
1979 root 1.223 // this time avoiding texture state changes
1980     // save gobs of state changes.
1981     if (key.texname != tex.name)
1982     {
1983 root 1.226 glEnd ();
1984     glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
1985     glBegin (GL_QUADS);
1986 root 1.223 }
1987    
1988     if (border)
1989     {
1990     float ox = border * dx;
1991    
1992 root 1.226 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
1993     glTexCoord2f (ox , dy ); glVertex2i (px , py + T);
1994     glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T);
1995     glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py );
1996 root 1.223 }
1997    
1998     if (corner)
1999     {
2000     float ox = corner * dx;
2001    
2002 root 1.226 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2003     glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T);
2004     glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T);
2005     glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py );
2006 root 1.223 }
2007 root 1.186 }
2008 root 1.174 }
2009 root 1.153 }
2010     }
2011 root 1.186 }
2012 root 1.226
2013     glEnd ();
2014     glDisable (GL_TEXTURE_2D);
2015     key.texname = -1;
2016 root 1.176 }
2017    
2018 root 1.186 hv_clear (smooth);
2019     }
2020 root 1.30
2021 root 1.152 glDisable (GL_BLEND);
2022 root 1.223 rc_free (rc);
2023 root 1.143
2024 root 1.145 // top layer: overlays such as the health bar
2025 root 1.143 for (y = 0; y < sh; y++)
2026 root 1.164 if (0 <= y + my && y + my < self->rows)
2027 root 1.143 {
2028 root 1.164 maprow *row = self->row + (y + my);
2029 root 1.143
2030     for (x = 0; x < sw; x++)
2031 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
2032 root 1.143 {
2033 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
2034 root 1.143
2035 root 1.171 int px = x * T;
2036     int py = y * T;
2037 root 1.143
2038     if (cell->stat_hp)
2039     {
2040 root 1.171 int width = cell->stat_width * T;
2041 root 1.174 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width;
2042 root 1.143
2043 root 1.152 glColor3ub (0, 0, 0);
2044 root 1.151 glRectf (px + 1, py - thick - 2,
2045     px + width - 1, py);
2046 root 1.147
2047 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
2048 root 1.147 glRectf (px + 2,
2049 root 1.151 py - thick - 1,
2050     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
2051 root 1.143 }
2052     }
2053     }
2054 root 1.116 }
2055    
2056     void
2057 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
2058 root 1.117 CODE:
2059     {
2060     static float color[16][3] = {
2061 root 1.123 { 0.00F, 0.00F, 0.00F },
2062     { 1.00F, 1.00F, 1.00F },
2063     { 0.00F, 0.00F, 0.55F },
2064     { 1.00F, 0.00F, 0.00F },
2065    
2066     { 1.00F, 0.54F, 0.00F },
2067     { 0.11F, 0.56F, 1.00F },
2068     { 0.93F, 0.46F, 0.00F },
2069     { 0.18F, 0.54F, 0.34F },
2070    
2071     { 0.56F, 0.73F, 0.56F },
2072     { 0.80F, 0.80F, 0.80F },
2073     { 0.55F, 0.41F, 0.13F },
2074     { 0.99F, 0.77F, 0.26F },
2075    
2076     { 0.74F, 0.65F, 0.41F },
2077    
2078     { 0.00F, 1.00F, 1.00F },
2079     { 1.00F, 0.00F, 1.00F },
2080     { 1.00F, 1.00F, 0.00F },
2081 root 1.117 };
2082    
2083     int x, y;
2084    
2085     glEnable (GL_TEXTURE_2D);
2086     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2087     glEnable (GL_BLEND);
2088     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089     glBegin (GL_QUADS);
2090    
2091     for (y = 0; y < h; y++)
2092     for (x = 0; x < w; x++)
2093     {
2094     unsigned char m = data [x + y * w];
2095    
2096 root 1.118 if (m)
2097     {
2098     float *c = color [m & 15];
2099    
2100     float tx1 = m & 0x40 ? 0.5 : 0.;
2101     float tx2 = tx1 + 0.5;
2102    
2103     glColor4f (c[0], c[1], c[2], 0.75);
2104     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2105     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2106     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2107     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2108     }
2109 root 1.117 }
2110    
2111     glEnd ();
2112     glDisable (GL_BLEND);
2113     glDisable (GL_TEXTURE_2D);
2114     }
2115    
2116     void
2117 root 1.204 fow_texture (CFPlus::Map self, int mx, int my, int sw, int sh)
2118 root 1.116 PPCODE:
2119     {
2120     int x, y;
2121 root 1.204 int sw1 = sw + 2;
2122     int sh1 = sh + 2;
2123     int sh3 = sh * 3;
2124     int sw34 = (sw * 3 + 3) & ~3;
2125     uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2126     SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3));
2127     uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2128    
2129     SvPOK_only (darkness3_sv);
2130     SvCUR_set (darkness3_sv, sw34 * sh3);
2131 root 1.116
2132 root 1.204 mx += self->x - 1;
2133     my += self->y - 1;
2134 root 1.116
2135 root 1.204 memset (darkness1, 255, sw1 * sh1);
2136    
2137     for (y = 0; y < sh1; y++)
2138 root 1.164 if (0 <= y + my && y + my < self->rows)
2139 root 1.116 {
2140 root 1.164 maprow *row = self->row + (y + my);
2141 root 1.116
2142 root 1.204 for (x = 0; x < sw1; x++)
2143 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
2144 root 1.116 {
2145 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
2146 root 1.116
2147 root 1.204 darkness1 [y * sw1 + x] = cell->darkness
2148 root 1.143 ? 255 - (cell->darkness - 1)
2149 root 1.142 : 255 - FOW_DARKNESS;
2150 root 1.116 }
2151     }
2152 root 1.34
2153 root 1.204 for (y = 0; y < sh; ++y)
2154     for (x = 0; x < sw; ++x)
2155     {
2156     uint8_t d11 = darkness1 [(y ) * sw1 + x ];
2157     uint8_t d21 = darkness1 [(y ) * sw1 + x + 1];
2158     uint8_t d31 = darkness1 [(y ) * sw1 + x + 2];
2159     uint8_t d12 = darkness1 [(y + 1) * sw1 + x ];
2160     uint8_t d22 = darkness1 [(y + 1) * sw1 + x + 1];
2161     uint8_t d32 = darkness1 [(y + 1) * sw1 + x + 2];
2162     uint8_t d13 = darkness1 [(y + 2) * sw1 + x ];
2163     uint8_t d23 = darkness1 [(y + 2) * sw1 + x + 1];
2164     uint8_t d33 = darkness1 [(y + 2) * sw1 + x + 2];
2165    
2166     uint8_t r11 = (d11 + d21 + d12) / 3;
2167     uint8_t r21 = d21;
2168     uint8_t r31 = (d21 + d31 + d32) / 3;
2169    
2170     uint8_t r12 = d12;
2171     uint8_t r22 = d22;
2172     uint8_t r32 = d32;
2173    
2174     uint8_t r13 = (d13 + d23 + d12) / 3;
2175     uint8_t r23 = d23;
2176     uint8_t r33 = (d23 + d33 + d32) / 3;
2177    
2178     darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11);
2179     darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21);
2180     darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31);
2181     darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12);
2182     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22);
2183     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32);
2184     darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13);
2185     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23);
2186     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33);
2187     }
2188 root 1.201
2189 root 1.204 free (darkness1);
2190 root 1.201
2191 root 1.32 EXTEND (SP, 3);
2192 root 1.204 PUSHs (sv_2mortal (newSViv (sw34)));
2193     PUSHs (sv_2mortal (newSViv (sh3)));
2194     PUSHs (darkness3_sv);
2195 root 1.30 }
2196    
2197 root 1.42 SV *
2198 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
2199 root 1.42 CODE:
2200     {
2201     int x, y, x1, y1;
2202     SV *data_sv = newSV (w * h * 7 + 5);
2203     uint8_t *data = (uint8_t *)SvPVX (data_sv);
2204    
2205     *data++ = 0; /* version 0 format */
2206     *data++ = w >> 8; *data++ = w;
2207     *data++ = h >> 8; *data++ = h;
2208    
2209     // we need to do this 'cause we don't keep an absolute coord system for rows
2210 root 1.55 // TODO: treat rows as we treat columns
2211 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2212     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2213    
2214     x0 += self->x - self->ox;
2215     y0 += self->y - self->oy;
2216    
2217     x1 = x0 + w;
2218     y1 = y0 + h;
2219    
2220     for (y = y0; y < y1; y++)
2221     {
2222     maprow *row = 0 <= y && y < self->rows
2223     ? self->row + y
2224     : 0;
2225    
2226     for (x = x0; x < x1; x++)
2227     {
2228     if (row && row->c0 <= x && x < row->c1)
2229     {
2230     mapcell *cell = row->col + (x - row->c0);
2231     uint8_t flags = 0;
2232    
2233 root 1.174 if (cell->tile [0]) flags |= 1;
2234     if (cell->tile [1]) flags |= 2;
2235     if (cell->tile [2]) flags |= 4;
2236 root 1.42
2237     *data++ = flags;
2238    
2239     if (flags & 1)
2240     {
2241 root 1.174 tileid tile = cell->tile [0];
2242     *data++ = tile >> 8;
2243     *data++ = tile;
2244 root 1.42 }
2245    
2246     if (flags & 2)
2247     {
2248 root 1.174 tileid tile = cell->tile [1];
2249     *data++ = tile >> 8;
2250     *data++ = tile;
2251 root 1.42 }
2252    
2253     if (flags & 4)
2254     {
2255 root 1.174 tileid tile = cell->tile [2];
2256     *data++ = tile >> 8;
2257     *data++ = tile;
2258 root 1.42 }
2259     }
2260     else
2261     *data++ = 0;
2262     }
2263     }
2264    
2265     SvPOK_only (data_sv);
2266     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2267     RETVAL = data_sv;
2268     }
2269     OUTPUT:
2270     RETVAL
2271    
2272     void
2273 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
2274 root 1.42 PPCODE:
2275     {
2276     int x, y, z;
2277 root 1.48 int w, h;
2278 root 1.42 int x1, y1;
2279    
2280     if (*data++ != 0)
2281 root 1.227 XSRETURN_EMPTY; /* version mismatch */
2282 root 1.42
2283 root 1.48 w = *data++ << 8; w |= *data++;
2284     h = *data++ << 8; h |= *data++;
2285 root 1.42
2286     // we need to do this 'cause we don't keep an absolute coord system for rows
2287 root 1.55 // TODO: treat rows as we treat columns
2288 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2289     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2290    
2291     x0 += self->x - self->ox;
2292     y0 += self->y - self->oy;
2293    
2294     x1 = x0 + w;
2295     y1 = y0 + h;
2296    
2297     for (y = y0; y < y1; y++)
2298     {
2299     maprow *row = map_get_row (self, y);
2300    
2301     for (x = x0; x < x1; x++)
2302     {
2303     uint8_t flags = *data++;
2304    
2305     if (flags)
2306     {
2307     mapcell *cell = row_get_cell (row, x);
2308 root 1.174 tileid tile[3] = { 0, 0, 0 };
2309 root 1.42
2310 root 1.174 if (flags & 1) { tile[0] = *data++ << 8; tile[0] |= *data++; }
2311     if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2312     if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2313 root 1.42
2314 root 1.143 if (cell->darkness == 0)
2315 root 1.42 {
2316 root 1.142 cell->darkness = 0;
2317 root 1.42
2318     for (z = 0; z <= 2; z++)
2319     {
2320 root 1.174 tileid t = tile [z];
2321    
2322 root 1.175 if (t >= self->texs || (t && !self->tex [t].name))
2323 root 1.174 {
2324     XPUSHs (sv_2mortal (newSViv (t)));
2325     need_texid (self, t);
2326     }
2327 root 1.42
2328 root 1.174 cell->tile [z] = t;
2329 root 1.42 }
2330     }
2331     }
2332     }
2333     }
2334     }
2335    
2336 root 1.212 MODULE = CFPlus PACKAGE = CFPlus::RW
2337 root 1.205
2338 root 1.212 CFPlus::RW
2339 root 1.211 new (SV *class, SV *data_sv)
2340     CODE:
2341     {
2342     STRLEN datalen;
2343     char *data = SvPVbyte (data_sv, datalen);
2344    
2345 root 1.212 RETVAL = SDL_RWFromConstMem (data, datalen);
2346 root 1.211 }
2347     OUTPUT:
2348     RETVAL
2349    
2350 root 1.212 CFPlus::RW
2351     new_from_file (SV *class, const char *path, const char *mode = "rb")
2352     CODE:
2353     RETVAL = SDL_RWFromFile (path, mode);
2354     OUTPUT:
2355     RETVAL
2356    
2357 root 1.218 # fails on win32:
2358     # CFPlus.xs(2268) : error C2059: syntax error : '('
2359     #void
2360     #close (CFPlus::RW self)
2361     # CODE:
2362     # (self->(close)) (self);
2363 root 1.212
2364     MODULE = CFPlus PACKAGE = CFPlus::Channel
2365    
2366     PROTOTYPES: DISABLE
2367    
2368 root 1.215 CFPlus::Channel
2369     find ()
2370     CODE:
2371     {
2372     RETVAL = Mix_GroupAvailable (-1);
2373    
2374     if (RETVAL < 0)
2375     {
2376     RETVAL = Mix_GroupOldest (-1);
2377    
2378     if (RETVAL < 0)
2379     XSRETURN_UNDEF;
2380    
2381     Mix_HaltChannel (RETVAL);
2382     }
2383    
2384     Mix_UnregisterAllEffects (RETVAL);
2385     Mix_Volume (RETVAL, 128);
2386     }
2387     OUTPUT:
2388     RETVAL
2389    
2390 root 1.213 void
2391     halt (CFPlus::Channel self)
2392     CODE:
2393     Mix_HaltChannel (self);
2394    
2395     void
2396     expire (CFPlus::Channel self, int ticks = -1)
2397     CODE:
2398     Mix_ExpireChannel (self, ticks);
2399    
2400     void
2401     fade_out (CFPlus::Channel self, int ticks = -1)
2402     CODE:
2403     Mix_FadeOutChannel (self, ticks);
2404    
2405 root 1.212 int
2406     volume (CFPlus::Channel self, int volume)
2407     CODE:
2408 root 1.216 RETVAL = Mix_Volume (self, CLAMP (volume, 0, 128));
2409 root 1.212 OUTPUT:
2410     RETVAL
2411    
2412 root 1.213 void
2413 root 1.212 unregister_all_effects (CFPlus::Channel self)
2414     CODE:
2415 root 1.213 Mix_UnregisterAllEffects (self);
2416 root 1.212
2417 root 1.213 void
2418 root 1.212 set_panning (CFPlus::Channel self, int left, int right)
2419     CODE:
2420 root 1.216 left = CLAMP (left , 0, 255);
2421     right = CLAMP (right, 0, 255);
2422 root 1.213 Mix_SetPanning (self, left, right);
2423 root 1.212
2424 root 1.213 void
2425 root 1.212 set_distance (CFPlus::Channel self, int distance)
2426     CODE:
2427 root 1.216 Mix_SetDistance (self, CLAMP (distance, 0, 255));
2428 root 1.212
2429 root 1.213 void
2430 root 1.212 set_position (CFPlus::Channel self, int angle, int distance)
2431     CODE:
2432 root 1.220
2433     void
2434     set_position_r (CFPlus::Channel self, int dx, int dy, int maxdistance)
2435     CODE:
2436     {
2437     int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2438     int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI);
2439 root 1.216 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2440 root 1.220 }
2441 root 1.212
2442 root 1.213 void
2443 root 1.212 set_reverse_stereo (CFPlus::Channel self, int flip)
2444     CODE:
2445 root 1.213 Mix_SetReverseStereo (self, flip);
2446 root 1.212
2447     MODULE = CFPlus PACKAGE = CFPlus::MixChunk
2448    
2449     PROTOTYPES: DISABLE
2450    
2451 root 1.211 CFPlus::MixChunk
2452 root 1.212 new (SV *class, CFPlus::RW rwops)
2453 root 1.52 CODE:
2454 root 1.212 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2455 root 1.52 OUTPUT:
2456     RETVAL
2457    
2458     void
2459 root 1.133 DESTROY (CFPlus::MixChunk self)
2460 root 1.52 CODE:
2461     Mix_FreeChunk (self);
2462    
2463     int
2464 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
2465 root 1.52 CODE:
2466 root 1.216 if (items > 1)
2467     volume = CLAMP (volume, 0, 128);
2468 root 1.52 RETVAL = Mix_VolumeChunk (self, volume);
2469     OUTPUT:
2470     RETVAL
2471    
2472 root 1.212 CFPlus::Channel
2473 root 1.215 play (CFPlus::MixChunk self, CFPlus::Channel channel = -1, int loops = 0, int ticks = -1)
2474 root 1.52 CODE:
2475 root 1.215 {
2476 root 1.52 RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
2477 root 1.215
2478     if (RETVAL < 0)
2479     XSRETURN_UNDEF;
2480    
2481     if (channel < 0)
2482     {
2483     Mix_UnregisterAllEffects (RETVAL);
2484     Mix_Volume (RETVAL, 128);
2485     }
2486     }
2487 root 1.52 OUTPUT:
2488     RETVAL
2489    
2490 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
2491 root 1.52
2492     int
2493     volume (int volume = -1)
2494 root 1.205 PROTOTYPE: ;$
2495 root 1.52 CODE:
2496 root 1.216 if (items > 0)
2497     volume = CLAMP (volume, 0, 128);
2498 root 1.52 RETVAL = Mix_VolumeMusic (volume);
2499     OUTPUT:
2500     RETVAL
2501    
2502 root 1.213 void
2503 root 1.194 fade_out (int ms)
2504     CODE:
2505 root 1.213 Mix_FadeOutMusic (ms);
2506 root 1.194
2507 root 1.212 void
2508     halt ()
2509     CODE:
2510     Mix_HaltMusic ();
2511    
2512 root 1.133 CFPlus::MixMusic
2513 root 1.212 new (SV *class, CFPlus::RW rwops)
2514 root 1.52 CODE:
2515 root 1.212 RETVAL = Mix_LoadMUS_RW (rwops);
2516 root 1.52 OUTPUT:
2517     RETVAL
2518    
2519     void
2520 root 1.133 DESTROY (CFPlus::MixMusic self)
2521 root 1.52 CODE:
2522     Mix_FreeMusic (self);
2523    
2524     int
2525 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
2526 root 1.52 CODE:
2527     RETVAL = Mix_PlayMusic (self, loops);
2528     OUTPUT:
2529     RETVAL
2530    
2531 root 1.213 void
2532 root 1.195 fade_in_pos (CFPlus::MixMusic self, int loops, int ms, double position)
2533     CODE:
2534 root 1.213 Mix_FadeInMusicPos (self, loops, ms, position);
2535 root 1.195
2536 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
2537 root 1.54
2538 root 1.205 PROTOTYPES: ENABLE
2539    
2540 root 1.54 BOOT:
2541     {
2542 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
2543 root 1.54 static const struct {
2544     const char *name;
2545     IV iv;
2546     } *civ, const_iv[] = {
2547     # define const_iv(name) { # name, (IV)name }
2548 root 1.199 const_iv (GL_VENDOR),
2549     const_iv (GL_VERSION),
2550     const_iv (GL_EXTENSIONS),
2551 root 1.54 const_iv (GL_COLOR_MATERIAL),
2552     const_iv (GL_SMOOTH),
2553     const_iv (GL_FLAT),
2554 root 1.69 const_iv (GL_DITHER),
2555 root 1.54 const_iv (GL_BLEND),
2556 root 1.89 const_iv (GL_CULL_FACE),
2557 root 1.69 const_iv (GL_SCISSOR_TEST),
2558 root 1.89 const_iv (GL_DEPTH_TEST),
2559     const_iv (GL_ALPHA_TEST),
2560     const_iv (GL_NORMALIZE),
2561     const_iv (GL_RESCALE_NORMAL),
2562 root 1.119 const_iv (GL_FRONT),
2563     const_iv (GL_BACK),
2564 root 1.206 const_iv (GL_AUX0),
2565 root 1.54 const_iv (GL_AND),
2566 root 1.67 const_iv (GL_ONE),
2567     const_iv (GL_ZERO),
2568 root 1.54 const_iv (GL_SRC_ALPHA),
2569 root 1.104 const_iv (GL_DST_ALPHA),
2570 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2571 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
2572 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
2573 root 1.54 const_iv (GL_RGB),
2574     const_iv (GL_RGBA),
2575 root 1.115 const_iv (GL_RGBA4),
2576     const_iv (GL_RGBA8),
2577     const_iv (GL_RGB5_A1),
2578 root 1.54 const_iv (GL_UNSIGNED_BYTE),
2579 root 1.89 const_iv (GL_UNSIGNED_SHORT),
2580     const_iv (GL_UNSIGNED_INT),
2581 root 1.54 const_iv (GL_ALPHA),
2582 root 1.86 const_iv (GL_INTENSITY),
2583 root 1.76 const_iv (GL_LUMINANCE),
2584 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
2585 root 1.54 const_iv (GL_FLOAT),
2586     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
2587 root 1.230 const_iv (GL_COMPRESSED_ALPHA_ARB),
2588     const_iv (GL_COMPRESSED_LUMINANCE_ARB),
2589     const_iv (GL_COMPRESSED_LUMINANCE_ALPHA_ARB),
2590     const_iv (GL_COMPRESSED_INTENSITY_ARB),
2591     const_iv (GL_COMPRESSED_RGB_ARB),
2592     const_iv (GL_COMPRESSED_RGBA_ARB),
2593 root 1.54 const_iv (GL_COMPILE),
2594 root 1.199 const_iv (GL_PROXY_TEXTURE_1D),
2595     const_iv (GL_PROXY_TEXTURE_2D),
2596 root 1.54 const_iv (GL_TEXTURE_1D),
2597     const_iv (GL_TEXTURE_2D),
2598     const_iv (GL_TEXTURE_ENV),
2599     const_iv (GL_TEXTURE_MAG_FILTER),
2600     const_iv (GL_TEXTURE_MIN_FILTER),
2601     const_iv (GL_TEXTURE_ENV_MODE),
2602     const_iv (GL_TEXTURE_WRAP_S),
2603     const_iv (GL_TEXTURE_WRAP_T),
2604 root 1.98 const_iv (GL_REPEAT),
2605 root 1.54 const_iv (GL_CLAMP),
2606 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
2607 root 1.54 const_iv (GL_NEAREST),
2608     const_iv (GL_LINEAR),
2609 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
2610     const_iv (GL_LINEAR_MIPMAP_NEAREST),
2611     const_iv (GL_NEAREST_MIPMAP_LINEAR),
2612     const_iv (GL_LINEAR_MIPMAP_LINEAR),
2613     const_iv (GL_GENERATE_MIPMAP),
2614 root 1.54 const_iv (GL_MODULATE),
2615 root 1.69 const_iv (GL_DECAL),
2616 root 1.54 const_iv (GL_REPLACE),
2617 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
2618 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
2619     const_iv (GL_PROJECTION),
2620     const_iv (GL_MODELVIEW),
2621     const_iv (GL_COLOR_LOGIC_OP),
2622 root 1.69 const_iv (GL_SEPARABLE_2D),
2623 root 1.54 const_iv (GL_CONVOLUTION_2D),
2624     const_iv (GL_CONVOLUTION_BORDER_MODE),
2625     const_iv (GL_CONSTANT_BORDER),
2626 root 1.208 const_iv (GL_POINTS),
2627 root 1.54 const_iv (GL_LINES),
2628 root 1.138 const_iv (GL_LINE_STRIP),
2629 root 1.89 const_iv (GL_LINE_LOOP),
2630 root 1.54 const_iv (GL_QUADS),
2631 root 1.89 const_iv (GL_QUAD_STRIP),
2632     const_iv (GL_TRIANGLES),
2633     const_iv (GL_TRIANGLE_STRIP),
2634     const_iv (GL_TRIANGLE_FAN),
2635 root 1.208 const_iv (GL_POLYGON),
2636 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
2637 root 1.206 const_iv (GL_POINT_SMOOTH_HINT),
2638     const_iv (GL_LINE_SMOOTH_HINT),
2639     const_iv (GL_POLYGON_SMOOTH_HINT),
2640     const_iv (GL_GENERATE_MIPMAP_HINT),
2641 root 1.232 const_iv (GL_TEXTURE_COMPRESSION_HINT),
2642 root 1.54 const_iv (GL_FASTEST),
2643 root 1.206 const_iv (GL_DONT_CARE),
2644     const_iv (GL_NICEST),
2645 root 1.89 const_iv (GL_V2F),
2646     const_iv (GL_V3F),
2647     const_iv (GL_T2F_V3F),
2648     const_iv (GL_T2F_N3F_V3F),
2649 root 1.54 # undef const_iv
2650     };
2651    
2652     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
2653     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
2654 root 1.188
2655     texture_av = newAV ();
2656     AvREAL_off (texture_av);
2657 root 1.54 }
2658    
2659 root 1.231 void
2660     disable_GL_EXT_blend_func_separate ()
2661     CODE:
2662     gl.BlendFuncSeparate = 0;
2663     gl.BlendFuncSeparateEXT = 0;
2664    
2665 root 1.97 char *
2666     gl_vendor ()
2667     CODE:
2668     RETVAL = (char *)glGetString (GL_VENDOR);
2669     OUTPUT:
2670     RETVAL
2671    
2672     char *
2673     gl_version ()
2674     CODE:
2675     RETVAL = (char *)glGetString (GL_VERSION);
2676     OUTPUT:
2677     RETVAL
2678    
2679     char *
2680     gl_extensions ()
2681     CODE:
2682     RETVAL = (char *)glGetString (GL_EXTENSIONS);
2683     OUTPUT:
2684     RETVAL
2685    
2686 root 1.201 const char *glGetString (GLenum pname)
2687 root 1.199
2688     GLint glGetInteger (GLenum pname)
2689     CODE:
2690     glGetIntegerv (pname, &RETVAL);
2691     OUTPUT:
2692     RETVAL
2693    
2694     GLdouble glGetDouble (GLenum pname)
2695     CODE:
2696     glGetDoublev (pname, &RETVAL);
2697     OUTPUT:
2698     RETVAL
2699    
2700 root 1.54 int glGetError ()
2701    
2702 root 1.114 void glFinish ()
2703    
2704 root 1.54 void glClear (int mask)
2705    
2706     void glClearColor (float r, float g, float b, float a = 1.0)
2707     PROTOTYPE: @
2708    
2709     void glEnable (int cap)
2710    
2711     void glDisable (int cap)
2712    
2713     void glShadeModel (int mode)
2714    
2715     void glHint (int target, int mode)
2716    
2717     void glBlendFunc (int sfactor, int dfactor)
2718    
2719 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2720     CODE:
2721     gl_BlendFuncSeparate (sa, da, saa, daa);
2722    
2723 root 1.89 void glDepthMask (int flag)
2724    
2725 root 1.54 void glLogicOp (int opcode)
2726    
2727 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
2728    
2729 root 1.54 void glMatrixMode (int mode)
2730    
2731     void glPushMatrix ()
2732    
2733     void glPopMatrix ()
2734    
2735     void glLoadIdentity ()
2736    
2737 root 1.119 void glDrawBuffer (int buffer)
2738    
2739     void glReadBuffer (int buffer)
2740    
2741 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
2742     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2743    
2744     # near_ and far_ are due to microsofts buggy "c" compiler
2745 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2746 root 1.54
2747 root 1.208 PROTOTYPES: DISABLE
2748    
2749 root 1.54 void glViewport (int x, int y, int width, int height)
2750    
2751 root 1.69 void glScissor (int x, int y, int width, int height)
2752    
2753 root 1.54 void glTranslate (float x, float y, float z = 0.)
2754     CODE:
2755     glTranslatef (x, y, z);
2756    
2757 root 1.62 void glScale (float x, float y, float z = 1.)
2758 root 1.54 CODE:
2759     glScalef (x, y, z);
2760    
2761     void glRotate (float angle, float x, float y, float z)
2762     CODE:
2763     glRotatef (angle, x, y, z);
2764    
2765     void glColor (float r, float g, float b, float a = 1.0)
2766 root 1.103 ALIAS:
2767     glColor_premultiply = 1
2768 root 1.54 CODE:
2769 root 1.103 if (ix)
2770     {
2771     r *= a;
2772     g *= a;
2773     b *= a;
2774     }
2775 root 1.90 // microsoft visual "c" rounds instead of truncating...
2776 root 1.130 glColor4f (r, g, b, a);
2777 root 1.54
2778 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2779     CODE:
2780     glRasterPos3f (0, 0, z);
2781     glBitmap (0, 0, 0, 0, x, y, 0);
2782    
2783 root 1.54 void glVertex (float x, float y, float z = 0.)
2784     CODE:
2785     glVertex3f (x, y, z);
2786    
2787     void glTexCoord (float s, float t)
2788     CODE:
2789     glTexCoord2f (s, t);
2790    
2791 root 1.210 void glRect (float x1, float y1, float x2, float y2)
2792     CODE:
2793     glRectf (x1, y1, x2, y2);
2794    
2795 root 1.233 void glRect_lineloop (float x1, float y1, float x2, float y2)
2796     CODE:
2797     glBegin (GL_LINE_LOOP);
2798     glVertex2f (x1, y1);
2799     glVertex2f (x2, y1);
2800     glVertex2f (x2, y2);
2801     glVertex2f (x1, y2);
2802     glEnd ();
2803    
2804 root 1.208 PROTOTYPES: ENABLE
2805    
2806     void glBegin (int mode)
2807    
2808     void glEnd ()
2809    
2810     void glPointSize (GLfloat size)
2811    
2812     void glLineWidth (GLfloat width)
2813    
2814     void glInterleavedArrays (int format, int stride, char *data)
2815    
2816     void glDrawElements (int mode, int count, int type, char *indices)
2817    
2818     # 1.2 void glDrawRangeElements (int mode, int start, int end
2819    
2820 root 1.54 void glTexEnv (int target, int pname, float param)
2821     CODE:
2822     glTexEnvf (target, pname, param);
2823    
2824     void glTexParameter (int target, int pname, float param)
2825     CODE:
2826     glTexParameterf (target, pname, param);
2827    
2828     void glBindTexture (int target, int name)
2829    
2830     void glConvolutionParameter (int target, int pname, float params)
2831     CODE:
2832 root 1.103 if (gl.ConvolutionParameterf)
2833     gl.ConvolutionParameterf (target, pname, params);
2834 root 1.54
2835     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2836 root 1.64 CODE:
2837 root 1.103 if (gl.ConvolutionFilter2D)
2838     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2839 root 1.54
2840 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2841     CODE:
2842 root 1.103 if (gl.SeparableFilter2D)
2843     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2844 root 1.69
2845 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2846    
2847     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2848    
2849 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2850 root 1.68
2851 root 1.199 void glPixelZoom (float x, float y)
2852    
2853 root 1.68 void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2854    
2855 root 1.54 int glGenTexture ()
2856     CODE:
2857 root 1.192 RETVAL = gen_texture ();
2858 root 1.54 OUTPUT:
2859     RETVAL
2860    
2861     void glDeleteTexture (int name)
2862     CODE:
2863 root 1.192 del_texture (name);
2864    
2865 root 1.54 int glGenList ()
2866     CODE:
2867     RETVAL = glGenLists (1);
2868     OUTPUT:
2869     RETVAL
2870    
2871     void glDeleteList (int list)
2872     CODE:
2873     glDeleteLists (list, 1);
2874    
2875     void glNewList (int list, int mode = GL_COMPILE)
2876    
2877     void glEndList ()
2878    
2879     void glCallList (int list)
2880    
2881 root 1.207 MODULE = CFPlus PACKAGE = CFPlus::UI::Base
2882    
2883     PROTOTYPES: DISABLE
2884    
2885     void
2886 root 1.209 find_widget (SV *self, NV x, NV y)
2887 root 1.207 PPCODE:
2888     {
2889 root 1.209 if (within_widget (self, x, y))
2890     XPUSHs (self);
2891     }
2892    
2893     BOOT:
2894     {
2895     hover_gv = gv_fetchpv ("CFPlus::UI::HOVER", 1, SVt_NV);
2896    
2897     draw_x_gv = gv_fetchpv ("CFPlus::UI::Base::draw_x", 1, SVt_NV);
2898     draw_y_gv = gv_fetchpv ("CFPlus::UI::Base::draw_y", 1, SVt_NV);
2899     draw_w_gv = gv_fetchpv ("CFPlus::UI::Base::draw_w", 1, SVt_NV);
2900     draw_h_gv = gv_fetchpv ("CFPlus::UI::Base::draw_h", 1, SVt_NV);
2901     }
2902    
2903     void
2904     draw (SV *self)
2905     CODE:
2906     {
2907     HV *hv;
2908     SV **svp;
2909     NV x, y, w, h;
2910     SV *draw_x_sv = GvSV (draw_x_gv);
2911     SV *draw_y_sv = GvSV (draw_y_gv);
2912     SV *draw_w_sv = GvSV (draw_w_gv);
2913     SV *draw_h_sv = GvSV (draw_h_gv);
2914 root 1.228 double draw_x, draw_y;
2915 root 1.209
2916     if (!SvROK (self))
2917     croak ("CFPlus::Base::draw: %s not a reference", SvPV_nolen (self));
2918    
2919     hv = (HV *)SvRV (self);
2920    
2921     if (SvTYPE (hv) != SVt_PVHV)
2922     croak ("CFPlus::Base::draw: %s not a hashref", SvPV_nolen (self));
2923    
2924     svp = hv_fetch (hv, "w", 1, 0); w = svp ? SvNV (*svp) : 0.;
2925     svp = hv_fetch (hv, "h", 1, 0); h = svp ? SvNV (*svp) : 0.;
2926    
2927     if (!h || !w)
2928     XSRETURN_EMPTY;
2929    
2930     svp = hv_fetch (hv, "x", 1, 0); x = svp ? SvNV (*svp) : 0.;
2931     svp = hv_fetch (hv, "y", 1, 0); y = svp ? SvNV (*svp) : 0.;
2932    
2933     draw_x = SvNV (draw_x_sv) + x;
2934     draw_y = SvNV (draw_y_sv) + y;
2935    
2936     if (draw_x + w < 0 || draw_x >= SvNV (draw_w_sv)
2937     || draw_y + h < 0 || draw_y >= SvNV (draw_h_sv))
2938     XSRETURN_EMPTY;
2939    
2940     sv_setnv (draw_x_sv, draw_x);
2941     sv_setnv (draw_y_sv, draw_y);
2942    
2943     glPushMatrix ();
2944     glTranslated (x, y, 0);
2945    
2946     if (SvROK (GvSV (hover_gv)) && SvRV (GvSV (hover_gv)) == (SV *)hv)
2947     {
2948     svp = hv_fetch (hv, "can_hover", sizeof ("can_hover") - 1, 0);
2949    
2950     if (svp && SvTRUE (*svp))
2951     {
2952 root 1.228 glColor4f (1.0f * 0.2f, 0.8f * 0.2f, 0.5f * 0.2f, 0.2f);
2953 root 1.209 glEnable (GL_BLEND);
2954     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2955     glBegin (GL_QUADS);
2956     glVertex2f (0, 0);
2957     glVertex2f (w, 0);
2958     glVertex2f (w, h);
2959     glVertex2f (0, h);
2960     glEnd ();
2961     glDisable (GL_BLEND);
2962     }
2963     }
2964     #if 0
2965 root 1.234 // draw borders, for debugging
2966     glPushMatrix ();
2967     glColor4f (1., 1., 0., 1.);
2968     glTranslatef (.5, .5, 0.);
2969     glBegin (GL_LINE_LOOP);
2970     glVertex2f (0 , 0);
2971     glVertex2f (w - 1, 0);
2972     glVertex2f (w - 1, h - 1);
2973     glVertex2f (0 , h - 1);
2974     glEnd ();
2975     glPopMatrix ();
2976 root 1.209 #endif
2977     PUSHMARK (SP);
2978     XPUSHs (self);
2979     PUTBACK;
2980     call_method ("_draw", G_VOID | G_DISCARD);
2981     SPAGAIN;
2982    
2983     glPopMatrix ();
2984    
2985     draw_x = draw_x - x; sv_setnv (draw_x_sv, draw_x);
2986     draw_y = draw_y - y; sv_setnv (draw_y_sv, draw_y);
2987 root 1.207 }
2988