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.167 by root, Sat Dec 9 02:21:25 2006 UTC vs.
Revision 1.211 by root, Sat Jul 28 00:45:28 2007 UTC

1#ifdef _WIN32 1#ifdef _WIN32
2# define WIN32_LEAN_AND_MEAN 2# define WIN32_LEAN_AND_MEAN
3# define _WIN32_WINNT 0x0500 // needed to get win2000 api calls 3# define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
4# include <malloc.h> 4# include <malloc.h>
5# include <windows.h> 5# include <windows.h>
6# include <wininet.h> 6# include <wininet.h>
7# pragma warning(disable:4244) 7# pragma warning(disable:4244)
8# pragma warning(disable:4761) 8# pragma warning(disable:4761)
9#endif 9#endif
10 10
11//#define DEBUG 1
12#if DEBUG
13# include <valgrind/memcheck.h>
14#endif
15
11#include "EXTERN.h" 16#include "EXTERN.h"
12#include "perl.h" 17#include "perl.h"
13#include "XSUB.h" 18#include "XSUB.h"
14 19
15#ifdef _WIN32 20#ifdef _WIN32
16# undef pipe 21# undef pipe
17#endif 22#endif
18 23
24#include <assert.h>
19#include <math.h> 25#include <math.h>
20#include <string.h> 26#include <string.h>
21#include <stdio.h> 27#include <stdio.h>
22#include <stdlib.h> 28#include <stdlib.h>
23 29
24#include <SDL.h> 30#include <SDL.h>
31#include <SDL_thread.h>
25#include <SDL_endian.h> 32#include <SDL_endian.h>
26#include <SDL_image.h> 33#include <SDL_image.h>
27#include <SDL_mixer.h> 34#include <SDL_mixer.h>
28#include <SDL_opengl.h> 35#include <SDL_opengl.h>
29 36
55# define PARACHUTE SDL_INIT_NOPARACHUTE 62# define PARACHUTE SDL_INIT_NOPARACHUTE
56#else 63#else
57# define PARACHUTE 0 64# define PARACHUTE 0
58#endif 65#endif
59 66
67static AV *texture_av;
68
60static struct 69static struct
61{ 70{
62#define GL_FUNC(ptr,name) ptr name; 71#define GL_FUNC(ptr,name) ptr name;
63#include "glfunc.h" 72#include "glfunc.h"
64#undef GL_FUNC 73#undef GL_FUNC
65} gl; 74} gl;
66 75
76static void
67static void gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa) 77gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
68{ 78{
69 if (gl.BlendFuncSeparate) 79 if (gl.BlendFuncSeparate)
70 gl.BlendFuncSeparate (sa, da, saa, daa); 80 gl.BlendFuncSeparate (sa, da, saa, daa);
71 else if (gl.BlendFuncSeparateEXT) 81 else if (gl.BlendFuncSeparateEXT)
72 gl.BlendFuncSeparateEXT (sa, da, saa, daa); 82 gl.BlendFuncSeparateEXT (sa, da, saa, daa);
73 else 83 else
74 glBlendFunc (sa, da); 84 glBlendFunc (sa, da);
75} 85}
76 86
87static GLuint
88gen_texture ()
89{
90 GLuint name;
91
92 if (AvFILL (texture_av) >= 0)
93 name = (GLuint)(size_t)av_pop (texture_av);
94 else
95 glGenTextures (1, &name);
96
97 return name;
98}
99
100static void
101del_texture (GLuint name)
102{
103 /* make a half-assed attempt at returning the memory used by the texture */
104 /* textures are frequently being reused by cfplus anyway */
105 /*glBindTexture (GL_TEXTURE_2D, name);*/
106 /*glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);*/
107 av_push (texture_av, (SV *)(size_t)name);
108 glDeleteTextures (1, &name);
109}
110
77#include "texcache.c" 111#include "texcache.c"
78 112
79#include "pango-font.c" 113#include "pango-font.c"
80#include "pango-fontmap.c" 114#include "pango-fontmap.c"
81#include "pango-render.c" 115#include "pango-render.c"
154 188
155 *w = rect.width; 189 *w = rect.width;
156 *h = rect.height; 190 *h = rect.height;
157} 191}
158 192
193typedef uint16_t tileid;
159typedef uint16_t mapface; 194typedef uint16_t faceid;
160 195
161typedef struct { 196typedef struct {
162 GLint name; 197 int name;
163 int w, h; 198 int w, h;
164 float s, t; 199 float s, t;
165 uint8_t r, g, b, a; 200 uint8_t r, g, b, a;
201 tileid smoothtile;
202 uint8_t smoothlevel;
166} maptex; 203} maptex;
167 204
168typedef struct { 205typedef struct {
169 uint32_t player; 206 uint32_t player;
170 mapface face[3]; 207 tileid tile[3];
171 uint16_t darkness; 208 uint16_t darkness;
172 uint8_t stat_width, stat_hp, flags; 209 uint8_t stat_width, stat_hp, flags, smoothmax;
173} mapcell; 210} mapcell;
174 211
175typedef struct { 212typedef struct {
176 int32_t c0, c1; 213 int32_t c0, c1;
177 mapcell *col; 214 mapcell *col;
178} maprow; 215} maprow;
179 216
180typedef struct map { 217typedef struct map {
181 int x, y, w, h; 218 int x, y, w, h;
182 int ox, oy; /* offset to virtual global coordinate system */ 219 int ox, oy; /* offset to virtual global coordinate system */
183 int faces; 220 int faces; tileid *face2tile; // [faceid]
184 mapface *face; 221 int texs; maptex *tex; // [tileid]
185
186 int texs;
187 maptex *tex;
188 222
189 int32_t rows; 223 int32_t rows;
190 maprow *row; 224 maprow *row;
191} *CFPlus__Map; 225} *CFPlus__Map;
192 226
212 return ptr; 246 return ptr;
213} 247}
214 248
215#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 249#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
216#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 250#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
251
252static void
253need_facenum (struct map *self, faceid face)
254{
255 while (self->faces <= face)
256 {
257 Append (tileid, self->face2tile, self->faces, self->faces);
258 self->faces *= 2;
259 }
260}
261
262static void
263need_texid (struct map *self, int texid)
264{
265 while (self->texs <= texid)
266 {
267 Append (maptex, self->tex, self->texs, self->texs);
268 self->texs *= 2;
269 }
270}
217 271
218static maprow * 272static maprow *
219map_get_row (CFPlus__Map self, int y) 273map_get_row (CFPlus__Map self, int y)
220{ 274{
221 if (0 > y) 275 if (0 > y)
316 cell->player = 0; 370 cell->player = 0;
317 } 371 }
318 } 372 }
319} 373}
320 374
375typedef struct {
376 tileid tile;
377 uint8_t x, y, level;
378} smooth_key;
379
380static void
381smooth_or_bits (HV *hv, smooth_key *key, IV bits)
382{
383 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1);
384
385 if (SvIOK (*sv))
386 SvIV_set (*sv, SvIVX (*sv) | bits);
387 else
388 sv_setiv (*sv, bits);
389}
390
321static void 391static void
322music_finished (void) 392music_finished (void)
323{ 393{
324 SDL_UserEvent ev; 394 SDL_UserEvent ev;
325 395
362} 432}
363 433
364/* SDL should provide this, really. */ 434/* SDL should provide this, really. */
365#define SDLK_MODIFIER_MIN 300 435#define SDLK_MODIFIER_MIN 300
366#define SDLK_MODIFIER_MAX 314 436#define SDLK_MODIFIER_MAX 314
437
438/******************************************************************************/
439
440static GV *draw_x_gv, *draw_y_gv, *draw_w_gv, *draw_h_gv;
441static GV *hover_gv;
442
443static int
444within_widget (SV *widget, NV x, NV y)
445{
446 HV *self;
447 SV **svp;
448 NV wx, ww, wy, wh;
449
450 if (!SvROK (widget))
451 return 0;
452
453 self = (HV *)SvRV (widget);
454
455 if (SvTYPE (self) != SVt_PVHV)
456 return 0;
457
458 svp = hv_fetch (self, "y", 1, 0); wy = svp ? SvNV (*svp) : 0.;
459 if (y < wy)
460 return 0;
461
462 svp = hv_fetch (self, "h", 1, 0); wh = svp ? SvNV (*svp) : 0.;
463 if (y >= wy + wh)
464 return 0;
465
466 svp = hv_fetch (self, "x", 1, 0); wx = svp ? SvNV (*svp) : 0.;
467 if (x < wx)
468 return 0;
469
470 svp = hv_fetch (self, "w", 1, 0); ww = svp ? SvNV (*svp) : 0.;
471 if (x >= wx + ww)
472 return 0;
473
474 svp = hv_fetch (self, "can_events", sizeof ("can_events") - 1, 0);
475 if (!svp || !SvTRUE (*svp))
476 return 0;
477
478 return 1;
479}
367 480
368MODULE = CFPlus PACKAGE = CFPlus 481MODULE = CFPlus PACKAGE = CFPlus
369 482
370PROTOTYPES: ENABLE 483PROTOTYPES: ENABLE
371 484
492 605
493 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 606 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
494 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 607 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
495} 608}
496 609
610void
611weaken (SV *rv)
612 PROTOTYPE: $
613 CODE:
614 sv_rvweaken (rv);
615
497int 616int
498in_destruct () 617in_destruct ()
499 CODE: 618 CODE:
500 RETVAL = PL_main_cv == Nullcv; 619 RETVAL = PL_main_cv == Nullcv;
501 OUTPUT: 620 OUTPUT:
512 opengl_fontmap = pango_opengl_font_map_new (); 631 opengl_fontmap = pango_opengl_font_map_new ();
513 pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0); 632 pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
514 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap); 633 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
515} 634}
516 635
636char *
637SDL_GetError ()
638
517int 639int
518SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE) 640SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
519 641
520void 642void
521SDL_Quit () 643SDL_Quit ()
522 644
523void 645void
524SDL_ListModes () 646SDL_ListModes (int rgb, int alpha)
525 PPCODE: 647 PPCODE:
526{ 648{
527 SDL_Rect **m; 649 SDL_Rect **m;
528 650
529 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); 651 SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
530 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5); 652 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
531 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); 653 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
532 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1); 654 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
533 655
534 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15); 656 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
535 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0); 657 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE , 0);
536 658
537 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0); 659 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE , 0);
538 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0); 660 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
539 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0); 661 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
540 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0); 662 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
541 663
542 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); 664 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
543#if SDL_VERSION_ATLEAST(1,2,10) 665#if SDL_VERSION_ATLEAST(1,2,10)
544 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1); 666 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
545 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); 667 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
546#endif 668#endif
547 669
548 SDL_EnableUNICODE (1);
549 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
550
551 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL); 670 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
552 671
553 if (m && m != (SDL_Rect **)-1) 672 if (m && m != (SDL_Rect **)-1)
554 while (*m) 673 while (*m)
555 { 674 {
675 if ((*m)->w >= 640 && (*m)->h >= 480)
676 {
556 AV *av = newAV (); 677 AV *av = newAV ();
557 av_push (av, newSViv ((*m)->w)); 678 av_push (av, newSViv ((*m)->w));
558 av_push (av, newSViv ((*m)->h)); 679 av_push (av, newSViv ((*m)->h));
680 av_push (av, newSViv (rgb));
681 av_push (av, newSViv (alpha));
559 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av))); 682 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
683 }
560 684
561 ++m; 685 ++m;
562 } 686 }
563} 687}
564 688
565char *
566SDL_GetError ()
567
568int 689int
569SDL_SetVideoMode (int w, int h, int fullscreen) 690SDL_SetVideoMode (int w, int h, int rgb, int alpha, int fullscreen)
570 CODE: 691 CODE:
692{
693 SDL_EnableUNICODE (1);
694 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
695
696 SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
697 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
698 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
699 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
700
571 RETVAL = !!SDL_SetVideoMode ( 701 RETVAL = !!SDL_SetVideoMode (
572 w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0) 702 w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
573 ); 703 );
704
574 if (RETVAL) 705 if (RETVAL)
575 { 706 {
707 av_clear (texture_av);
708
576 SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+"); 709 SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
577# define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 710#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
578# include "glfunc.h" 711#include "glfunc.h"
579# undef GL_FUNC 712#undef GL_FUNC
580 } 713 }
714}
581 OUTPUT: 715 OUTPUT:
582 RETVAL 716 RETVAL
583 717
584void 718void
585SDL_GL_SwapBuffers () 719SDL_GL_SwapBuffers ()
586 720
587char * 721char *
588SDL_GetKeyName (int sym) 722SDL_GetKeyName (int sym)
589 723
724int
725SDL_GetAppState ()
726
590void 727void
591SDL_PollEvent () 728poll_events ()
592 PPCODE: 729 PPCODE:
593{ 730{
594 SDL_Event ev; 731 SDL_Event ev;
595 732
596 while (SDL_PollEvent (&ev)) 733 SDL_PumpEvents ();
734 while (SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0)
597 { 735 {
598 HV *hv = newHV (); 736 HV *hv = newHV ();
599 hv_store (hv, "type", 4, newSViv (ev.type), 0); 737 hv_store (hv, "type", 4, newSViv (ev.type), 0);
600 738
601 switch (ev.type) 739 switch (ev.type)
613 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0); 751 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
614 hv_store (hv, "state", 5, newSViv (ev.active.state), 0); 752 hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
615 break; 753 break;
616 754
617 case SDL_MOUSEMOTION: 755 case SDL_MOUSEMOTION:
756 {
757 int state = ev.motion.state;
758 int x = ev.motion.x;
759 int y = ev.motion.y;
760 int xrel = ev.motion.xrel;
761 int yrel = ev.motion.yrel;
762
763 /* do simplistic event compression */
764 while (SDL_PeepEvents (&ev, 1, SDL_PEEKEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0
765 && state == ev.motion.state)
766 {
767 xrel += ev.motion.xrel;
768 yrel += ev.motion.yrel;
769 x = ev.motion.x;
770 y = ev.motion.y;
771 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
772 }
773
618 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0); 774 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
619
620 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0); 775 hv_store (hv, "state", 5, newSViv (state), 0);
621 hv_store (hv, "x", 1, newSViv (ev.motion.x), 0); 776 hv_store (hv, "x", 1, newSViv (x), 0);
622 hv_store (hv, "y", 1, newSViv (ev.motion.y), 0); 777 hv_store (hv, "y", 1, newSViv (y), 0);
623 hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0); 778 hv_store (hv, "xrel", 4, newSViv (xrel), 0);
624 hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0); 779 hv_store (hv, "yrel", 4, newSViv (yrel), 0);
780 }
625 break; 781 break;
626 782
627 case SDL_MOUSEBUTTONDOWN: 783 case SDL_MOUSEBUTTONDOWN:
628 case SDL_MOUSEBUTTONUP: 784 case SDL_MOUSEBUTTONUP:
629 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0); 785 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
644 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1)))); 800 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
645 } 801 }
646} 802}
647 803
648int 804int
649Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048) 805Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
650 POSTCALL: 806 POSTCALL:
651 Mix_HookMusicFinished (music_finished); 807 Mix_HookMusicFinished (music_finished);
652 Mix_ChannelFinished (channel_finished); 808 Mix_ChannelFinished (channel_finished);
653 809
654void 810void
658Mix_AllocateChannels (int numchans = -1) 814Mix_AllocateChannels (int numchans = -1)
659 815
660void 816void
661lowdelay (int fd, int val = 1) 817lowdelay (int fd, int val = 1)
662 CODE: 818 CODE:
663#ifndef _WIN32
664 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val)); 819 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
665#endif
666 820
667void 821void
668win32_proxy_info () 822win32_proxy_info ()
669 PPCODE: 823 PPCODE:
670{ 824{
811 ExitThread (retval); // unclean, please beam me up 965 ExitThread (retval); // unclean, please beam me up
812#else 966#else
813 _exit (retval); 967 _exit (retval);
814#endif 968#endif
815 969
970void
971debug ()
972 CODE:
973{
974#if DEBUG
975 VALGRIND_DO_LEAK_CHECK;
976#endif
977}
978
816MODULE = CFPlus PACKAGE = CFPlus::Font 979MODULE = CFPlus PACKAGE = CFPlus::Font
980
981PROTOTYPES: DISABLE
817 982
818CFPlus::Font 983CFPlus::Font
819new_from_file (SV *class, char *path, int id = 0) 984new_from_file (SV *class, char *path, int id = 0)
820 CODE: 985 CODE:
821{ 986{
832 CODE: 997 CODE:
833 pango_font_description_free (self); 998 pango_font_description_free (self);
834 999
835void 1000void
836make_default (CFPlus::Font self) 1001make_default (CFPlus::Font self)
1002 PROTOTYPE: $
837 CODE: 1003 CODE:
838 default_font = self; 1004 default_font = self;
839 1005
840MODULE = CFPlus PACKAGE = CFPlus::Layout 1006MODULE = CFPlus PACKAGE = CFPlus::Layout
841 1007
1008PROTOTYPES: DISABLE
1009
842void 1010void
843reset_glyph_cache () 1011reset_glyph_cache ()
1012 PROTOTYPE:
844 CODE: 1013 CODE:
845 tc_clear (); 1014 tc_clear ();
846 1015
847CFPlus::Layout 1016CFPlus::Layout
848new (SV *class) 1017new (SV *class)
1135 flags 1304 flags
1136 ); 1305 );
1137 1306
1138MODULE = CFPlus PACKAGE = CFPlus::Texture 1307MODULE = CFPlus PACKAGE = CFPlus::Texture
1139 1308
1140void 1309PROTOTYPES: ENABLE
1141pad2pot (SV *data_, SV *w_, SV *h_)
1142 CODE:
1143{
1144 int ow = SvIV (w_);
1145 int oh = SvIV (h_);
1146 1310
1147 if (ow && oh) 1311int minpot (int n)
1312
1313void
1314pad (SV *data_, int ow, int oh, int nw, int nh)
1315 CODE:
1316{
1317 if ((nw != ow || nh != oh) && SvOK (data_))
1148 { 1318 {
1149 int nw = minpot (ow);
1150 int nh = minpot (oh);
1151
1152 if (nw != ow || nh != oh)
1153 {
1154 if (SvOK (data_))
1155 {
1156 STRLEN datalen; 1319 STRLEN datalen;
1157 char *data = SvPVbyte (data_, datalen); 1320 char *data = SvPVbyte (data_, datalen);
1158 int bpp = datalen / (ow * oh); 1321 int bpp = datalen / (ow * oh);
1159 SV *result_ = sv_2mortal (newSV (nw * nh * bpp)); 1322 SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1160 1323
1161 SvPOK_only (result_); 1324 SvPOK_only (result_);
1162 SvCUR_set (result_, nw * nh * bpp); 1325 SvCUR_set (result_, nw * nh * bpp);
1163 1326
1164 memset (SvPVX (result_), 0, nw * nh * bpp); 1327 memset (SvPVX (result_), 0, nw * nh * bpp);
1165 while (oh--) 1328 while (oh--)
1166 memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp); 1329 memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1167 1330
1168 sv_setsv (data_, result_); 1331 sv_setsv (data_, result_);
1169 }
1170
1171 sv_setiv (w_, nw);
1172 sv_setiv (h_, nh);
1173 }
1174 } 1332 }
1175} 1333}
1176 1334
1177void 1335void
1178draw_quad (SV *self, float x, float y, float w = 0., float h = 0.) 1336draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1221 glDisable (GL_ALPHA_TEST); 1379 glDisable (GL_ALPHA_TEST);
1222 glDisable (GL_BLEND); 1380 glDisable (GL_BLEND);
1223 } 1381 }
1224} 1382}
1225 1383
1384IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1385 CODE:
1386{
1387 GLint width;
1388 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1389 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
1390 RETVAL = width > 0;
1391}
1392 OUTPUT:
1393 RETVAL
1394
1226MODULE = CFPlus PACKAGE = CFPlus::Map 1395MODULE = CFPlus PACKAGE = CFPlus::Map
1396
1397PROTOTYPES: DISABLE
1227 1398
1228CFPlus::Map 1399CFPlus::Map
1229new (SV *class) 1400new (SV *class)
1230 CODE: 1401 CODE:
1231 New (0, RETVAL, 1, struct map); 1402 New (0, RETVAL, 1, struct map);
1233 RETVAL->y = 0; 1404 RETVAL->y = 0;
1234 RETVAL->w = 0; 1405 RETVAL->w = 0;
1235 RETVAL->h = 0; 1406 RETVAL->h = 0;
1236 RETVAL->ox = 0; 1407 RETVAL->ox = 0;
1237 RETVAL->oy = 0; 1408 RETVAL->oy = 0;
1238 RETVAL->faces = 8192; 1409 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1239 Newz (0, RETVAL->face, RETVAL->faces, mapface); 1410 RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1240 RETVAL->texs = 8192;
1241 Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1242 RETVAL->rows = 0; 1411 RETVAL->rows = 0;
1243 RETVAL->row = 0; 1412 RETVAL->row = 0;
1244 OUTPUT: 1413 OUTPUT:
1245 RETVAL 1414 RETVAL
1246 1415
1247void 1416void
1248DESTROY (CFPlus::Map self) 1417DESTROY (CFPlus::Map self)
1249 CODE: 1418 CODE:
1250{ 1419{
1251 map_clear (self); 1420 map_clear (self);
1252 Safefree (self->face); 1421 Safefree (self->face2tile);
1253 Safefree (self->tex); 1422 Safefree (self->tex);
1254 Safefree (self); 1423 Safefree (self);
1255} 1424}
1256 1425
1257void 1426void
1264clear (CFPlus::Map self) 1433clear (CFPlus::Map self)
1265 CODE: 1434 CODE:
1266 map_clear (self); 1435 map_clear (self);
1267 1436
1268void 1437void
1269set_face (CFPlus::Map self, int face, int texid) 1438set_tileid (CFPlus::Map self, int face, int tile)
1270 CODE: 1439 CODE:
1271{ 1440{
1272 while (self->faces <= face) 1441 need_facenum (self, face); self->face2tile [face] = tile;
1273 { 1442 need_texid (self, tile);
1274 Append (mapface, self->face, self->faces, self->faces); 1443}
1275 self->faces *= 2;
1276 }
1277 1444
1278 self->face [face] = texid; 1445void
1446set_smooth (CFPlus::Map self, int face, int smooth, int level)
1447 CODE:
1448{
1449 tileid texid;
1450 maptex *tex;
1451
1452 if (face < 0 || face >= self->faces)
1453 return;
1454
1455 if (smooth < 0 || smooth >= self->faces)
1456 return;
1457
1458 texid = self->face2tile [face];
1459
1460 if (!texid)
1461 return;
1462
1463 tex = self->tex + texid;
1464 tex->smoothtile = self->face2tile [smooth];
1465 tex->smoothlevel = level;
1279} 1466}
1280 1467
1281void 1468void
1282set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1469set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1283 CODE: 1470 CODE:
1284{ 1471{
1285 while (self->texs <= texid) 1472 need_texid (self, texid);
1286 {
1287 Append (maptex, self->tex, self->texs, self->texs);
1288 self->texs *= 2;
1289 }
1290 1473
1291 { 1474 {
1292 maptex *tex = self->tex + texid; 1475 maptex *tex = self->tex + texid;
1293 1476
1294 tex->name = name; 1477 tex->name = name;
1338 CODE: 1521 CODE:
1339{ 1522{
1340 if (dx > 0) 1523 if (dx > 0)
1341 map_blank (self, self->x, self->y, dx, self->h); 1524 map_blank (self, self->x, self->y, dx, self->h);
1342 else if (dx < 0) 1525 else if (dx < 0)
1343 map_blank (self, self->x + self->w + dx + 1, self->y, -dx, self->h); 1526 map_blank (self, self->x + self->w + dx, self->y, -dx, self->h);
1344 1527
1345 if (dy > 0) 1528 if (dy > 0)
1346 map_blank (self, self->x, self->y, self->w, dy); 1529 map_blank (self, self->x, self->y, self->w, dy);
1347 else if (dy < 0) 1530 else if (dy < 0)
1348 map_blank (self, self->x, self->y + self->h + dy + 1, self->w, -dy); 1531 map_blank (self, self->x, self->y + self->h + dy, self->w, -dy);
1349 1532
1350 self->ox += dx; self->x += dx; 1533 self->ox += dx; self->x += dx;
1351 self->oy += dy; self->y += dy; 1534 self->oy += dy; self->y += dy;
1352 1535
1353 while (self->y < 0) 1536 while (self->y < 0)
1405 cell->stat_width = 1; 1588 cell->stat_width = 1;
1406 cell->stat_hp = *data++; 1589 cell->stat_hp = *data++;
1407 } 1590 }
1408 else if (cmd == 6) // monster width 1591 else if (cmd == 6) // monster width
1409 cell->stat_width = *data++ + 1; 1592 cell->stat_width = *data++ + 1;
1410 else if (cmd == 0x47) // monster width 1593 else if (cmd == 0x47)
1411 { 1594 {
1412 if (*data == 4) 1595 if (*data == 4)
1413 ; // decode player tag 1596 ; // decode player count
1414 1597
1415 data += *data + 1; 1598 data += *data + 1;
1416 } 1599 }
1417 else if (cmd == 8) // cell flags 1600 else if (cmd == 8) // cell flags
1418 cell->flags = *data++; 1601 cell->flags = *data++;
1427 cell->darkness = *data++ + 1; 1610 cell->darkness = *data++ + 1;
1428 } 1611 }
1429 1612
1430 if (flags & 4) 1613 if (flags & 4)
1431 { 1614 {
1432 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2; 1615 faceid face = (data [0] << 8) + data [1]; data += 2;
1616 need_facenum (self, face);
1617 cell->tile [0] = self->face2tile [face];
1433 } 1618 }
1434 1619
1435 if (flags & 2) 1620 if (flags & 2)
1436 { 1621 {
1437 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2; 1622 faceid face = (data [0] << 8) + data [1]; data += 2;
1623 need_facenum (self, face);
1624 cell->tile [1] = self->face2tile [face];
1438 } 1625 }
1439 1626
1440 if (flags & 1) 1627 if (flags & 1)
1441 { 1628 {
1442 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2; 1629 faceid face = (data [0] << 8) + data [1]; data += 2;
1630 need_facenum (self, face);
1631 cell->tile [2] = self->face2tile [face];
1443 } 1632 }
1444 } 1633 }
1445 else 1634 else
1446 cell->darkness = 0; 1635 cell->darkness = 0;
1447 } 1636 }
1477 { 1666 {
1478 mapcell *cell = row->col + (x - row->c0); 1667 mapcell *cell = row->col + (x - row->c0);
1479 1668
1480 for (z = 0; z <= 0; z++) 1669 for (z = 0; z <= 0; z++)
1481 { 1670 {
1482 mapface face = cell->face [z];
1483
1484 if (face)
1485 {
1486 maptex tex = self->tex [face]; 1671 maptex tex = self->tex [cell->tile [z]];
1487 int a0 = 255 - tex.a; 1672 int a0 = 255 - tex.a;
1488 int a1 = tex.a; 1673 int a1 = tex.a;
1489 1674
1490 r = (r * a0 + tex.r * a1) / 255; 1675 r = (r * a0 + tex.r * a1) / 255;
1491 g = (g * a0 + tex.g * a1) / 255; 1676 g = (g * a0 + tex.g * a1) / 255;
1492 b = (b * a0 + tex.b * a1) / 255; 1677 b = (b * a0 + tex.b * a1) / 255;
1493 a = (a * a0 + tex.a * a1) / 255; 1678 a = (a * a0 + tex.a * a1) / 255;
1494 }
1495 } 1679 }
1496 } 1680 }
1497 1681
1498 *map++ = (r ) 1682 *map++ = (r )
1499 | (g << 8) 1683 | (g << 8)
1506} 1690}
1507 OUTPUT: 1691 OUTPUT:
1508 RETVAL 1692 RETVAL
1509 1693
1510void 1694void
1511draw (CFPlus::Map self, int mx, int my, int sw, int sh) 1695draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1512 CODE: 1696 CODE:
1513{ 1697{
1698 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1699 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1700 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k)
1701 smooth_key skey;
1514 int x, y, z; 1702 int x, y, z;
1515 int last_name; 1703 int last_name;
1516 mapface face; 1704
1705 // thats current max. sorry.
1706 if (sw > 255) sw = 255;
1707 if (sh > 255) sh = 255;
1708
1709 // clear key, in case of extra padding
1710 memset (&skey, 0, sizeof (skey));
1517 1711
1518 glColor4ub (255, 255, 255, 255); 1712 glColor4ub (255, 255, 255, 255);
1519 1713
1520 glEnable (GL_BLEND); 1714 glEnable (GL_BLEND);
1521 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1715 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1527 last_name = 0; 1721 last_name = 0;
1528 1722
1529 mx += self->x; 1723 mx += self->x;
1530 my += self->y; 1724 my += self->y;
1531 1725
1726 // first pass: determine smooth_max
1727 // rather ugly, if you ask me
1728 // could also be stored inside mapcell and updated on change
1729 memset (smooth_max, 0, sizeof (smooth_max));
1730
1731 for (y = 0; y < sh; y++)
1732 if (0 <= y + my && y + my < self->rows)
1733 {
1734 maprow *row = self->row + (y + my);
1735
1736 for (x = 0; x < sw; x++)
1737 if (row->c0 <= x + mx && x + mx < row->c1)
1738 {
1739 mapcell *cell = row->col + (x + mx - row->c0);
1740
1741 smooth_max[x + 1][y + 1] =
1742 MAX (self->tex [cell->tile [0]].smoothlevel,
1743 MAX (self->tex [cell->tile [1]].smoothlevel,
1744 self->tex [cell->tile [2]].smoothlevel));
1745 }
1746 }
1747
1532 for (z = 0; z < 3; z++) 1748 for (z = 0; z <= 2; z++)
1749 {
1750 memset (smooth_level, 0, sizeof (smooth_level));
1751
1533 for (y = 0; y < sh; y++) 1752 for (y = 0; y < sh; y++)
1534 if (0 <= y + my && y + my < self->rows) 1753 if (0 <= y + my && y + my < self->rows)
1535 { 1754 {
1536 maprow *row = self->row + (y + my); 1755 maprow *row = self->row + (y + my);
1537 1756
1538 for (x = 0; x < sw; x++) 1757 for (x = 0; x < sw; x++)
1539 if (row->c0 <= x + mx && x + mx < row->c1) 1758 if (row->c0 <= x + mx && x + mx < row->c1)
1540 { 1759 {
1541 mapcell *cell = row->col + (x + mx - row->c0); 1760 mapcell *cell = row->col + (x + mx - row->c0);
1542
1543 face = cell->face [z]; 1761 tileid tile = cell->tile [z];
1762
1763 if (tile)
1764 {
1765 maptex tex = self->tex [tile];
1766 int px = (x + 1) * T - tex.w;
1767 int py = (y + 1) * T - tex.h;
1544 1768
1545 if (face && face < self->texs) 1769 // suppressing texture state switches here
1770 // is only moderately effective, but worth the extra effort
1771 if (last_name != tex.name)
1772 {
1773 if (!tex.name)
1774 tex = self->tex [2]; /* missing, replace by noface */
1775
1776 glEnd ();
1777 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1778 glBegin (GL_QUADS);
1779 }
1780
1781 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1782 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1783 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1784 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1785
1786 if (cell->flags && z == 2)
1787 {
1788 if (cell->flags & 1)
1789 {
1790 maptex tex = self->tex [1];
1791 int px = x * T + T * 2 / 32;
1792 int py = y * T - T * 6 / 32;
1793
1794 glEnd ();
1795 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1796 glBegin (GL_QUADS);
1797
1798 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1799 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T);
1800 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T);
1801 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py );
1802 }
1803 }
1804
1805 // update smooth hash
1806 if (tex.smoothtile)
1807 {
1808 skey.tile = tex.smoothtile;
1809 skey.level = tex.smoothlevel;
1810
1811 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
1812
1813 // add bits to current tile and all neighbours. skey.x|y is
1814 // shifted +1|+1 so we always stay positive.
1815
1816 // bits is ___n cccc CCCC bbbb
1817 // n do not draw borders&corners
1818 // c draw these corners, but...
1819 // C ... not these
1820 // b draw these borders
1821
1822 // borders: 1 ┃· 2 ━━ 4 ·┃ 8 ··
1823 // ┃· ·· ·┃ ━━
1824
1825 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1826 // ·· ·· ·┏ ┓·
1827
1828 // full tile
1829 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
1830
1831 // borders
1832 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091);
1833 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032);
1834 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
1835 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
1836
1837 // corners
1838 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1839 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1840 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1841 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1842 }
1843 }
1844 }
1845 }
1846
1847 // go through all smoothlevels, lowest to highest, then draw.
1848 // this is basically counting sort
1849 {
1850 int w, b;
1851
1852 for (w = 0; w < 256 / 32; ++w)
1853 {
1854 uint32_t smask = smooth_level [w];
1855 if (smask)
1856 for (b = 0; b < 32; ++b)
1857 if (smask & (((uint32_t)1) << b))
1546 { 1858 {
1547 maptex tex = self->tex [face]; 1859 int level = (w << 5) | b;
1548 int px = (x + 1) * 32 - tex.w; 1860 HE *he;
1549 int py = (y + 1) * 32 - tex.h;
1550 1861
1551 if (last_name != tex.name) 1862 hv_iterinit (smooth);
1863 while ((he = hv_iternext (smooth)))
1552 { 1864 {
1865 smooth_key *skey = (smooth_key *)HeKEY (he);
1866 IV bits = SvIVX (HeVAL (he));
1867
1868 if (!(bits & 0x1000)
1869 && skey->level == level
1870 && level > smooth_max [skey->x][skey->y])
1871 {
1872 maptex tex = self->tex [skey->tile];
1873 int px = (((int)skey->x) - 1) * T;
1874 int py = (((int)skey->y) - 1) * T;
1875 int border = bits & 15;
1876 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1877 float dx = tex.s * .0625f; // 16 images/row
1878 float dy = tex.t * .5f ; // 2 images/column
1879
1880 // this time naively avoiding texture state changes
1881 // save gobs of state changes.
1882 if (last_name != tex.name)
1883 {
1884 if (!tex.name)
1885 continue; // smoothing not yet available
1886
1553 glEnd (); 1887 glEnd ();
1554 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1888 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1555 glBegin (GL_QUADS); 1889 glBegin (GL_QUADS);
1890 }
1891
1892 if (border)
1893 {
1894 float ox = border * dx;
1895
1896 glTexCoord2f (ox , 0.f ); glVertex2f (px , py );
1897 glTexCoord2f (ox , dy ); glVertex2f (px , py + T);
1898 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py + T);
1899 glTexCoord2f (ox + dx, 0.f ); glVertex2f (px + T, py );
1900 }
1901
1902 if (corner)
1903 {
1904 float ox = corner * dx;
1905
1906 glTexCoord2f (ox , dy ); glVertex2f (px , py );
1907 glTexCoord2f (ox , dy * 2.f); glVertex2f (px , py + T);
1908 glTexCoord2f (ox + dx, dy * 2.f); glVertex2f (px + T, py + T);
1909 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py );
1910 }
1556 } 1911 }
1557
1558 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1559 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1560 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1561 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1562 }
1563
1564 if (cell->flags && z == 2)
1565 {
1566 if (cell->flags & 1)
1567 {
1568 maptex tex = self->tex [1];
1569 int px = (x + 1) * 32 - tex.w + 2;
1570 int py = (y + 1) * 32 - tex.h - 6;
1571
1572 glEnd ();
1573 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1574 glBegin (GL_QUADS);
1575
1576 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1577 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1578 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1579 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1580 } 1912 }
1581 } 1913 }
1582 }
1583 } 1914 }
1915 }
1916
1917 hv_clear (smooth);
1918 }
1584 1919
1585 glEnd (); 1920 glEnd ();
1586 1921
1587 glDisable (GL_TEXTURE_2D); 1922 glDisable (GL_TEXTURE_2D);
1588 glDisable (GL_BLEND); 1923 glDisable (GL_BLEND);
1596 for (x = 0; x < sw; x++) 1931 for (x = 0; x < sw; x++)
1597 if (row->c0 <= x + mx && x + mx < row->c1) 1932 if (row->c0 <= x + mx && x + mx < row->c1)
1598 { 1933 {
1599 mapcell *cell = row->col + (x + mx - row->c0); 1934 mapcell *cell = row->col + (x + mx - row->c0);
1600 1935
1601 int px = x * 32; 1936 int px = x * T;
1602 int py = y * 32; 1937 int py = y * T;
1603 1938
1604 if (cell->stat_hp) 1939 if (cell->stat_hp)
1605 { 1940 {
1606 int width = cell->stat_width * 32; 1941 int width = cell->stat_width * T;
1607 int thick = sh / 28 + 1 + cell->stat_width; 1942 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width;
1608 1943
1609 glColor3ub (0, 0, 0); 1944 glColor3ub (0, 0, 0);
1610 glRectf (px + 1, py - thick - 2, 1945 glRectf (px + 1, py - thick - 2,
1611 px + width - 1, py); 1946 px + width - 1, py);
1612 1947
1682void 2017void
1683fow_texture (CFPlus::Map self, int mx, int my, int sw, int sh) 2018fow_texture (CFPlus::Map self, int mx, int my, int sw, int sh)
1684 PPCODE: 2019 PPCODE:
1685{ 2020{
1686 int x, y; 2021 int x, y;
2022 int sw1 = sw + 2;
2023 int sh1 = sh + 2;
2024 int sh3 = sh * 3;
1687 int sw4 = (sw + 3) & ~3; 2025 int sw34 = (sw * 3 + 3) & ~3;
2026 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
1688 SV *darkness_sv = sv_2mortal (newSV (sw4 * sh)); 2027 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3));
1689 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv); 2028 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
1690 2029
1691 memset (darkness, 255, sw4 * sh);
1692 SvPOK_only (darkness_sv); 2030 SvPOK_only (darkness3_sv);
1693 SvCUR_set (darkness_sv, sw4 * sh); 2031 SvCUR_set (darkness3_sv, sw34 * sh3);
1694 2032
1695 mx += self->x; 2033 mx += self->x - 1;
1696 my += self->y; 2034 my += self->y - 1;
1697 2035
2036 memset (darkness1, 255, sw1 * sh1);
2037
1698 for (y = 0; y < sh; y++) 2038 for (y = 0; y < sh1; y++)
1699 if (0 <= y + my && y + my < self->rows) 2039 if (0 <= y + my && y + my < self->rows)
1700 { 2040 {
1701 maprow *row = self->row + (y + my); 2041 maprow *row = self->row + (y + my);
1702 2042
1703 for (x = 0; x < sw; x++) 2043 for (x = 0; x < sw1; x++)
1704 if (row->c0 <= x + mx && x + mx < row->c1) 2044 if (row->c0 <= x + mx && x + mx < row->c1)
1705 { 2045 {
1706 mapcell *cell = row->col + (x + mx - row->c0); 2046 mapcell *cell = row->col + (x + mx - row->c0);
1707 2047
1708 darkness[y * sw4 + x] = cell->darkness 2048 darkness1 [y * sw1 + x] = cell->darkness
1709 ? 255 - (cell->darkness - 1) 2049 ? 255 - (cell->darkness - 1)
1710 : 255 - FOW_DARKNESS; 2050 : 255 - FOW_DARKNESS;
1711 } 2051 }
1712 } 2052 }
1713 2053
2054 for (y = 0; y < sh; ++y)
2055 for (x = 0; x < sw; ++x)
2056 {
2057 uint8_t d11 = darkness1 [(y ) * sw1 + x ];
2058 uint8_t d21 = darkness1 [(y ) * sw1 + x + 1];
2059 uint8_t d31 = darkness1 [(y ) * sw1 + x + 2];
2060 uint8_t d12 = darkness1 [(y + 1) * sw1 + x ];
2061 uint8_t d22 = darkness1 [(y + 1) * sw1 + x + 1];
2062 uint8_t d32 = darkness1 [(y + 1) * sw1 + x + 2];
2063 uint8_t d13 = darkness1 [(y + 2) * sw1 + x ];
2064 uint8_t d23 = darkness1 [(y + 2) * sw1 + x + 1];
2065 uint8_t d33 = darkness1 [(y + 2) * sw1 + x + 2];
2066
2067 uint8_t r11 = (d11 + d21 + d12) / 3;
2068 uint8_t r21 = d21;
2069 uint8_t r31 = (d21 + d31 + d32) / 3;
2070
2071 uint8_t r12 = d12;
2072 uint8_t r22 = d22;
2073 uint8_t r32 = d32;
2074
2075 uint8_t r13 = (d13 + d23 + d12) / 3;
2076 uint8_t r23 = d23;
2077 uint8_t r33 = (d23 + d33 + d32) / 3;
2078
2079 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11);
2080 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21);
2081 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31);
2082 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12);
2083 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22);
2084 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32);
2085 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13);
2086 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23);
2087 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33);
2088 }
2089
2090 free (darkness1);
2091
1714 EXTEND (SP, 3); 2092 EXTEND (SP, 3);
1715 PUSHs (sv_2mortal (newSViv (sw4))); 2093 PUSHs (sv_2mortal (newSViv (sw34)));
1716 PUSHs (sv_2mortal (newSViv (sh))); 2094 PUSHs (sv_2mortal (newSViv (sh3)));
1717 PUSHs (darkness_sv); 2095 PUSHs (darkness3_sv);
1718} 2096}
1719 2097
1720SV * 2098SV *
1721get_rect (CFPlus::Map self, int x0, int y0, int w, int h) 2099get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1722 CODE: 2100 CODE:
1751 if (row && row->c0 <= x && x < row->c1) 2129 if (row && row->c0 <= x && x < row->c1)
1752 { 2130 {
1753 mapcell *cell = row->col + (x - row->c0); 2131 mapcell *cell = row->col + (x - row->c0);
1754 uint8_t flags = 0; 2132 uint8_t flags = 0;
1755 2133
1756 if (cell->face [0]) flags |= 1; 2134 if (cell->tile [0]) flags |= 1;
1757 if (cell->face [1]) flags |= 2; 2135 if (cell->tile [1]) flags |= 2;
1758 if (cell->face [2]) flags |= 4; 2136 if (cell->tile [2]) flags |= 4;
1759 2137
1760 *data++ = flags; 2138 *data++ = flags;
1761 2139
1762 if (flags & 1) 2140 if (flags & 1)
1763 { 2141 {
2142 tileid tile = cell->tile [0];
1764 *data++ = cell->face [0] >> 8; 2143 *data++ = tile >> 8;
1765 *data++ = cell->face [0]; 2144 *data++ = tile;
1766 } 2145 }
1767 2146
1768 if (flags & 2) 2147 if (flags & 2)
1769 { 2148 {
2149 tileid tile = cell->tile [1];
1770 *data++ = cell->face [1] >> 8; 2150 *data++ = tile >> 8;
1771 *data++ = cell->face [1]; 2151 *data++ = tile;
1772 } 2152 }
1773 2153
1774 if (flags & 4) 2154 if (flags & 4)
1775 { 2155 {
2156 tileid tile = cell->tile [2];
1776 *data++ = cell->face [2] >> 8; 2157 *data++ = tile >> 8;
1777 *data++ = cell->face [2]; 2158 *data++ = tile;
1778 } 2159 }
1779 } 2160 }
1780 else 2161 else
1781 *data++ = 0; 2162 *data++ = 0;
1782 } 2163 }
1822 { 2203 {
1823 uint8_t flags = *data++; 2204 uint8_t flags = *data++;
1824 2205
1825 if (flags) 2206 if (flags)
1826 { 2207 {
1827 mapface face[3] = { 0, 0, 0 };
1828
1829 mapcell *cell = row_get_cell (row, x); 2208 mapcell *cell = row_get_cell (row, x);
2209 tileid tile[3] = { 0, 0, 0 };
1830 2210
1831 if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; } 2211 if (flags & 1) { tile[0] = *data++ << 8; tile[0] |= *data++; }
1832 if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; } 2212 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
1833 if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; } 2213 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
1834 2214
1835 if (cell->darkness == 0) 2215 if (cell->darkness == 0)
1836 { 2216 {
1837 cell->darkness = 0; 2217 cell->darkness = 0;
1838 2218
1839 for (z = 0; z <= 2; z++) 2219 for (z = 0; z <= 2; z++)
1840 { 2220 {
1841 cell->face[z] = face[z]; 2221 tileid t = tile [z];
1842 2222
1843 if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name)) 2223 if (t >= self->texs || (t && !self->tex [t].name))
2224 {
1844 XPUSHs (sv_2mortal (newSViv (face[z]))); 2225 XPUSHs (sv_2mortal (newSViv (t)));
2226 need_texid (self, t);
2227 }
2228
2229 cell->tile [z] = t;
1845 } 2230 }
1846 } 2231 }
1847 } 2232 }
1848 } 2233 }
1849 } 2234 }
1850} 2235}
1851 2236
1852MODULE = CFPlus PACKAGE = CFPlus::MixChunk 2237MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1853 2238
2239PROTOTYPES: DISABLE
2240
2241CFPlus::MixChunk
2242new (SV *class, SV *data_sv)
2243 CODE:
2244{
2245 STRLEN datalen;
2246 char *data = SvPVbyte (data_sv, datalen);
2247
2248 RETVAL = Mix_LoadWAV_RW (SDL_RWFromConstMem (data, datalen), 1);
2249}
2250 OUTPUT:
2251 RETVAL
2252
1854CFPlus::MixChunk 2253CFPlus::MixChunk
1855new_from_file (SV *class, char *path) 2254new_from_file (SV *class, char *path)
1856 CODE: 2255 CODE:
1857 RETVAL = Mix_LoadWAV (path); 2256 RETVAL = Mix_LoadWAV (path);
1858 OUTPUT: 2257 OUTPUT:
1879 2278
1880MODULE = CFPlus PACKAGE = CFPlus::MixMusic 2279MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1881 2280
1882int 2281int
1883volume (int volume = -1) 2282volume (int volume = -1)
2283 PROTOTYPE: ;$
1884 CODE: 2284 CODE:
1885 RETVAL = Mix_VolumeMusic (volume); 2285 RETVAL = Mix_VolumeMusic (volume);
1886 OUTPUT: 2286 OUTPUT:
1887 RETVAL 2287 RETVAL
1888 2288
2289int
2290fade_out (int ms)
2291 CODE:
2292 RETVAL = Mix_FadeOutMusic (ms);
2293 OUTPUT:
2294 RETVAL
2295
1889CFPlus::MixMusic 2296CFPlus::MixMusic
1890new_from_file (SV *class, char *path) 2297new_from_file (SV *class, char *path)
1891 CODE: 2298 CODE:
1892 RETVAL = Mix_LoadMUS (path); 2299 RETVAL = Mix_LoadMUS (path);
1893 OUTPUT: 2300 OUTPUT:
1903 CODE: 2310 CODE:
1904 RETVAL = Mix_PlayMusic (self, loops); 2311 RETVAL = Mix_PlayMusic (self, loops);
1905 OUTPUT: 2312 OUTPUT:
1906 RETVAL 2313 RETVAL
1907 2314
2315int
2316fade_in_pos (CFPlus::MixMusic self, int loops, int ms, double position)
2317 CODE:
2318 RETVAL = Mix_FadeInMusicPos (self, loops, ms, position);
2319 OUTPUT:
2320 RETVAL
2321
1908MODULE = CFPlus PACKAGE = CFPlus::OpenGL 2322MODULE = CFPlus PACKAGE = CFPlus::OpenGL
2323
2324PROTOTYPES: ENABLE
1909 2325
1910BOOT: 2326BOOT:
1911{ 2327{
1912 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1); 2328 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1913 static const struct { 2329 static const struct {
1914 const char *name; 2330 const char *name;
1915 IV iv; 2331 IV iv;
1916 } *civ, const_iv[] = { 2332 } *civ, const_iv[] = {
1917# define const_iv(name) { # name, (IV)name } 2333# define const_iv(name) { # name, (IV)name }
2334 const_iv (GL_VENDOR),
2335 const_iv (GL_VERSION),
2336 const_iv (GL_EXTENSIONS),
1918 const_iv (GL_COLOR_MATERIAL), 2337 const_iv (GL_COLOR_MATERIAL),
1919 const_iv (GL_SMOOTH), 2338 const_iv (GL_SMOOTH),
1920 const_iv (GL_FLAT), 2339 const_iv (GL_FLAT),
1921 const_iv (GL_DITHER), 2340 const_iv (GL_DITHER),
1922 const_iv (GL_BLEND), 2341 const_iv (GL_BLEND),
1926 const_iv (GL_ALPHA_TEST), 2345 const_iv (GL_ALPHA_TEST),
1927 const_iv (GL_NORMALIZE), 2346 const_iv (GL_NORMALIZE),
1928 const_iv (GL_RESCALE_NORMAL), 2347 const_iv (GL_RESCALE_NORMAL),
1929 const_iv (GL_FRONT), 2348 const_iv (GL_FRONT),
1930 const_iv (GL_BACK), 2349 const_iv (GL_BACK),
2350 const_iv (GL_AUX0),
1931 const_iv (GL_AND), 2351 const_iv (GL_AND),
1932 const_iv (GL_ONE), 2352 const_iv (GL_ONE),
1933 const_iv (GL_ZERO), 2353 const_iv (GL_ZERO),
1934 const_iv (GL_SRC_ALPHA), 2354 const_iv (GL_SRC_ALPHA),
1935 const_iv (GL_DST_ALPHA), 2355 const_iv (GL_DST_ALPHA),
1949 const_iv (GL_LUMINANCE), 2369 const_iv (GL_LUMINANCE),
1950 const_iv (GL_LUMINANCE_ALPHA), 2370 const_iv (GL_LUMINANCE_ALPHA),
1951 const_iv (GL_FLOAT), 2371 const_iv (GL_FLOAT),
1952 const_iv (GL_UNSIGNED_INT_8_8_8_8_REV), 2372 const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1953 const_iv (GL_COMPILE), 2373 const_iv (GL_COMPILE),
2374 const_iv (GL_PROXY_TEXTURE_1D),
2375 const_iv (GL_PROXY_TEXTURE_2D),
1954 const_iv (GL_TEXTURE_1D), 2376 const_iv (GL_TEXTURE_1D),
1955 const_iv (GL_TEXTURE_2D), 2377 const_iv (GL_TEXTURE_2D),
1956 const_iv (GL_TEXTURE_ENV), 2378 const_iv (GL_TEXTURE_ENV),
1957 const_iv (GL_TEXTURE_MAG_FILTER), 2379 const_iv (GL_TEXTURE_MAG_FILTER),
1958 const_iv (GL_TEXTURE_MIN_FILTER), 2380 const_iv (GL_TEXTURE_MIN_FILTER),
1979 const_iv (GL_COLOR_LOGIC_OP), 2401 const_iv (GL_COLOR_LOGIC_OP),
1980 const_iv (GL_SEPARABLE_2D), 2402 const_iv (GL_SEPARABLE_2D),
1981 const_iv (GL_CONVOLUTION_2D), 2403 const_iv (GL_CONVOLUTION_2D),
1982 const_iv (GL_CONVOLUTION_BORDER_MODE), 2404 const_iv (GL_CONVOLUTION_BORDER_MODE),
1983 const_iv (GL_CONSTANT_BORDER), 2405 const_iv (GL_CONSTANT_BORDER),
2406 const_iv (GL_POINTS),
1984 const_iv (GL_LINES), 2407 const_iv (GL_LINES),
1985 const_iv (GL_LINE_STRIP), 2408 const_iv (GL_LINE_STRIP),
1986 const_iv (GL_LINE_LOOP), 2409 const_iv (GL_LINE_LOOP),
1987 const_iv (GL_QUADS), 2410 const_iv (GL_QUADS),
1988 const_iv (GL_QUAD_STRIP), 2411 const_iv (GL_QUAD_STRIP),
1989 const_iv (GL_TRIANGLES), 2412 const_iv (GL_TRIANGLES),
1990 const_iv (GL_TRIANGLE_STRIP), 2413 const_iv (GL_TRIANGLE_STRIP),
1991 const_iv (GL_TRIANGLE_FAN), 2414 const_iv (GL_TRIANGLE_FAN),
2415 const_iv (GL_POLYGON),
1992 const_iv (GL_PERSPECTIVE_CORRECTION_HINT), 2416 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
2417 const_iv (GL_POINT_SMOOTH_HINT),
2418 const_iv (GL_LINE_SMOOTH_HINT),
2419 const_iv (GL_POLYGON_SMOOTH_HINT),
2420 const_iv (GL_GENERATE_MIPMAP_HINT),
1993 const_iv (GL_FASTEST), 2421 const_iv (GL_FASTEST),
2422 const_iv (GL_DONT_CARE),
2423 const_iv (GL_NICEST),
1994 const_iv (GL_V2F), 2424 const_iv (GL_V2F),
1995 const_iv (GL_V3F), 2425 const_iv (GL_V3F),
1996 const_iv (GL_T2F_V3F), 2426 const_iv (GL_T2F_V3F),
1997 const_iv (GL_T2F_N3F_V3F), 2427 const_iv (GL_T2F_N3F_V3F),
1998# undef const_iv 2428# undef const_iv
1999 }; 2429 };
2000 2430
2001 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 2431 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
2002 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 2432 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
2433
2434 texture_av = newAV ();
2435 AvREAL_off (texture_av);
2003} 2436}
2004 2437
2005char * 2438char *
2006gl_vendor () 2439gl_vendor ()
2007 CODE: 2440 CODE:
2021 CODE: 2454 CODE:
2022 RETVAL = (char *)glGetString (GL_EXTENSIONS); 2455 RETVAL = (char *)glGetString (GL_EXTENSIONS);
2023 OUTPUT: 2456 OUTPUT:
2024 RETVAL 2457 RETVAL
2025 2458
2459const char *glGetString (GLenum pname)
2460
2461GLint glGetInteger (GLenum pname)
2462 CODE:
2463 glGetIntegerv (pname, &RETVAL);
2464 OUTPUT:
2465 RETVAL
2466
2467GLdouble glGetDouble (GLenum pname)
2468 CODE:
2469 glGetDoublev (pname, &RETVAL);
2470 OUTPUT:
2471 RETVAL
2472
2026int glGetError () 2473int glGetError ()
2027 2474
2028void glFinish () 2475void glFinish ()
2029 2476
2030void glClear (int mask) 2477void glClear (int mask)
2067# near_ and far_ are due to microsofts buggy "c" compiler 2514# near_ and far_ are due to microsofts buggy "c" compiler
2068void glFrustum (double left, double right, double bottom, double top, double near_, double far_) 2515void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2069 2516
2070# near_ and far_ are due to microsofts buggy "c" compiler 2517# near_ and far_ are due to microsofts buggy "c" compiler
2071void glOrtho (double left, double right, double bottom, double top, double near_, double far_) 2518void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2519
2520PROTOTYPES: DISABLE
2072 2521
2073void glViewport (int x, int y, int width, int height) 2522void glViewport (int x, int y, int width, int height)
2074 2523
2075void glScissor (int x, int y, int width, int height) 2524void glScissor (int x, int y, int width, int height)
2076 2525
2084 2533
2085void glRotate (float angle, float x, float y, float z) 2534void glRotate (float angle, float x, float y, float z)
2086 CODE: 2535 CODE:
2087 glRotatef (angle, x, y, z); 2536 glRotatef (angle, x, y, z);
2088 2537
2089void glBegin (int mode)
2090
2091void glEnd ()
2092
2093void glColor (float r, float g, float b, float a = 1.0) 2538void glColor (float r, float g, float b, float a = 1.0)
2094 PROTOTYPE: @
2095 ALIAS: 2539 ALIAS:
2096 glColor_premultiply = 1 2540 glColor_premultiply = 1
2097 CODE: 2541 CODE:
2098 if (ix) 2542 if (ix)
2099 { 2543 {
2102 b *= a; 2546 b *= a;
2103 } 2547 }
2104 // microsoft visual "c" rounds instead of truncating... 2548 // microsoft visual "c" rounds instead of truncating...
2105 glColor4f (r, g, b, a); 2549 glColor4f (r, g, b, a);
2106 2550
2107void glInterleavedArrays (int format, int stride, char *data)
2108
2109void glDrawElements (int mode, int count, int type, char *indices)
2110
2111# 1.2 void glDrawRangeElements (int mode, int start, int end
2112
2113void glRasterPos (float x, float y, float z = 0.) 2551void glRasterPos (float x, float y, float z = 0.)
2114 CODE: 2552 CODE:
2115 glRasterPos3f (0, 0, z); 2553 glRasterPos3f (0, 0, z);
2116 glBitmap (0, 0, 0, 0, x, y, 0); 2554 glBitmap (0, 0, 0, 0, x, y, 0);
2117 2555
2121 2559
2122void glTexCoord (float s, float t) 2560void glTexCoord (float s, float t)
2123 CODE: 2561 CODE:
2124 glTexCoord2f (s, t); 2562 glTexCoord2f (s, t);
2125 2563
2564void glRect (float x1, float y1, float x2, float y2)
2565 CODE:
2566 glRectf (x1, y1, x2, y2);
2567
2568PROTOTYPES: ENABLE
2569
2570void glBegin (int mode)
2571
2572void glEnd ()
2573
2574void glPointSize (GLfloat size)
2575
2576void glLineWidth (GLfloat width)
2577
2578void glInterleavedArrays (int format, int stride, char *data)
2579
2580void glDrawElements (int mode, int count, int type, char *indices)
2581
2582# 1.2 void glDrawRangeElements (int mode, int start, int end
2583
2126void glTexEnv (int target, int pname, float param) 2584void glTexEnv (int target, int pname, float param)
2127 CODE: 2585 CODE:
2128 glTexEnvf (target, pname, param); 2586 glTexEnvf (target, pname, param);
2129 2587
2130void glTexParameter (int target, int pname, float param) 2588void glTexParameter (int target, int pname, float param)
2152 2610
2153void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border) 2611void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2154 2612
2155void glDrawPixels (int width, int height, int format, int type, char *pixels) 2613void glDrawPixels (int width, int height, int format, int type, char *pixels)
2156 2614
2615void glPixelZoom (float x, float y)
2616
2157void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR) 2617void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2158 2618
2159int glGenTexture () 2619int glGenTexture ()
2160 CODE: 2620 CODE:
2161{ 2621 RETVAL = gen_texture ();
2162 GLuint name;
2163 glGenTextures (1, &name);
2164 RETVAL = name;
2165}
2166 OUTPUT: 2622 OUTPUT:
2167 RETVAL 2623 RETVAL
2168 2624
2169void glDeleteTexture (int name) 2625void glDeleteTexture (int name)
2170 CODE: 2626 CODE:
2171{
2172 GLuint name_ = name;
2173 glDeleteTextures (1, &name_); 2627 del_texture (name);
2174} 2628
2175
2176int glGenList () 2629int glGenList ()
2177 CODE: 2630 CODE:
2178 RETVAL = glGenLists (1); 2631 RETVAL = glGenLists (1);
2179 OUTPUT: 2632 OUTPUT:
2180 RETVAL 2633 RETVAL
2187 2640
2188void glEndList () 2641void glEndList ()
2189 2642
2190void glCallList (int list) 2643void glCallList (int list)
2191 2644
2645MODULE = CFPlus PACKAGE = CFPlus::UI::Base
2646
2647PROTOTYPES: DISABLE
2648
2649void
2650find_widget (SV *self, NV x, NV y)
2651 PPCODE:
2652{
2653 if (within_widget (self, x, y))
2654 XPUSHs (self);
2655}
2656
2657BOOT:
2658{
2659 hover_gv = gv_fetchpv ("CFPlus::UI::HOVER", 1, SVt_NV);
2660
2661 draw_x_gv = gv_fetchpv ("CFPlus::UI::Base::draw_x", 1, SVt_NV);
2662 draw_y_gv = gv_fetchpv ("CFPlus::UI::Base::draw_y", 1, SVt_NV);
2663 draw_w_gv = gv_fetchpv ("CFPlus::UI::Base::draw_w", 1, SVt_NV);
2664 draw_h_gv = gv_fetchpv ("CFPlus::UI::Base::draw_h", 1, SVt_NV);
2665}
2666
2667void
2668draw (SV *self)
2669 CODE:
2670{
2671 HV *hv;
2672 SV **svp;
2673 NV x, y, w, h;
2674 SV *draw_x_sv = GvSV (draw_x_gv);
2675 SV *draw_y_sv = GvSV (draw_y_gv);
2676 SV *draw_w_sv = GvSV (draw_w_gv);
2677 SV *draw_h_sv = GvSV (draw_h_gv);
2678 SV *hover;
2679 double draw_x, draw_y, draw_w, draw_h;
2680
2681 if (!SvROK (self))
2682 croak ("CFPlus::Base::draw: %s not a reference", SvPV_nolen (self));
2683
2684 hv = (HV *)SvRV (self);
2685
2686 if (SvTYPE (hv) != SVt_PVHV)
2687 croak ("CFPlus::Base::draw: %s not a hashref", SvPV_nolen (self));
2688
2689 svp = hv_fetch (hv, "w", 1, 0); w = svp ? SvNV (*svp) : 0.;
2690 svp = hv_fetch (hv, "h", 1, 0); h = svp ? SvNV (*svp) : 0.;
2691
2692 if (!h || !w)
2693 XSRETURN_EMPTY;
2694
2695 svp = hv_fetch (hv, "x", 1, 0); x = svp ? SvNV (*svp) : 0.;
2696 svp = hv_fetch (hv, "y", 1, 0); y = svp ? SvNV (*svp) : 0.;
2697
2698 draw_x = SvNV (draw_x_sv) + x;
2699 draw_y = SvNV (draw_y_sv) + y;
2700
2701 if (draw_x + w < 0 || draw_x >= SvNV (draw_w_sv)
2702 || draw_y + h < 0 || draw_y >= SvNV (draw_h_sv))
2703 XSRETURN_EMPTY;
2704
2705 sv_setnv (draw_x_sv, draw_x);
2706 sv_setnv (draw_y_sv, draw_y);
2707
2708 glPushMatrix ();
2709 glTranslated (x, y, 0);
2710
2711 if (SvROK (GvSV (hover_gv)) && SvRV (GvSV (hover_gv)) == (SV *)hv)
2712 {
2713 svp = hv_fetch (hv, "can_hover", sizeof ("can_hover") - 1, 0);
2714
2715 if (svp && SvTRUE (*svp))
2716 {
2717 glColor4f (1*0.2f, 0.8*0.2f, 0.5*0.2f, 0.2f);
2718 glEnable (GL_BLEND);
2719 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2720 glBegin (GL_QUADS);
2721 glVertex2f (0, 0);
2722 glVertex2f (w, 0);
2723 glVertex2f (w, h);
2724 glVertex2f (0, h);
2725 glEnd ();
2726 glDisable (GL_BLEND);
2727 }
2728 }
2729#if 0
2730 if ($ENV{CFPLUS_DEBUG} & 1) {
2731 glPushMatrix;
2732 glColor 1, 1, 0, 1;
2733 glTranslate 0.375, 0.375;
2734 glBegin GL_LINE_LOOP;
2735 glVertex 0 , 0;
2736 glVertex $self->{w} - 1, 0;
2737 glVertex $self->{w} - 1, $self->{h} - 1;
2738 glVertex 0 , $self->{h} - 1;
2739 glEnd;
2740 glPopMatrix;
2741 #CFPlus::UI::Label->new (w => $self->{w}, h => $self->{h}, text => $self, fontsize => 0)->_draw;
2742 }
2743#endif
2744 PUSHMARK (SP);
2745 XPUSHs (self);
2746 PUTBACK;
2747 call_method ("_draw", G_VOID | G_DISCARD);
2748 SPAGAIN;
2749
2750 glPopMatrix ();
2751
2752 draw_x = draw_x - x; sv_setnv (draw_x_sv, draw_x);
2753 draw_y = draw_y - y; sv_setnv (draw_y_sv, draw_y);
2754}
2755

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines