ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.252
Committed: Fri Dec 28 17:30:33 2007 UTC (16 years, 4 months ago) by root
Branch: MAIN
Changes since 1.251: +1 -1 lines
Log Message:
*** empty log message ***

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