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