ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.254
Committed: Sun Jan 6 18:12:20 2008 UTC (16 years, 4 months ago) by root
Branch: MAIN
Changes since 1.253: +7 -3 lines
Log Message:
port backt o old pango

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