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