ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.233
Committed: Tue Aug 21 02:39:17 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.232: +9 -0 lines
Log Message:
- new progress widget
- new experience progress widget
- took advantage of experience info and displayed "next level" info.
  needs tooltips with details..

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