ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
(Generate patch)

Comparing deliantra/Deliantra-Client/Client.xs (file contents):
Revision 1.283 by root, Thu Dec 11 00:11:58 2008 UTC vs.
Revision 1.327 by root, Sun Nov 18 12:01:50 2018 UTC

15 15
16#include "EXTERN.h" 16#include "EXTERN.h"
17#include "perl.h" 17#include "perl.h"
18#include "XSUB.h" 18#include "XSUB.h"
19 19
20#include "flat_hash_map.hpp"
21
20#ifdef _WIN32 22#ifdef _WIN32
21# undef pipe 23# undef pipe
22// microsoft vs. C 24// microsoft vs. C
23# define sqrtf(x) sqrt(x) 25# define sqrtf(x) sqrt(x)
24# define roundf(x) (int)(x)
25# define atan2f(x,y) atan2(x,y) 26# define atan2f(x,y) atan2(x,y)
26# define M_PI 3.14159265f 27# define M_PI 3.14159265f
27#endif 28#endif
28 29
29#include <assert.h> 30#include <cassert>
30#include <math.h> 31#include <cmath>
31#include <string.h> 32#include <cstring>
32#include <stdio.h> 33#include <cstdio>
33#include <stdlib.h> 34#include <cstdlib>
35
36#include <utility>
37#include <bitset>
34 38
35#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW 39#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
36 40
37#include <SDL.h> 41#include <SDL.h>
38#include <SDL_thread.h> 42#include <SDL_thread.h>
42#include <SDL_opengl.h> 46#include <SDL_opengl.h>
43 47
44/* work around os x broken headers */ 48/* work around os x broken headers */
45#ifdef __MACOSX__ 49#ifdef __MACOSX__
46typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 50typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
51typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
52typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
47#endif 53#endif
48 54
49#define PANGO_ENABLE_BACKEND 55#define PANGO_ENABLE_BACKEND
50#define G_DISABLE_CAST_CHECKS 56#define G_DISABLE_CAST_CHECKS
51 57
52#include <glib/gmacros.h> 58#include <glib.h>
53 59
54#include <pango/pango.h> 60#include <pango/pango.h>
55 61
56#ifndef PANGO_VERSION_CHECK 62#ifndef PANGO_VERSION_CHECK
57# define PANGO_VERSION_CHECK(a,b,c) 0 63# define PANGO_VERSION_CHECK(a,b,c) 0
81#define expect_false(expr) expect ((expr) != 0, 0) 87#define expect_false(expr) expect ((expr) != 0, 0)
82#define expect_true(expr) expect ((expr) != 0, 1) 88#define expect_true(expr) expect ((expr) != 0, 1)
83 89
84#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 90#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
85 91
92/* this is used as fow flag as well, so has to have a different value */
93/* then anything that is computed by incoming darkness */
86#define FOW_DARKNESS 16 94#define FOW_DARKNESS 50
95#define DARKNESS_ADJUST(n) (n)
87 96
88#define MAP_EXTEND_X 32 97#define MAP_EXTEND_X 32
89#define MAP_EXTEND_Y 512 98#define MAP_EXTEND_Y 512
90 99
91#define MIN_FONT_HEIGHT 10 100#define MIN_FONT_HEIGHT 10
92 101
93/* mask out modifiers we are not interested in */ 102/* mask out modifiers we are not interested in */
94#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META) 103#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
95 104
96#define KMOD_LRAM 0x10000 // our extension 105#define KMOD_LRAM 0x10000 // our extension
106
107#define TEXID_SPEECH 1
108#define TEXID_NOFACE 2
109
110static char *
111fast_sv_grow (SV *sv, STRLEN need)
112{
113 STRLEN len = SvLEN (sv);
114 STRLEN want = SvCUR (sv) + need;
115
116 if (expect_false (len < want))
117 {
118 do
119 len *= 2;
120 while (len < want);
121
122 sv_grow (sv, len);
123 }
124
125 SvCUR_set (sv, want);
126 return SvEND (sv) - need;
127}
97 128
98static AV *texture_av; 129static AV *texture_av;
99 130
100static struct 131static struct
101{ 132{
158{ 189{
159 GSList *attrs = run->item->analysis.extra_attrs; 190 GSList *attrs = run->item->analysis.extra_attrs;
160 191
161 while (attrs) 192 while (attrs)
162 { 193 {
163 PangoAttribute *attr = attrs->data; 194 PangoAttribute *attr = (PangoAttribute *)attrs->data;
164 195
165 if (attr->klass->type == PANGO_ATTR_SHAPE) 196 if (attr->klass->type == PANGO_ATTR_SHAPE)
166 return 1; 197 return 1;
167 198
168 attrs = attrs->next; 199 attrs = attrs->next;
169 } 200 }
170 201
171 return 0; 202 return 0;
172} 203}
173 204
174typedef struct cf_layout { 205struct cf_layout {
175 PangoLayout *pl; 206 PangoLayout *pl;
176 float r, g, b, a; // default color for rgba mode 207 float r, g, b, a; // default color for rgba mode
177 int base_height; 208 int base_height;
178 DC__Font font; 209 DC__Font font;
179 rc_t *rc; 210 rc_t rc;
180} *DC__Layout; 211};
212
213typedef cf_layout *DC__Layout;
181 214
182static DC__Font default_font; 215static DC__Font default_font;
183static PangoContext *opengl_context; 216static PangoContext *opengl_context;
184static PangoFontMap *opengl_fontmap; 217static PangoFontMap *opengl_fontmap;
185 218
186static void 219static void
187substitute_func (FcPattern *pattern, gpointer data) 220substitute_func (FcPattern *pattern, gpointer data)
188{ 221{
189 FcPatternAddBool (pattern, FC_HINTING, 1); 222 FcPatternAddBool (pattern, FC_HINTING, 1);
190#ifdef FC_HINT_STYLE 223#ifdef FC_HINT_STYLE
191 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 224 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
192#endif 225#endif
193 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 226 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
194} 227}
195 228
196static void 229static void
226} 259}
227 260
228typedef uint16_t tileid; 261typedef uint16_t tileid;
229typedef uint16_t faceid; 262typedef uint16_t faceid;
230 263
231typedef struct { 264struct maptex
265{
232 GLuint name; 266 GLuint name;
233 int w, h; 267 int w, h;
234 float s, t; 268 float s, t;
235 uint8_t r, g, b, a; 269 uint8_t r, g, b, a;
236 tileid smoothtile; 270 tileid smoothtile;
237 uint8_t smoothlevel; 271 uint8_t smoothlevel;
238 uint8_t unused; /* set to zero on use */ 272 uint8_t unused; /* set to zero on use */
239} maptex; 273};
240 274
241typedef struct { 275struct mapcell
276{
242 uint32_t player; 277 uint32_t player;
243 tileid tile[3]; 278 tileid tile[3];
244 uint16_t darkness; 279 uint16_t darkness;
245 uint8_t stat_width, stat_hp, flags, smoothmax; 280 uint8_t stat_width, stat_hp, flags, smoothmax;
246} mapcell; 281};
247 282
248typedef struct { 283struct maprow
284{
249 int32_t c0, c1; 285 int32_t c0, c1;
250 mapcell *col; 286 mapcell *col;
251} maprow; 287};
252 288
253typedef struct map { 289struct mapgrid {
254 int x, y, w, h; 290 int x, y, w, h;
255 int ox, oy; /* offset to virtual global coordinate system */ 291 int ox, oy; /* offset to virtual global coordinate system */
256 int faces; tileid *face2tile; // [faceid] 292 std::vector<tileid> tile;
257 int texs; maptex *tex; // [tileid] 293 std::vector<maptex> tex;
258 294
259 int32_t rows; 295 int32_t rows;
260 maprow *row; 296 maprow *row;
261} *DC__Map; 297
298 ~mapgrid ()
299 {
300 clear_cells ();
301 }
302
303 void clear_cells ();
304};
305
306typedef mapgrid *DC__Map;
262 307
263static char * 308static char *
264prepend (char *ptr, int sze, int inc) 309prepend (char *ptr, int sze, int inc)
265{ 310{
266 char *p; 311 char *p;
283} 328}
284 329
285#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 330#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
286#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 331#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
287 332
288static void
289need_facenum (struct map *self, faceid face)
290{
291 while (self->faces <= face)
292 {
293 Append (tileid, self->face2tile, self->faces, self->faces);
294 self->faces *= 2;
295 }
296}
297
298static void
299need_texid (struct map *self, int texid)
300{
301 while (self->texs <= texid)
302 {
303 Append (maptex, self->tex, self->texs, self->texs);
304 self->texs *= 2;
305 }
306}
307
308static maprow * 333static maprow *
309map_get_row (DC__Map self, int y) 334map_get_row (mapgrid *self, int y)
310{ 335{
311 if (0 > y) 336 if (0 > y)
312 { 337 {
313 int extend = - y + MAP_EXTEND_Y; 338 int extend = - y + MAP_EXTEND_Y;
314 Prepend (maprow, self->row, self->rows, extend); 339 Prepend (maprow, self->row, self->rows, extend);
352 377
353 return row->col + (x - row->c0); 378 return row->col + (x - row->c0);
354} 379}
355 380
356static mapcell * 381static mapcell *
357map_get_cell (DC__Map self, int x, int y) 382map_get_cell (mapgrid *self, int x, int y)
358{ 383{
359 return row_get_cell (map_get_row (self, y), x); 384 return row_get_cell (map_get_row (self, y), x);
360} 385}
361 386
362static void 387void mapgrid::clear_cells ()
363map_clear (DC__Map self)
364{ 388{
365 int r; 389 int r;
366 390
367 for (r = 0; r < self->rows; r++) 391 for (r = 0; r < rows; r++)
368 Safefree (self->row[r].col); 392 Safefree (row[r].col);
369 393
370 Safefree (self->row); 394 Safefree (row);
371 395
372 self->x = 0; 396 x = 0;
373 self->y = 0; 397 y = 0;
374 self->ox = 0; 398 ox = 0;
375 self->oy = 0; 399 oy = 0;
376 self->row = 0; 400 row = 0;
377 self->rows = 0; 401 rows = 0;
378} 402}
379 403
380#define CELL_CLEAR(cell) \ 404#define CELL_CLEAR(cell) \
381 do { \ 405 do { \
382 if ((cell)->player) \ 406 if ((cell)->player) \
386 (cell)->flags = 0; \ 410 (cell)->flags = 0; \
387 (cell)->player = 0; \ 411 (cell)->player = 0; \
388 } while (0) 412 } while (0)
389 413
390static void 414static void
391map_blank (DC__Map self, int x0, int y0, int w, int h) 415map_blank (mapgrid *self, int x0, int y0, int w, int h)
392{ 416{
393 int x, y; 417 int x, y;
394 maprow *row; 418 maprow *row;
395 mapcell *cell; 419 mapcell *cell;
396 420
413 CELL_CLEAR (cell); 437 CELL_CLEAR (cell);
414 } 438 }
415 } 439 }
416} 440}
417 441
418typedef struct { 442struct smooth_key
443{
419 tileid tile; 444 tileid tile;
420 uint8_t x, y, level; 445 uint8_t x, y, level;
421} smooth_key; 446
447 bool operator == (const smooth_key &o) const
448 {
449 return tile == o.tile && x == o.x && y == o.y && level == o.level;
450 }
451};
452
453typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
454
455namespace std {
456 template <>
457 struct hash<smooth_key>
458 {
459 size_t operator () (const smooth_key &v) const
460 {
461 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
462 }
463 };
464}
422 465
423static void 466static void
424smooth_or_bits (HV *hv, smooth_key *key, IV bits) 467smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
425{ 468{
426 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 469 auto &&it = h.find (key);
427 470
428 if (SvIOK (*sv)) 471 if (it == h.end ())
429 SvIV_set (*sv, SvIVX (*sv) | bits); 472 h.insert (std::make_pair (key, bits));
430 else 473 else
431 sv_setiv (*sv, bits); 474 it->second |= bits;
432} 475}
433 476
434static void 477static void
435music_finished (void) 478music_finished (void)
436{ 479{
453 ev.code = 1; 496 ev.code = 1;
454 ev.data1 = (void *)(long)channel; 497 ev.data1 = (void *)(long)channel;
455 ev.data2 = 0; 498 ev.data2 = 0;
456 499
457 SDL_PushEvent ((SDL_Event *)&ev); 500 SDL_PushEvent ((SDL_Event *)&ev);
501}
502
503// approximately divide by 255
504static unsigned int
505div255 (unsigned int n)
506{
507 return (n + (n >> 8)) >> 8;
458} 508}
459 509
460static unsigned int 510static unsigned int
461minpot (unsigned int n) 511minpot (unsigned int n)
462{ 512{
545 595
546 return mod; 596 return mod;
547} 597}
548 598
549static void 599static void
550deliantra_main () 600deliantra_main (SV *real_main)
551{ 601{
552 char *argv[] = { 0 }; 602 dSP;
553 call_argv ("::main", G_DISCARD | G_VOID, argv); 603
604 PUSHMARK (SP);
605 call_sv (real_main, G_DISCARD | G_VOID);
554} 606}
555 607
556#ifdef __MACOSX__ 608#ifdef __MACOSX__
609 static SV *real_main;
610
557 /* to due surprising braindamage on the side of SDL design, we 611 /* to due surprising braindamage on the side of SDL design, we
558 * do some mind-boggling hack here: SDL requires a custom main() 612 * do some mind-boggling hack here: SDL requires a custom main()
559 * on OS X, so... we provide one and call the original main(), which, 613 * on OS X, so... we provide one and call the original main(), which,
560 * due to share dlibrary magic, calls -lSDLmain's main, not perl's main, 614 * due to shared library magic, calls -lSDLmain's main, not perl's main,
561 * and which calls our main (== SDL_main) back. 615 * and which calls our main (== SDL_main) back.
562 */ 616 */
563 extern C_LINKAGE int 617 extern C_LINKAGE int
564 main (int argc, char *argv[]) 618 main (int argc, char *argv[])
565 { 619 {
566 deliantra_main (); 620 deliantra_main (real_main);
567 } 621 }
568 622
569 #undef main 623 #undef main
570 624
571 extern C_LINKAGE int main (int argc, char *argv[]); 625 extern C_LINKAGE int main (int argc, char *argv[]);
572 626
573 static void 627 static void
574 SDL_braino (void) 628 SDL_main_hack (SV *real_main_)
575 { 629 {
630 real_main = real_main_;
631
576 char *argv[] = { "deliantra client", 0 }; 632 char *argv[] = { "deliantra client", 0 };
577 (main) (1, argv); 633 (main) (1, argv);
578 } 634 }
579#else 635#else
580 static void 636 static void
581 SDL_braino (void) 637 SDL_main_hack (SV *real_main)
582 { 638 {
583 deliantra_main (); 639 deliantra_main (real_main);
584 } 640 }
585#endif 641#endif
586 642
587MODULE = Deliantra::Client PACKAGE = DC 643MODULE = Deliantra::Client PACKAGE = DC
588 644
789 845
790 const_iv (FOW_DARKNESS) 846 const_iv (FOW_DARKNESS)
791# undef const_iv 847# undef const_iv
792 }; 848 };
793 849
794 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 850 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
795 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 851 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
796 852
797 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 853 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
798 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 854 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
799} 855}
800 856
816NV ceil (NV x) 872NV ceil (NV x)
817 873
818IV minpot (UV n) 874IV minpot (UV n)
819 875
820IV popcount (UV n) 876IV popcount (UV n)
877
878NV distance (NV dx, NV dy)
879 CODE:
880 RETVAL = pow (dx * dx + dy * dy, 0.5);
881 OUTPUT:
882 RETVAL
821 883
822void 884void
823pango_init () 885pango_init ()
824 CODE: 886 CODE:
825{ 887{
833#endif 895#endif
834} 896}
835 897
836char *SDL_GetError () 898char *SDL_GetError ()
837 899
838void SDL_braino () 900void SDL_main_hack (SV *real_main)
901 PROTOTYPE: &
839 902
840int SDL_Init (U32 flags) 903int SDL_Init (U32 flags)
841 904
842int SDL_InitSubSystem (U32 flags) 905int SDL_InitSubSystem (U32 flags)
843 906
844void SDL_QuitSubSystem (U32 flags) 907void SDL_QuitSubSystem (U32 flags)
845 908
846void SDL_Quit () 909void SDL_Quit ()
847 910
848int SDL_GL_SetAttribute (int attr, int value) 911int SDL_GL_SetAttribute (int attr, int value)
912 C_ARGS: (SDL_GLattr)attr, value
849 913
850int SDL_GL_GetAttribute (int attr) 914int SDL_GL_GetAttribute (int attr)
851 CODE: 915 CODE:
852 if (SDL_GL_GetAttribute (attr, &RETVAL)) 916 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
853 XSRETURN_UNDEF; 917 XSRETURN_UNDEF;
854 OUTPUT: 918 OUTPUT:
855 RETVAL 919 RETVAL
856 920
857void 921void
912 ); 976 );
913 977
914 if (RETVAL) 978 if (RETVAL)
915 { 979 {
916 av_clear (texture_av); 980 av_clear (texture_av);
917
918 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
919#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 981#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
920#include "glfunc.h" 982#include "glfunc.h"
921#undef GL_FUNC 983#undef GL_FUNC
984 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
985 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
922 } 986 }
923} 987}
924 OUTPUT: 988 OUTPUT:
925 RETVAL 989 RETVAL
990
991void
992SDL_WM_SetCaption (const char *title, const char *icon)
926 993
927void 994void
928SDL_GL_SwapBuffers () 995SDL_GL_SwapBuffers ()
929 996
930char * 997char *
931SDL_GetKeyName (int sym) 998SDL_GetKeyName (int sym)
999 C_ARGS: (SDLKey)sym
932 1000
933int 1001int
934SDL_GetAppState () 1002SDL_GetAppState ()
935 1003
936int 1004int
937SDL_GetModState () 1005SDL_GetModState ()
938 1006
1007int
1008SDL_WaitEvent ()
1009 C_ARGS: 0
1010
939void 1011void
1012SDL_PumpEvents ()
1013
1014void
940poll_events () 1015peep_events ()
941 PPCODE: 1016 PPCODE:
942{ 1017{
943 SDL_Event ev; 1018 SDL_Event ev;
944 1019
945 SDL_PumpEvents (); 1020 SDL_PumpEvents ();
1011 1086
1012 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1087 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1013 } 1088 }
1014} 1089}
1015 1090
1091char *
1092SDL_AudioDriverName ()
1093 CODE:
1094{
1095 char buf [256];
1096 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1097 XSRETURN_UNDEF;
1098
1099 RETVAL = buf;
1100}
1101 OUTPUT:
1102 RETVAL
1103
1016int 1104int
1017Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1105Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1018 POSTCALL: 1106 POSTCALL:
1019 Mix_HookMusicFinished (music_finished); 1107 Mix_HookMusicFinished (music_finished);
1020 Mix_ChannelFinished (channel_finished); 1108 Mix_ChannelFinished (channel_finished);
1021 1109
1022void 1110void
1023Mix_QuerySpec () 1111Mix_QuerySpec ()
1082add_font (char *file) 1170add_font (char *file)
1083 CODE: 1171 CODE:
1084 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1172 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1085 OUTPUT: 1173 OUTPUT:
1086 RETVAL 1174 RETVAL
1175
1176void
1177IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1178
1179# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1180void
1181Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
1087 1182
1088void 1183void
1089load_image_inline (SV *image_) 1184load_image_inline (SV *image_)
1090 ALIAS: 1185 ALIAS:
1091 load_image_file = 1 1186 load_image_file = 1
1137 1232
1138 SDL_LockSurface (surface2); 1233 SDL_LockSurface (surface2);
1139 EXTEND (SP, 6); 1234 EXTEND (SP, 6);
1140 PUSHs (sv_2mortal (newSViv (surface2->w))); 1235 PUSHs (sv_2mortal (newSViv (surface2->w)));
1141 PUSHs (sv_2mortal (newSViv (surface2->h))); 1236 PUSHs (sv_2mortal (newSViv (surface2->h)));
1142 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1237 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
1143 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB))); 1238 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1144 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1239 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1145 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1240 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1146 SDL_UnlockSurface (surface2); 1241 SDL_UnlockSurface (surface2);
1147 1242
1219MODULE = Deliantra::Client PACKAGE = DC::Font 1314MODULE = Deliantra::Client PACKAGE = DC::Font
1220 1315
1221PROTOTYPES: DISABLE 1316PROTOTYPES: DISABLE
1222 1317
1223DC::Font 1318DC::Font
1224new_from_file (SV *class, char *path, int id = 0) 1319new_from_file (SV *klass, char *path, int id = 0)
1225 CODE: 1320 CODE:
1226{ 1321{
1227 int count; 1322 int count;
1228 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1323 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1229 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1324 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1258 PROTOTYPE: 1353 PROTOTYPE:
1259 CODE: 1354 CODE:
1260 tc_restore (); 1355 tc_restore ();
1261 1356
1262DC::Layout 1357DC::Layout
1263new (SV *class) 1358new (SV *klass)
1264 CODE: 1359 CODE:
1265 New (0, RETVAL, 1, struct cf_layout); 1360 RETVAL = new cf_layout;
1266 1361
1267 RETVAL->pl = pango_layout_new (opengl_context); 1362 RETVAL->pl = pango_layout_new (opengl_context);
1268 RETVAL->r = 1.; 1363 RETVAL->r = 1.;
1269 RETVAL->g = 1.; 1364 RETVAL->g = 1.;
1270 RETVAL->b = 1.; 1365 RETVAL->b = 1.;
1271 RETVAL->a = 1.; 1366 RETVAL->a = 1.;
1272 RETVAL->base_height = MIN_FONT_HEIGHT; 1367 RETVAL->base_height = MIN_FONT_HEIGHT;
1273 RETVAL->font = 0; 1368 RETVAL->font = 0;
1274 RETVAL->rc = rc_alloc ();
1275 1369
1276 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1370 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1277 layout_update_font (RETVAL); 1371 layout_update_font (RETVAL);
1278 OUTPUT: 1372 OUTPUT:
1279 RETVAL 1373 RETVAL
1280 1374
1281void 1375void
1282DESTROY (DC::Layout self) 1376DESTROY (DC::Layout self)
1283 CODE: 1377 CODE:
1284 g_object_unref (self->pl); 1378 g_object_unref (self->pl);
1285 rc_free (self->rc);
1286 Safefree (self); 1379 delete self;
1287 1380
1288void 1381void
1289set_text (DC::Layout self, SV *text_) 1382set_text (DC::Layout self, SV *text_)
1290 CODE: 1383 CODE:
1291{ 1384{
1417 1510
1418void 1511void
1419set_height (DC::Layout self, int base_height) 1512set_height (DC::Layout self, int base_height)
1420 CODE: 1513 CODE:
1421 if (self->base_height != base_height) 1514 if (self->base_height != base_height)
1422 { 1515 {
1423 self->base_height = base_height; 1516 self->base_height = base_height;
1424 layout_update_font (self); 1517 layout_update_font (self);
1425 } 1518 }
1426 1519
1427void 1520void
1545} 1638}
1546 1639
1547void 1640void
1548render (DC::Layout self, float x, float y, int flags = 0) 1641render (DC::Layout self, float x, float y, int flags = 0)
1549 CODE: 1642 CODE:
1550 rc_clear (self->rc); 1643 self->rc.clear ();
1551 pango_opengl_render_layout_subpixel ( 1644 pango_opengl_render_layout_subpixel (
1552 self->pl, 1645 self->pl,
1553 self->rc, 1646 &self->rc,
1554 x * PANGO_SCALE, y * PANGO_SCALE, 1647 x * PANGO_SCALE, y * PANGO_SCALE,
1555 self->r, self->g, self->b, self->a, 1648 self->r, self->g, self->b, self->a,
1556 flags 1649 flags
1557 ); 1650 );
1558 // we assume that context_change actually clears/frees stuff 1651 // we assume that context_change actually clears/frees stuff
1569 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1662 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1570 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1663 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1571 glEnable (GL_ALPHA_TEST); 1664 glEnable (GL_ALPHA_TEST);
1572 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1665 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1573 1666
1574 rc_draw (self->rc); 1667 self->rc.draw ();
1575 1668
1576 glDisable (GL_ALPHA_TEST); 1669 glDisable (GL_ALPHA_TEST);
1577 glDisable (GL_BLEND); 1670 glDisable (GL_BLEND);
1578 glDisable (GL_TEXTURE_2D); 1671 glDisable (GL_TEXTURE_2D);
1579} 1672}
1654 glDisable (GL_ALPHA_TEST); 1747 glDisable (GL_ALPHA_TEST);
1655 glDisable (GL_BLEND); 1748 glDisable (GL_BLEND);
1656 } 1749 }
1657} 1750}
1658 1751
1752void
1753draw_fow_texture (float intensity, int hidden_tex, int name1, uint8_t *data1, float s, float t, int w, int h, float blend = 0.f, int dx = 0, int dy = 0, int name2 = 0, uint8_t *data2 = data1)
1754 PROTOTYPE: @
1755 CODE:
1756{
1757 glEnable (GL_BLEND);
1758 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1759 glEnable (GL_TEXTURE_2D);
1760 glBindTexture (GL_TEXTURE_2D, name1);
1761
1762 glColor3f (intensity, intensity, intensity);
1763 glPushMatrix ();
1764 glScalef (1./3, 1./3, 1.);
1765
1766 if (blend > 0.f)
1767 {
1768 float dx3 = dx * -3.f / w;
1769 float dy3 = dy * -3.f / h;
1770 GLfloat env_color[4] = { 0., 0., 0., blend };
1771
1772 /* interpolate the two shadow textures */
1773 /* stage 0 == rgb(glcolor) + alpha(t0) */
1774 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1775
1776 /* stage 1 == rgb(glcolor) + alpha(interpolate t0, t1, texenv) */
1777 gl.ActiveTexture (GL_TEXTURE1);
1778 glEnable (GL_TEXTURE_2D);
1779 glBindTexture (GL_TEXTURE_2D, name2);
1780 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1781
1782 /* rgb == rgb(glcolor) */
1783 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1784 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1785 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1786
1787 /* alpha = interpolate t0, t1 by env_alpha */
1788 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1789
1790 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
1791 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
1792 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1793
1794 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
1795 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1796
1797 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1798 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1799
1800 glBegin (GL_QUADS);
1801 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1802 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1803 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1804 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1805 glEnd ();
1806
1807 glDisable (GL_TEXTURE_2D);
1808 gl.ActiveTexture (GL_TEXTURE0);
1809 }
1810 else
1811 {
1812 /* simple blending of one texture, also opengl <1.3 path */
1813 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1814
1815 glBegin (GL_QUADS);
1816 glTexCoord2f (0, 0); glVertex2f (0, 0);
1817 glTexCoord2f (0, t); glVertex2f (0, h);
1818 glTexCoord2f (s, t); glVertex2f (w, h);
1819 glTexCoord2f (s, 0); glVertex2f (w, 0);
1820 glEnd ();
1821 }
1822
1823 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1824 {
1825 int x, y;
1826 int dx3 = dx * 3;
1827 int dy3 = dy * 3;
1828
1829 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1830 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1831 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1832 glTranslatef (-1., -1., 0);
1833 glBegin (GL_QUADS);
1834
1835 for (y = 1; y < h; y += 3)
1836 {
1837 int y1 = y - dy3;
1838 int y1valid = y1 >= 0 && y1 < h;
1839
1840 for (x = 1; x < w; x += 3)
1841 {
1842 int x1 = x - dx3;
1843 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1844 uint8_t h2;
1845
1846 if (y1valid && x1 >= 0 && x1 < w)
1847 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1848 else
1849 h2 = 1; /* out of range == invisible */
1850
1851 if (h1 || h2)
1852 {
1853 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1854 glColor4f (1., 1., 1., alpha);
1855
1856 glTexCoord2f (0, 0.); glVertex2i (x , y );
1857 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1858 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1859 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1860 }
1861 }
1862 }
1863 }
1864
1865 glEnd ();
1866
1867 glPopMatrix ();
1868
1869 glDisable (GL_TEXTURE_2D);
1870 glDisable (GL_BLEND);
1871}
1872
1659IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type) 1873IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1660 CODE: 1874 CODE:
1661{ 1875{
1662 GLint width; 1876 GLint width;
1663 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0); 1877 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1670MODULE = Deliantra::Client PACKAGE = DC::Map 1884MODULE = Deliantra::Client PACKAGE = DC::Map
1671 1885
1672PROTOTYPES: DISABLE 1886PROTOTYPES: DISABLE
1673 1887
1674DC::Map 1888DC::Map
1675new (SV *class) 1889new (SV *klass)
1676 CODE: 1890 CODE:
1677 New (0, RETVAL, 1, struct map); 1891 RETVAL = new mapgrid;
1678 RETVAL->x = 0; 1892 RETVAL->x = 0;
1679 RETVAL->y = 0; 1893 RETVAL->y = 0;
1680 RETVAL->w = 0; 1894 RETVAL->w = 0;
1681 RETVAL->h = 0; 1895 RETVAL->h = 0;
1682 RETVAL->ox = 0; 1896 RETVAL->ox = 0;
1683 RETVAL->oy = 0; 1897 RETVAL->oy = 0;
1684 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1685 RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1686 RETVAL->rows = 0; 1898 RETVAL->rows = 0;
1687 RETVAL->row = 0; 1899 RETVAL->row = 0;
1688 OUTPUT: 1900 OUTPUT:
1689 RETVAL 1901 RETVAL
1690 1902
1691void 1903void
1692DESTROY (DC::Map self) 1904DESTROY (DC::Map self)
1693 CODE: 1905 CODE:
1694{ 1906{
1695 map_clear (self);
1696 Safefree (self->face2tile);
1697 Safefree (self->tex);
1698 Safefree (self); 1907 delete self;
1699} 1908}
1700 1909
1701void 1910void
1702resize (DC::Map self, int map_width, int map_height) 1911resize (DC::Map self, int map_width, int map_height)
1703 CODE: 1912 CODE:
1705 self->h = map_height; 1914 self->h = map_height;
1706 1915
1707void 1916void
1708clear (DC::Map self) 1917clear (DC::Map self)
1709 CODE: 1918 CODE:
1710 map_clear (self); 1919 self->clear_cells ();
1711 1920
1712void 1921void
1713set_tileid (DC::Map self, int face, int tile) 1922set_tileid (DC::Map self, int face, int tile)
1714 CODE: 1923 CODE:
1715{ 1924{
1716 need_facenum (self, face); self->face2tile [face] = tile; 1925 if (self->tile.size () <= face) self->tile.resize (face + 1);
1717 need_texid (self, tile); 1926 self->tile[face] = tile;
1927 if (self->tex.size () <= tile) self->tex .resize (tile + 1);
1718} 1928}
1719 1929
1720void 1930void
1721set_smooth (DC::Map self, int face, int smooth, int level) 1931set_smooth (DC::Map self, int face, int smooth, int level)
1722 CODE: 1932 CODE:
1723{ 1933{
1724 tileid texid;
1725 maptex *tex;
1726
1727 if (face < 0 || face >= self->faces) 1934 if (face < 0 || face >= self->tile.size ())
1728 return; 1935 return;
1729 1936
1730 if (smooth < 0 || smooth >= self->faces) 1937 if (smooth < 0 || smooth >= self->tile.size ())
1731 return; 1938 return;
1732 1939
1733 texid = self->face2tile [face]; 1940 tileid texid = self->tile[face];
1734 1941
1735 if (!texid) 1942 if (!texid)
1736 return; 1943 return;
1737 1944
1738 tex = self->tex + texid; 1945 maptex &tex = self->tex[texid];
1739 tex->smoothtile = self->face2tile [smooth]; 1946 tex.smoothtile = self->tile[smooth];
1740 tex->smoothlevel = level; 1947 tex.smoothlevel = level;
1741} 1948}
1742 1949
1743void 1950void
1744set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1951set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1745 CODE: 1952 CODE:
1746{ 1953{
1747 need_texid (self, texid); 1954 if (self->tex.size () < texid) self->tex.resize (texid + 1);
1748 1955
1749 { 1956 {
1750 maptex *tex = self->tex + texid; 1957 maptex &tex = self->tex[texid];
1751 1958
1752 tex->name = name; 1959 tex.name = name;
1753 tex->w = w; 1960 tex.w = w;
1754 tex->h = h; 1961 tex.h = h;
1755 tex->s = s; 1962 tex.s = s;
1756 tex->t = t; 1963 tex.t = t;
1757 tex->r = r; 1964 tex.r = r;
1758 tex->g = g; 1965 tex.g = g;
1759 tex->b = b; 1966 tex.b = b;
1760 tex->a = a; 1967 tex.a = a;
1761 } 1968 }
1762 1969
1763 // somewhat hackish, but for textures that require it, it really 1970 // somewhat hackish, but for textures that require it, it really
1764 // improves the look, and most others don't suffer. 1971 // improves the look, and most others don't suffer.
1765 glBindTexture (GL_TEXTURE_2D, name); 1972 glBindTexture (GL_TEXTURE_2D, name);
1771} 1978}
1772 1979
1773void 1980void
1774expire_textures (DC::Map self, int texid, int count) 1981expire_textures (DC::Map self, int texid, int count)
1775 PPCODE: 1982 PPCODE:
1776 for (; texid < self->texs && count; ++texid, --count) 1983 for (; texid < self->tex.size () && count; ++texid, --count)
1777 { 1984 {
1778 maptex *tex = self->tex + texid; 1985 maptex &tex = self->tex[texid];
1779 1986
1780 if (tex->name) 1987 if (tex.name)
1781 { 1988 {
1782 if (tex->unused) 1989 if (tex.unused)
1783 { 1990 {
1784 tex->name = 0; 1991 tex.name = 0;
1785 tex->unused = 0; 1992 tex.unused = 0;
1786 XPUSHs (sv_2mortal (newSViv (texid))); 1993 XPUSHs (sv_2mortal (newSViv (texid)));
1787 } 1994 }
1788 else 1995 else
1789 tex->unused = 1; 1996 tex.unused = 1;
1790 } 1997 }
1791 } 1998 }
1792 1999
1793int 2000int
1794ox (DC::Map self) 2001ox (DC::Map self)
1836 self->y += MAP_EXTEND_Y; 2043 self->y += MAP_EXTEND_Y;
1837 } 2044 }
1838} 2045}
1839 2046
1840SV * 2047SV *
1841map1a_update (DC::Map self, SV *data_, int extmap) 2048map1a_update (DC::Map self, SV *data_)
1842 CODE: 2049 CODE:
1843{ 2050{
1844 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2051 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1845 uint8_t *data_end = (uint8_t *)SvEND (data_); 2052 uint8_t *data_end = (uint8_t *)SvEND (data_);
1846 mapcell *cell; 2053 mapcell *cell;
1867 2074
1868 //TODO: don't trust server data to be in-range(!) 2075 //TODO: don't trust server data to be in-range(!)
1869 2076
1870 if (flags & 8) 2077 if (flags & 8)
1871 { 2078 {
2079 uint8_t ext, cmd;
2080
1872 if (extmap) 2081 do
1873 { 2082 {
1874 uint8_t ext, cmd; 2083 ext = *data++;
2084 cmd = ext & 0x7f;
1875 2085
1876 do 2086 if (cmd < 4)
2087 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2088 else if (cmd == 5) // health
1877 { 2089 {
1878 ext = *data++;
1879 cmd = ext & 0x7f;
1880
1881 if (cmd < 4)
1882 cell->darkness = 255 - ext * 64 + 1;
1883 else if (cmd == 5) // health
1884 {
1885 cell->stat_width = 1; 2090 cell->stat_width = 1;
1886 cell->stat_hp = *data++; 2091 cell->stat_hp = *data++;
1887 }
1888 else if (cmd == 6) // monster width
1889 cell->stat_width = *data++ + 1;
1890 else if (cmd == 0x47)
1891 {
1892 if (*data == 1) cell->player = data [1];
1893 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
1894 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
1895 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1896
1897 data += *data + 1;
1898 }
1899 else if (cmd == 8) // cell flags
1900 cell->flags = *data++;
1901 else if (ext & 0x40) // unknown, multibyte => skip
1902 data += *data + 1;
1903 else
1904 data++;
1905 } 2092 }
1906 while (ext & 0x80); 2093 else if (cmd == 6) // monster width
2094 cell->stat_width = *data++ + 1;
2095 else if (cmd == 0x47)
2096 {
2097 if (*data == 1) cell->player = data [1];
2098 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2099 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2100 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2101
2102 data += *data + 1;
2103 }
2104 else if (cmd == 8) // cell flags
2105 cell->flags = *data++;
2106 else if (ext & 0x40) // unknown, multibyte => skip
2107 data += *data + 1;
2108 else
2109 data++;
1907 } 2110 }
1908 else 2111 while (ext & 0x80);
1909 cell->darkness = *data++ + 1;
1910 } 2112 }
1911 2113
1912 for (z = 0; z <= 2; ++z) 2114 for (z = 0; z <= 2; ++z)
1913 if (flags & (4 >> z)) 2115 if (flags & (4 >> z))
1914 { 2116 {
1915 faceid face = (data [0] << 8) + data [1]; data += 2; 2117 faceid face = (data[0] << 8) + data[1]; data += 2;
1916 need_facenum (self, face); 2118 if (self->tile.size () <= face) self->tile.resize (face + 1);
1917 cell->tile [z] = self->face2tile [face]; 2119 cell->tile[z] = self->tile[face];
1918 2120
1919 if (cell->tile [z]) 2121 if (cell->tile[z])
1920 { 2122 {
1921 maptex *tex = self->tex + cell->tile [z]; 2123 maptex &tex = self->tex[cell->tile[z]];
1922 tex->unused = 0; 2124 tex.unused = 0;
1923 if (!tex->name) 2125 if (!tex.name)
1924 av_push (missing, newSViv (cell->tile [z])); 2126 av_push (missing, newSViv (cell->tile [z]));
1925 2127
1926 if (tex->smoothtile) 2128 if (tex.smoothtile)
1927 { 2129 {
1928 maptex *smooth = self->tex + tex->smoothtile; 2130 maptex &smooth = self->tex[tex.smoothtile];
1929 smooth->unused = 0; 2131 smooth.unused = 0;
1930 if (!smooth->name) 2132 if (!smooth.name)
1931 av_push (missing, newSViv (tex->smoothtile)); 2133 av_push (missing, newSViv (tex.smoothtile));
1932 } 2134 }
1933 } 2135 }
1934 } 2136 }
1935 } 2137 }
1936 else 2138 else
1962 ? self->row + y 2164 ? self->row + y
1963 : 0; 2165 : 0;
1964 2166
1965 for (x = x0; x < x1; x++) 2167 for (x = x0; x < x1; x++)
1966 { 2168 {
1967 int r = 32, g = 32, b = 32, a = 192; 2169 unsigned int r = 32, g = 32, b = 32, a = 192;
1968 2170
1969 if (row && row->c0 <= x && x < row->c1) 2171 if (row && row->c0 <= x && x < row->c1)
1970 { 2172 {
1971 mapcell *cell = row->col + (x - row->c0); 2173 mapcell *cell = row->col + (x - row->c0);
1972 2174
1974 { 2176 {
1975 maptex tex = self->tex [cell->tile [z]]; 2177 maptex tex = self->tex [cell->tile [z]];
1976 int a0 = 255 - tex.a; 2178 int a0 = 255 - tex.a;
1977 int a1 = tex.a; 2179 int a1 = tex.a;
1978 2180
1979 r = (r * a0 + tex.r * a1) / 255; 2181 r = div255 (r * a0 + tex.r * a1);
1980 g = (g * a0 + tex.g * a1) / 255; 2182 g = div255 (g * a0 + tex.g * a1);
1981 b = (b * a0 + tex.b * a1) / 255; 2183 b = div255 (b * a0 + tex.b * a1);
1982 a = (a * a0 + tex.a * a1) / 255; 2184 a = div255 (a * a0 + tex.a * a1);
1983 } 2185 }
1984 } 2186 }
1985 2187
1986 *map++ = (r ) 2188 *map++ = (r )
1987 | (g << 8) 2189 | (g << 8)
1988 | (b << 16) 2190 | (b << 16)
1989 | (a << 24); 2191 | (a << 24);
1990 } 2192 }
1991 } 2193 }
1992 2194
1993 RETVAL = map_sv; 2195 RETVAL = map_sv;
1994} 2196}
1995 OUTPUT: 2197 OUTPUT:
1996 RETVAL 2198 RETVAL
1997 2199
1998void 2200void
1999draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0) 2201draw (DC::Map self, int mx, int my, int sw, int sh, int Tw, int Th, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
2000 CODE: 2202 CODE:
2001{ 2203{
2002 int x, y, z; 2204 int x, y, z;
2003 2205
2004 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
2005 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
2006 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) 2206 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k), also, static!
2007 smooth_key skey;
2008 int pl_x, pl_y; 2207 int pl_x, pl_y;
2009 maptex pl_tex; 2208 maptex pl_tex;
2010 rc_t *rc = rc_alloc (); 2209 rc_t rc;
2210 rc_t rc_ov;
2011 rc_key_t key; 2211 rc_key_t key;
2012 rc_array_t *arr; 2212 rc_t::array_t *arr;
2013 2213
2014 pl_tex.name = 0; 2214 pl_tex.name = 0;
2015 2215
2016 // thats current max. sorry. 2216 // that's current max. sorry.
2017 if (sw > 255) sw = 255; 2217 if (sw > 255) sw = 255;
2018 if (sh > 255) sh = 255; 2218 if (sh > 255) sh = 255;
2019
2020 // clear key, in case of extra padding
2021 memset (&skey, 0, sizeof (skey));
2022 2219
2023 memset (&key, 0, sizeof (key)); 2220 memset (&key, 0, sizeof (key));
2024 key.r = 255; 2221 key.r = 255;
2025 key.g = 255; 2222 key.g = 255;
2026 key.b = 255; 2223 key.b = 255;
2032 my += self->y; 2229 my += self->y;
2033 2230
2034 // first pass: determine smooth_max 2231 // first pass: determine smooth_max
2035 // rather ugly, if you ask me 2232 // rather ugly, if you ask me
2036 // could also be stored inside mapcell and updated on change 2233 // could also be stored inside mapcell and updated on change
2037 memset (smooth_max, 0, sizeof (smooth_max)); 2234 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
2038 2235
2039 for (y = 0; y < sh; y++) 2236 for (y = 0; y < sh; y++)
2040 if (0 <= y + my && y + my < self->rows) 2237 if (0 <= y + my && y + my < self->rows)
2041 { 2238 {
2042 maprow *row = self->row + (y + my); 2239 maprow *row = self->row + (y + my);
2057 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2254 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2058 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2255 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2059 2256
2060 for (z = 0; z <= 2; z++) 2257 for (z = 0; z <= 2; z++)
2061 { 2258 {
2062 memset (smooth_level, 0, sizeof (smooth_level)); 2259 std::bitset<256> smooth_level; // one bit for every possible smooth level
2260 smooth_key skey;
2261 smooth_hash smooth;
2063 key.texname = -1; 2262 key.texname = -1;
2064 2263
2065 for (y = 0; y < sh; y++) 2264 for (y = 0; y < sh; y++)
2066 if (0 <= y + my && y + my < self->rows) 2265 if (0 <= y + my && y + my < self->rows)
2067 { 2266 {
2074 tileid tile = cell->tile [z]; 2273 tileid tile = cell->tile [z];
2075 2274
2076 if (tile) 2275 if (tile)
2077 { 2276 {
2078 maptex tex = self->tex [tile]; 2277 maptex tex = self->tex [tile];
2079 int px = (x + 1) * T - tex.w; 2278 int px, py;
2080 int py = (y + 1) * T - tex.h;
2081 2279
2082 if (key.texname != tex.name) 2280 if (key.texname != tex.name)
2083 { 2281 {
2084 self->tex [tile].unused = 0; 2282 self->tex [tile].unused = 0;
2085 2283
2086 if (!tex.name) 2284 if (!tex.name)
2087 tex = self->tex [2]; /* missing, replace by noface */ 2285 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2088 2286
2089 key.texname = tex.name; 2287 key.texname = tex.name;
2090 arr = rc_array (rc, &key); 2288 arr = &rc.array (key);
2091 } 2289 }
2290
2291 px = (x + 1) * Th - tex.w;
2292 py = (y + 1) * Tw - tex.h;
2092 2293
2093 if (expect_false (cell->player == player) && expect_false (z == 2)) 2294 if (expect_false (cell->player == player) && expect_false (z == 2))
2094 { 2295 {
2095 pl_x = px; 2296 pl_x = px;
2096 pl_y = py; 2297 pl_y = py;
2097 pl_tex = tex; 2298 pl_tex = tex;
2098 continue; 2299 continue;
2099 } 2300 }
2100 2301
2101 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2302 arr->t2f_v3f (0 , 0 , px , py , 0);
2102 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2303 arr->t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2103 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2304 arr->t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2104 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2305 arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2105
2106 if (expect_false (cell->flags) && expect_false (z == 2))
2107 {
2108 // overlays such as the speech bubble, probably more to come
2109 if (cell->flags & 1)
2110 {
2111 maptex tex = self->tex [1];
2112 int px = x * T + T * 2 / 32;
2113 int py = y * T - T * 6 / 32;
2114
2115 if (tex.name)
2116 {
2117 if (key.texname != tex.name)
2118 {
2119 key.texname = tex.name;
2120 arr = rc_array (rc, &key);
2121 }
2122
2123 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2124 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
2125 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
2126 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
2127 }
2128 }
2129 }
2130 2306
2131 // update smooth hash 2307 // update smooth hash
2132 if (tex.smoothtile) 2308 if (tex.smoothtile)
2133 { 2309 {
2134 skey.tile = tex.smoothtile; 2310 skey.tile = tex.smoothtile;
2135 skey.level = tex.smoothlevel; 2311 skey.level = tex.smoothlevel;
2136 2312
2137 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2313 smooth_level[tex.smoothlevel] = 1;
2138 2314
2139 // add bits to current tile and all neighbours. skey.x|y is 2315 // add bits to current tile and all neighbours. skey.x|y is
2140 // shifted +1|+1 so we always stay positive. 2316 // shifted +1|+1 so we always stay positive.
2141 2317
2142 // bits is ___n cccc CCCC bbbb 2318 // bits is ___n cccc CCCC bbbb
2150 2326
2151 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2327 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2152 // ·· ·· ·┏ ┓· 2328 // ·· ·· ·┏ ┓·
2153 2329
2154 // full tile 2330 // full tile
2155 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2331 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
2156 2332
2157 // borders 2333 // borders
2158 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2334 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0091);
2159 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032); 2335 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0032);
2160 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064); 2336 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0064);
2161 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8); 2337 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
2162 2338
2163 // corners 2339 // corners
2164 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2340 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0100);
2165 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2341 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0200);
2166 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2342 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, skey, 0x0400);
2167 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2343 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2344 }
2345 }
2346
2347 if (expect_false (z == 2) && expect_false (cell->flags))
2348 {
2349 // overlays such as the speech bubble, probably more to come
2350 if (cell->flags & 1)
2351 {
2352 rc_key_t key_ov = key;
2353 maptex tex = self->tex[TEXID_SPEECH];
2354 int px = x * Tw + Tw * 2 / 32;
2355 int py = y * Th - Th * 6 / 32;
2356
2357 key_ov.texname = tex.name;
2358 rc_t::array_t &arr = rc_ov.array (key_ov);
2359
2360 arr.t2f_v3f (0 , 0 , px , py , 0);
2361 arr.t2f_v3f (0 , tex.t, px , py + Th, 0);
2362 arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0);
2363 arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0);
2168 } 2364 }
2169 } 2365 }
2170 } 2366 }
2171 } 2367 }
2172 2368
2173 rc_draw (rc); 2369 rc.draw ();
2174 rc_clear (rc); 2370 rc.clear ();
2175 2371
2176 // go through all smoothlevels, lowest to highest, then draw. 2372 // go through all smoothlevels, lowest to highest, then draw.
2177 // this is basically counting sort 2373 // this is basically counting sort
2178 { 2374 {
2179 int w, b; 2375 int w, b;
2180 2376
2181 glEnable (GL_TEXTURE_2D); 2377 glEnable (GL_TEXTURE_2D);
2182 glBegin (GL_QUADS); 2378 glBegin (GL_QUADS);
2183 for (w = 0; w < 256 / 32; ++w) 2379 for (int level = 0; level < smooth_level.size (); ++level)
2380 if (smooth_level[level])
2381 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2184 { 2382 {
2185 uint32_t smask = smooth_level [w]; 2383 smooth_key &skey = it->first;
2186 if (smask) 2384 IV bits = it->second;
2187 for (b = 0; b < 32; ++b) 2385
2188 if (smask & (((uint32_t)1) << b)) 2386 if (!(bits & 0x1000)
2387 && skey.level == level
2388 && level > smooth_max [skey.x][skey.y])
2189 { 2389 {
2190 int level = (w << 5) | b; 2390 maptex tex = self->tex [skey.tile];
2391 int px = (((int)skey.x) - 1) * Tw;
2392 int py = (((int)skey.y) - 1) * Th;
2393 int border = bits & 15;
2394 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2395 float dx = tex.s * .0625f; // 16 images/row
2396 float dy = tex.t * .5f ; // 2 images/column
2397
2191 HE *he; 2398 if (tex.name)
2192
2193 hv_iterinit (smooth);
2194 while ((he = hv_iternext (smooth)))
2195 { 2399 {
2196 smooth_key *skey = (smooth_key *)HeKEY (he); 2400 // this time avoiding texture state changes
2197 IV bits = SvIVX (HeVAL (he)); 2401 // save gobs of state changes.
2198 2402 if (key.texname != tex.name)
2199 if (!(bits & 0x1000)
2200 && skey->level == level
2201 && level > smooth_max [skey->x][skey->y])
2202 { 2403 {
2203 maptex tex = self->tex [skey->tile];
2204 int px = (((int)skey->x) - 1) * T;
2205 int py = (((int)skey->y) - 1) * T;
2206 int border = bits & 15;
2207 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2208 float dx = tex.s * .0625f; // 16 images/row
2209 float dy = tex.t * .5f ; // 2 images/column
2210
2211 if (tex.name)
2212 {
2213 // this time avoiding texture state changes
2214 // save gobs of state changes.
2215 if (key.texname != tex.name)
2216 {
2217 self->tex [skey->tile].unused = 0; 2404 self->tex [skey.tile].unused = 0;
2218 2405
2219 glEnd (); 2406 glEnd ();
2220 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2407 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2221 glBegin (GL_QUADS); 2408 glBegin (GL_QUADS);
2222 } 2409 }
2223 2410
2224 if (border) 2411 if (border)
2225 { 2412 {
2226 float ox = border * dx; 2413 float ox = border * dx;
2227 2414
2228 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2415 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2229 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2416 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2230 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2417 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2231 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2418 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2232 } 2419 }
2233 2420
2234 if (corner) 2421 if (corner)
2235 { 2422 {
2236 float ox = corner * dx; 2423 float ox = corner * dx;
2237 2424
2238 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2425 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2239 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2426 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2240 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2427 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2241 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2428 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2242 }
2243 }
2244 } 2429 }
2245 } 2430 }
2246 } 2431 }
2247 } 2432 }
2248 2433
2249 glEnd (); 2434 glEnd ();
2250 glDisable (GL_TEXTURE_2D); 2435 glDisable (GL_TEXTURE_2D);
2251 key.texname = -1; 2436 key.texname = -1;
2252 } 2437 }
2253
2254 hv_clear (smooth);
2255 } 2438 }
2256 2439
2257 if (pl_tex.name) 2440 if (pl_tex.name)
2258 { 2441 {
2259 maptex tex = pl_tex; 2442 maptex tex = pl_tex;
2260 int px = pl_x + sdx; 2443 int px = pl_x + sdx;
2261 int py = pl_y + sdy; 2444 int py = pl_y + sdy;
2262 2445
2263 key.texname = tex.name; 2446 key.texname = tex.name;
2264 arr = rc_array (rc, &key); 2447 rc_t::array_t &arr = rc.array (key);
2265 2448
2266 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2449 arr.t2f_v3f (0 , 0 , px , py , 0);
2267 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2450 arr.t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2268 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2451 arr.t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2269 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2452 arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2270 2453
2271 rc_draw (rc); 2454 rc.draw ();
2272 } 2455 }
2273 2456
2457 rc_ov.draw ();
2458 rc_ov.clear ();
2459
2274 glDisable (GL_BLEND); 2460 glDisable (GL_BLEND);
2275 rc_free (rc);
2276 2461
2277 // top layer: overlays such as the health bar 2462 // top layer: overlays such as the health bar
2278 for (y = 0; y < sh; y++) 2463 for (y = 0; y < sh; y++)
2279 if (0 <= y + my && y + my < self->rows) 2464 if (0 <= y + my && y + my < self->rows)
2280 { 2465 {
2283 for (x = 0; x < sw; x++) 2468 for (x = 0; x < sw; x++)
2284 if (row->c0 <= x + mx && x + mx < row->c1) 2469 if (row->c0 <= x + mx && x + mx < row->c1)
2285 { 2470 {
2286 mapcell *cell = row->col + (x + mx - row->c0); 2471 mapcell *cell = row->col + (x + mx - row->c0);
2287 2472
2288 int px = x * T; 2473 int px = x * Tw;
2289 int py = y * T; 2474 int py = y * Th;
2290 2475
2291 if (expect_false (cell->player == player)) 2476 if (expect_false (cell->player == player))
2292 { 2477 {
2293 px += sdx; 2478 px += sdx;
2294 py += sdy; 2479 py += sdy;
2295 } 2480 }
2296 2481
2297 if (cell->stat_hp) 2482 if (cell->stat_hp)
2298 { 2483 {
2299 int width = cell->stat_width * T; 2484 int width = cell->stat_width * Tw;
2300 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2485 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2301 2486
2302 glColor3ub (0, 0, 0); 2487 glColor3ub (0, 0, 0);
2303 glRectf (px + 1, py - thick - 2, 2488 glRectf (px + 1, py - thick - 2,
2304 px + width - 1, py); 2489 px + width - 1, py);
2305 2490
2311 } 2496 }
2312 } 2497 }
2313} 2498}
2314 2499
2315void 2500void
2316draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data) 2501draw_magicmap (DC::Map self, int w, int h, unsigned char *data)
2317 CODE: 2502 CODE:
2318{ 2503{
2319 static float color[16][3] = { 2504 static float color[16][3] = {
2320 { 0.00F, 0.00F, 0.00F }, 2505 { 0.00f, 0.00f, 0.00f },
2321 { 1.00F, 1.00F, 1.00F }, 2506 { 1.00f, 1.00f, 1.00f },
2322 { 0.00F, 0.00F, 0.55F }, 2507 { 0.00f, 0.00f, 0.55f },
2323 { 1.00F, 0.00F, 0.00F }, 2508 { 1.00f, 0.00f, 0.00f },
2324 2509
2325 { 1.00F, 0.54F, 0.00F }, 2510 { 1.00f, 0.54f, 0.00f },
2326 { 0.11F, 0.56F, 1.00F }, 2511 { 0.11f, 0.56f, 1.00f },
2327 { 0.93F, 0.46F, 0.00F }, 2512 { 0.93f, 0.46f, 0.00f },
2328 { 0.18F, 0.54F, 0.34F }, 2513 { 0.18f, 0.54f, 0.34f },
2329 2514
2330 { 0.56F, 0.73F, 0.56F }, 2515 { 0.56f, 0.73f, 0.56f },
2331 { 0.80F, 0.80F, 0.80F }, 2516 { 0.80f, 0.80f, 0.80f },
2332 { 0.55F, 0.41F, 0.13F }, 2517 { 0.55f, 0.41f, 0.13f },
2333 { 0.99F, 0.77F, 0.26F }, 2518 { 0.99f, 0.77f, 0.26f },
2334 2519
2335 { 0.74F, 0.65F, 0.41F }, 2520 { 0.74f, 0.65f, 0.41f },
2336 2521
2337 { 0.00F, 1.00F, 1.00F }, 2522 { 0.00f, 1.00f, 1.00f },
2338 { 1.00F, 0.00F, 1.00F }, 2523 { 1.00f, 0.00f, 1.00f },
2339 { 1.00F, 1.00F, 0.00F }, 2524 { 1.00f, 1.00f, 0.00f },
2340 }; 2525 };
2341 2526
2342 int x, y; 2527 int x, y;
2343 2528
2344 glEnable (GL_TEXTURE_2D); 2529 glEnable (GL_TEXTURE_2D);
2530 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2531 * but the nvidia driver (185.18.14) mishandles alpha textures
2532 * and takes the colour from god knows where instead of using
2533 * Cp. MODULATE results in the same colour, but slightly different
2534 * alpha, but atcually gives us the correct colour with nvidia.
2535 */
2345 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2536 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2346 glEnable (GL_BLEND); 2537 glEnable (GL_BLEND);
2347 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2538 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2348 glBegin (GL_QUADS); 2539 glBegin (GL_QUADS);
2349 2540
2350 for (y = 0; y < h; y++) 2541 for (y = 0; y < h; y++)
2354 2545
2355 if (m) 2546 if (m)
2356 { 2547 {
2357 float *c = color [m & 15]; 2548 float *c = color [m & 15];
2358 2549
2359 float tx1 = m & 0x40 ? 0.5 : 0.; 2550 float tx1 = m & 0x40 ? 0.5f : 0.f;
2360 float tx2 = tx1 + 0.5; 2551 float tx2 = tx1 + 0.5f;
2361 2552
2362 glColor4f (c[0], c[1], c[2], 0.75); 2553 glColor4f (c[0], c[1], c[2], 1);
2363 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2554 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2364 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2555 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2365 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2556 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2366 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2557 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2367 } 2558 }
2375void 2566void
2376fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2567fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2377 PPCODE: 2568 PPCODE:
2378{ 2569{
2379 int x, y; 2570 int x, y;
2380 int sw1 = sw + 2; 2571 int sw1 = sw + 2;
2381 int sh1 = sh + 2; 2572 int sh1 = sh + 2;
2382 int sh3 = sh * 3; 2573 int sh3 = sh * 3;
2383 int sw34 = (sw * 3 + 3) & ~3; 2574 int sw3 = sw * 3;
2575 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2576 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2384 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2577 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2385 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2578 memset (darkness1, 0, sw1*sh1);
2386 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2387 2579
2388 SvPOK_only (darkness3_sv); 2580 SvPOK_only (darkness3_sv);
2389 SvCUR_set (darkness3_sv, sw34 * sh3); 2581 SvCUR_set (darkness3_sv, sw3 * sh3);
2390 2582
2391 mx += self->x - 1; 2583 mx += self->x - 1;
2392 my += self->y - 1; 2584 my += self->y - 1;
2393
2394 memset (darkness1, 255 - FOW_DARKNESS, sw1 * sh1);
2395 2585
2396 for (y = 0; y < sh1; y++) 2586 for (y = 0; y < sh1; y++)
2397 if (0 <= y + my && y + my < self->rows) 2587 if (0 <= y + my && y + my < self->rows)
2398 { 2588 {
2399 maprow *row = self->row + (y + my); 2589 maprow *row = self->row + (y + my);
2402 if (row->c0 <= x + mx && x + mx < row->c1) 2592 if (row->c0 <= x + mx && x + mx < row->c1)
2403 { 2593 {
2404 mapcell *cell = row->col + (x + mx - row->c0); 2594 mapcell *cell = row->col + (x + mx - row->c0);
2405 2595
2406 darkness1 [y * sw1 + x] = cell->darkness 2596 darkness1 [y * sw1 + x] = cell->darkness
2407 ? 255 - (cell->darkness - 1) 2597 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2408 : 255 - FOW_DARKNESS; 2598 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2409 } 2599 }
2410 } 2600 }
2411 2601
2412 for (y = 0; y < sh; ++y) 2602 for (y = 0; y < sh; ++y)
2413 for (x = 0; x < sw; ++x) 2603 for (x = 0; x < sw; ++x)
2432 2622
2433 uint8_t r13 = (d13 + d23 + d12) / 3; 2623 uint8_t r13 = (d13 + d23 + d12) / 3;
2434 uint8_t r23 = d23; 2624 uint8_t r23 = d23;
2435 uint8_t r33 = (d23 + d33 + d32) / 3; 2625 uint8_t r33 = (d23 + d33 + d32) / 3;
2436 2626
2437 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2627 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2438 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2628 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2439 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2629 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2440 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2630 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2441 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2631 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2442 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2632 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2443 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2633 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2444 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2634 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2445 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2635 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2446 } 2636 }
2447 2637
2448 free (darkness1); 2638 free (darkness1);
2449 2639
2450 EXTEND (SP, 3); 2640 EXTEND (SP, 3);
2451 PUSHs (sv_2mortal (newSViv (sw34))); 2641 PUSHs (sv_2mortal (newSViv (sw3)));
2452 PUSHs (sv_2mortal (newSViv (sh3))); 2642 PUSHs (sv_2mortal (newSViv (sh3)));
2453 PUSHs (darkness3_sv); 2643 PUSHs (darkness3_sv);
2454} 2644}
2455 2645
2456SV * 2646SV *
2519 else 2709 else
2520 *data++ = 0; 2710 *data++ = 0;
2521 } 2711 }
2522 } 2712 }
2523 2713
2524 /* if size is w*h + 5 then no data has been found */ 2714 /* if size is w*h + 5 then no data has been found */
2525 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2715 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2526 { 2716 {
2527 SvPOK_only (data_sv); 2717 SvPOK_only (data_sv);
2528 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2718 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2529 } 2719 }
2530 2720
2531 RETVAL = data_sv; 2721 RETVAL = data_sv;
2532} 2722}
2533 OUTPUT: 2723 OUTPUT:
2534 RETVAL 2724 RETVAL
2535 2725
2536void 2726void
2543 STRLEN len; 2733 STRLEN len;
2544 uint8_t *data, *end; 2734 uint8_t *data, *end;
2545 2735
2546 len = SvLEN (data_sv); 2736 len = SvLEN (data_sv);
2547 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2737 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2548 data = SvPVbyte_nolen (data_sv); 2738 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2549 end = data + len + 8; 2739 end = data + len + 8;
2550 2740
2551 if (len < 5) 2741 if (len < 5)
2552 XSRETURN_EMPTY; 2742 XSRETURN_EMPTY;
2553 2743
2597 2787
2598 for (z = 0; z <= 2; z++) 2788 for (z = 0; z <= 2; z++)
2599 { 2789 {
2600 tileid t = tile [z]; 2790 tileid t = tile [z];
2601 2791
2602 if (t >= self->texs || (t && !self->tex [t].name)) 2792 if (t >= self->tex.size () || (t && !self->tex[t].name))
2603 { 2793 {
2604 PUSHs (sv_2mortal (newSViv (t))); 2794 PUSHs (sv_2mortal (newSViv (t)));
2605 need_texid (self, t); 2795 if (self->tex.size () <= t) self->tex.resize (t + 1);
2606 } 2796 }
2607 2797
2608 cell->tile [z] = t; 2798 cell->tile[z] = t;
2609 } 2799 }
2610 } 2800 }
2611 } 2801 }
2612 } 2802 }
2613 } 2803 }
2614} 2804}
2615 2805
2616MODULE = Deliantra::Client PACKAGE = DC::RW 2806MODULE = Deliantra::Client PACKAGE = DC::RW
2617 2807
2618DC::RW 2808DC::RW
2619new (SV *class, SV *data_sv) 2809new (SV *klass, SV *data_sv)
2620 CODE: 2810 CODE:
2621{ 2811{
2622 STRLEN datalen; 2812 STRLEN datalen;
2623 char *data = SvPVbyte (data_sv, datalen); 2813 char *data = SvPVbyte (data_sv, datalen);
2624 2814
2626} 2816}
2627 OUTPUT: 2817 OUTPUT:
2628 RETVAL 2818 RETVAL
2629 2819
2630DC::RW 2820DC::RW
2631new_from_file (SV *class, const char *path, const char *mode = "rb") 2821new_from_file (SV *klass, const char *path, const char *mode = "rb")
2632 CODE: 2822 CODE:
2633 RETVAL = SDL_RWFromFile (path, mode); 2823 RETVAL = SDL_RWFromFile (path, mode);
2634 OUTPUT: 2824 OUTPUT:
2635 RETVAL 2825 RETVAL
2636 2826
2654 if (RETVAL < 0) 2844 if (RETVAL < 0)
2655 { 2845 {
2656 RETVAL = Mix_GroupOldest (-1); 2846 RETVAL = Mix_GroupOldest (-1);
2657 2847
2658 if (RETVAL < 0) 2848 if (RETVAL < 0)
2849 {
2850 // happens sometimes, maybe it just stopped playing(?)
2851 RETVAL = Mix_GroupAvailable (-1);
2852
2853 if (RETVAL < 0)
2659 XSRETURN_UNDEF; 2854 XSRETURN_UNDEF;
2660 2855 }
2856 else
2661 Mix_HaltChannel (RETVAL); 2857 Mix_HaltChannel (RETVAL);
2662 } 2858 }
2663 2859
2664 Mix_UnregisterAllEffects (RETVAL); 2860 Mix_UnregisterAllEffects (RETVAL);
2665 Mix_Volume (RETVAL, 128); 2861 Mix_Volume (RETVAL, 128);
2666} 2862}
2713void 2909void
2714set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2910set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2715 CODE: 2911 CODE:
2716{ 2912{
2717 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance)); 2913 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2718 int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI); 2914 int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
2719 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2915 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2720} 2916}
2721 2917
2722void 2918void
2723set_reverse_stereo (DC::Channel self, int flip) 2919set_reverse_stereo (DC::Channel self, int flip)
2726 2922
2727MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2923MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2728 2924
2729PROTOTYPES: DISABLE 2925PROTOTYPES: DISABLE
2730 2926
2927void
2928decoders ()
2929 PPCODE:
2930#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2931 int i, num = Mix_GetNumChunkDecoders ();
2932 EXTEND (SP, num);
2933 for (i = 0; i < num; ++i)
2934 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2935#else
2936 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2937#endif
2938
2731DC::MixChunk 2939DC::MixChunk
2732new (SV *class, DC::RW rwops) 2940new (SV *klass, DC::RW rwops)
2733 CODE: 2941 CODE:
2734 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2942 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2735 OUTPUT: 2943 OUTPUT:
2736 RETVAL 2944 RETVAL
2737 2945
2767 OUTPUT: 2975 OUTPUT:
2768 RETVAL 2976 RETVAL
2769 2977
2770MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2978MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2771 2979
2980void
2981decoders ()
2982 PPCODE:
2983#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2984 int i, num = Mix_GetNumMusicDecoders ();
2985 EXTEND (SP, num);
2986 for (i = 0; i < num; ++i)
2987 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
2988#else
2989 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2990#endif
2991
2772int 2992int
2773volume (int volume = -1) 2993volume (int volume = -1)
2774 PROTOTYPE: ;$ 2994 PROTOTYPE: ;$
2775 CODE: 2995 CODE:
2776 if (items > 0) 2996 if (items > 0)
2787void 3007void
2788halt () 3008halt ()
2789 CODE: 3009 CODE:
2790 Mix_HaltMusic (); 3010 Mix_HaltMusic ();
2791 3011
3012int
3013playing ()
3014 CODE:
3015 RETVAL = Mix_PlayingMusic ();
3016 OUTPUT:
3017 RETVAL
3018
2792DC::MixMusic 3019DC::MixMusic
2793new (SV *class, DC::RW rwops) 3020new (SV *klass, DC::RW rwops)
2794 CODE: 3021 CODE:
2795 RETVAL = Mix_LoadMUS_RW (rwops); 3022 RETVAL = Mix_LoadMUS_RW (rwops);
2796 OUTPUT: 3023 OUTPUT:
2797 RETVAL 3024 RETVAL
2798 3025
2826 } *civ, const_iv[] = { 3053 } *civ, const_iv[] = {
2827# define const_iv(name) { # name, (IV)name } 3054# define const_iv(name) { # name, (IV)name }
2828 const_iv (GL_VENDOR), 3055 const_iv (GL_VENDOR),
2829 const_iv (GL_VERSION), 3056 const_iv (GL_VERSION),
2830 const_iv (GL_EXTENSIONS), 3057 const_iv (GL_EXTENSIONS),
3058 const_iv (GL_MAX_TEXTURE_UNITS),
2831 const_iv (GL_COLOR_MATERIAL), 3059 const_iv (GL_COLOR_MATERIAL),
2832 const_iv (GL_SMOOTH), 3060 const_iv (GL_SMOOTH),
2833 const_iv (GL_FLAT), 3061 const_iv (GL_FLAT),
2834 const_iv (GL_DITHER), 3062 const_iv (GL_DITHER),
2835 const_iv (GL_BLEND), 3063 const_iv (GL_BLEND),
2847 const_iv (GL_ZERO), 3075 const_iv (GL_ZERO),
2848 const_iv (GL_SRC_ALPHA), 3076 const_iv (GL_SRC_ALPHA),
2849 const_iv (GL_DST_ALPHA), 3077 const_iv (GL_DST_ALPHA),
2850 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3078 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2851 const_iv (GL_ONE_MINUS_DST_ALPHA), 3079 const_iv (GL_ONE_MINUS_DST_ALPHA),
3080 const_iv (GL_SRC_COLOR),
3081 const_iv (GL_DST_COLOR),
3082 const_iv (GL_ONE_MINUS_SRC_COLOR),
3083 const_iv (GL_ONE_MINUS_DST_COLOR),
2852 const_iv (GL_SRC_ALPHA_SATURATE), 3084 const_iv (GL_SRC_ALPHA_SATURATE),
2853 const_iv (GL_RGB), 3085 const_iv (GL_RGB),
2854 const_iv (GL_RGBA), 3086 const_iv (GL_RGBA),
2855 const_iv (GL_RGBA4), 3087 const_iv (GL_RGBA4),
2856 const_iv (GL_RGBA8), 3088 const_iv (GL_RGBA8),
2924 const_iv (GL_NICEST), 3156 const_iv (GL_NICEST),
2925 const_iv (GL_V2F), 3157 const_iv (GL_V2F),
2926 const_iv (GL_V3F), 3158 const_iv (GL_V3F),
2927 const_iv (GL_T2F_V3F), 3159 const_iv (GL_T2F_V3F),
2928 const_iv (GL_T2F_N3F_V3F), 3160 const_iv (GL_T2F_N3F_V3F),
3161 const_iv (GL_FUNC_ADD),
3162 const_iv (GL_FUNC_SUBTRACT),
3163 const_iv (GL_FUNC_REVERSE_SUBTRACT),
2929# undef const_iv 3164# undef const_iv
2930 }; 3165 };
2931 3166
2932 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3167 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
2933 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3168 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2934 3169
2935 texture_av = newAV (); 3170 texture_av = newAV ();
2936 AvREAL_off (texture_av); 3171 AvREAL_off (texture_av);
2937} 3172}
2938 3173
2940disable_GL_EXT_blend_func_separate () 3175disable_GL_EXT_blend_func_separate ()
2941 CODE: 3176 CODE:
2942 gl.BlendFuncSeparate = 0; 3177 gl.BlendFuncSeparate = 0;
2943 gl.BlendFuncSeparateEXT = 0; 3178 gl.BlendFuncSeparateEXT = 0;
2944 3179
2945char * 3180void
3181apple_nvidia_bug (int enable)
3182
3183const char *
2946gl_vendor () 3184gl_vendor ()
2947 CODE: 3185 CODE:
2948 RETVAL = (char *)glGetString (GL_VENDOR); 3186 RETVAL = (const char *)glGetString (GL_VENDOR);
2949 OUTPUT: 3187 OUTPUT:
2950 RETVAL 3188 RETVAL
2951 3189
2952char * 3190const char *
2953gl_version () 3191gl_version ()
2954 CODE: 3192 CODE:
2955 RETVAL = (char *)glGetString (GL_VERSION); 3193 RETVAL = (const char *)glGetString (GL_VERSION);
2956 OUTPUT: 3194 OUTPUT:
2957 RETVAL 3195 RETVAL
2958 3196
2959char * 3197const char *
2960gl_extensions () 3198gl_extensions ()
2961 CODE: 3199 CODE:
2962 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3200 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2963 OUTPUT: 3201 OUTPUT:
2964 RETVAL 3202 RETVAL
2965 3203
2966const char *glGetString (GLenum pname) 3204const char *glGetString (GLenum pname)
3205 CODE:
3206 RETVAL = (const char *)glGetString (pname);
3207 OUTPUT:
3208 RETVAL
2967 3209
2968GLint glGetInteger (GLenum pname) 3210GLint glGetInteger (GLenum pname)
2969 CODE: 3211 CODE:
2970 glGetIntegerv (pname, &RETVAL); 3212 glGetIntegerv (pname, &RETVAL);
2971 OUTPUT: 3213 OUTPUT:
2979 3221
2980int glGetError () 3222int glGetError ()
2981 3223
2982void glFinish () 3224void glFinish ()
2983 3225
3226void glFlush ()
3227
2984void glClear (int mask) 3228void glClear (int mask)
2985 3229
2986void glClearColor (float r, float g, float b, float a = 1.0) 3230void glClearColor (float r, float g, float b, float a = 1.0)
2987 PROTOTYPE: @ 3231 PROTOTYPE: @
2988 3232
2997void glBlendFunc (int sfactor, int dfactor) 3241void glBlendFunc (int sfactor, int dfactor)
2998 3242
2999void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3243void glBlendFuncSeparate (int sa, int da, int saa, int daa)
3000 CODE: 3244 CODE:
3001 gl_BlendFuncSeparate (sa, da, saa, daa); 3245 gl_BlendFuncSeparate (sa, da, saa, daa);
3246
3247# void glBlendEquation (int se)
3002 3248
3003void glDepthMask (int flag) 3249void glDepthMask (int flag)
3004 3250
3005void glLogicOp (int opcode) 3251void glLogicOp (int opcode)
3006 3252
3157 3403
3158void glEndList () 3404void glEndList ()
3159 3405
3160void glCallList (int list) 3406void glCallList (int list)
3161 3407
3408void c_init ()
3409 CODE:
3410 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3411 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3412
3162MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3413MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3163 3414
3164PROTOTYPES: DISABLE 3415PROTOTYPES: DISABLE
3165 3416
3166void 3417void
3167find_widget (SV *self, NV x, NV y) 3418find_widget (SV *self, NV x, NV y)
3168 PPCODE: 3419 PPCODE:
3169{ 3420{
3170 if (within_widget (self, x, y)) 3421 if (within_widget (self, x, y))
3171 XPUSHs (self); 3422 XPUSHs (self);
3172} 3423}
3173 3424
3174BOOT: 3425BOOT:
3175{ 3426{
3183 3434
3184void 3435void
3185draw (SV *self) 3436draw (SV *self)
3186 CODE: 3437 CODE:
3187{ 3438{
3188 HV *hv; 3439 HV *hv;
3189 SV **svp; 3440 SV **svp;
3190 NV x, y, w, h; 3441 NV x, y, w, h;
3191 SV *draw_x_sv = GvSV (draw_x_gv); 3442 SV *draw_x_sv = GvSV (draw_x_gv);
3192 SV *draw_y_sv = GvSV (draw_y_gv); 3443 SV *draw_y_sv = GvSV (draw_y_gv);
3193 SV *draw_w_sv = GvSV (draw_w_gv); 3444 SV *draw_w_sv = GvSV (draw_w_gv);
3194 SV *draw_h_sv = GvSV (draw_h_gv); 3445 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines