/src/SDLx/LayerManager.xs
Unknown | 370 lines | 327 code | 43 blank | 0 comment | 0 complexity | 7b43620b2d63404299396abe34556eff MD5 | raw file
1#include "EXTERN.h" 2#include "perl.h" 3#include "XSUB.h" 4#include "ppport.h" 5#include "helper.h" 6 7#ifndef aTHX_ 8#define aTHX_ 9#endif 10 11#include <SDL.h> 12#include "SDLx/LayerManager.h" 13 14int _get_pixel( SDL_Surface *surface, int x, int y ) 15{ 16 int value = 0; 17 int offset = x + surface->w * y; 18 switch(surface->format->BytesPerPixel) 19 { 20 case 1: value = ((Uint8 *)surface->pixels)[offset]; 21 break; 22 case 2: value = ((Uint16 *)surface->pixels)[offset]; 23 break; 24 case 3: value = ((Uint32)((Uint8 *)surface->pixels)[offset * surface->format->BytesPerPixel] << 0) 25 + ((Uint32)((Uint8 *)surface->pixels)[offset * surface->format->BytesPerPixel + 1] << 8) 26 + ((Uint32)((Uint8 *)surface->pixels)[offset * surface->format->BytesPerPixel + 2] << 16); 27 break; 28 case 4: value = ((Uint32 *)surface->pixels)[offset]; 29 break; 30 } 31 32 return value; 33} 34 35MODULE = SDLx::LayerManager PACKAGE = SDLx::LayerManager PREFIX = lmx_ 36 37SDLx_LayerManager * 38lmx_new( CLASS, ... ) 39 char* CLASS 40 CODE: 41 RETVAL = (SDLx_LayerManager *)safemalloc( sizeof(SDLx_LayerManager) ); 42 RETVAL->layers = newAV(); 43 RETVAL->saveshot = (SDL_Surface *)safemalloc( sizeof(SDL_Surface) ); 44 RETVAL->saved = 0; 45 OUTPUT: 46 RETVAL 47 48void 49lmx_add( manager, bag ) 50 SDLx_LayerManager *manager 51 SV* bag 52 CODE: 53 if( sv_isobject(bag) && (SvTYPE(SvRV(bag)) == SVt_PVMG) ) 54 { 55 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(bag); 56 layer->index = av_len( manager->layers ) + 1; 57 layer->manager = manager; 58 layer->touched = 1; 59 av_push( manager->layers, bag); 60 SvREFCNT_inc(bag); 61 } 62 63AV * 64lmx_layers( manager ) 65 SDLx_LayerManager *manager 66 CODE: 67 RETVAL = manager->layers; 68 OUTPUT: 69 RETVAL 70 71 72SV * 73lmx_layer( manager, index ) 74 SDLx_LayerManager *manager 75 int index 76 PREINIT: 77 char* CLASS = "SDLx::Layer"; 78 CODE: 79 if(index >= 0 && index < av_len( manager->layers ) + 1) 80 { 81 RETVAL = *av_fetch( manager->layers, index, 0 ) ; 82 SvREFCNT_inc(RETVAL); 83 } 84 else 85 XSRETURN_UNDEF; 86 OUTPUT: 87 RETVAL 88 89int 90lmx_length( manager ) 91 SDLx_LayerManager *manager 92 CODE: 93 RETVAL = av_len( manager->layers ) + 1; 94 OUTPUT: 95 RETVAL 96 97AV * 98lmx_blit( manager, dest ) 99 SDLx_LayerManager *manager 100 SDL_Surface *dest 101 CODE: 102 manager->dest = dest; 103 RETVAL = newAV(); 104 int index = 0; 105 int length = av_len( manager->layers ) + 1; 106 int attached_layers = 0; 107 int did_something = 0; 108 109 while(index < length) 110 { 111 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 112 113 if(layer->attached == 0) 114 { 115 if(layer->touched || manager->saved == 0) 116 { 117 SDL_Rect *rect = (SDL_Rect *)safemalloc( sizeof(SDL_Rect) ); 118 rect->x = layer->pos->x; 119 rect->y = layer->pos->y; 120 rect->w = layer->clip->w; 121 rect->h = layer->clip->h; 122 layer->touched = 0; 123 SDL_BlitSurface(layer->surface, layer->clip, dest, rect); 124 av_push(RETVAL, _sv_ref( rect, sizeof(SDL_Rect *), sizeof(SDL_Rect), "SDL::Rect" )); 125 did_something = 1; 126 } 127 } 128 else 129 attached_layers = 1; 130 index++; 131 } 132 133 if(manager->saved == 0) 134 { 135 manager->saveshot = SDL_ConvertSurface(dest, dest->format, dest->flags); 136 manager->saved = 1; 137 } 138 139 if((manager->saved && did_something) || attached_layers) 140 { 141 SDL_BlitSurface(manager->saveshot, NULL, dest, NULL); 142 } 143 144 if(attached_layers) 145 { 146 int x, y; 147 SDL_GetMouseState(&x, &y); 148 index = 0; 149 while(index < length) 150 { 151 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 152 153 if(layer->attached == 1 || layer->attached == 2) 154 { 155 if(layer->attached == 1) 156 { 157 layer->pos->x = x + layer->attached_rel->x; 158 layer->pos->y = y + layer->attached_rel->y; 159 } 160 161 SDL_Rect *rect = (SDL_Rect *)safemalloc( sizeof(SDL_Rect) ); 162 rect->x = layer->pos->x; 163 rect->y = layer->pos->y; 164 rect->w = layer->clip->w; 165 rect->h = layer->clip->h; 166 167 SDL_BlitSurface(layer->surface, layer->clip, dest, rect); 168 av_push(RETVAL, _sv_ref( rect, sizeof(SDL_Rect *), sizeof(SDL_Rect), "SDL::Rect" )); 169 } 170 171 index++; 172 } 173 } 174 OUTPUT: 175 RETVAL 176 177SV * 178lmx_by_position( manager, x, y ) 179 SDLx_LayerManager* manager 180 int x 181 int y 182 CODE: 183 int i; 184 SV *match = NULL; 185 for( i = av_len( manager->layers ); i >= 0 && match == NULL; i-- ) 186 { 187 SV *bag = *av_fetch(manager->layers, i, 0); 188 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(bag); 189 SDL_Rect *clip = layer->clip; 190 SDL_Rect *pos = layer->pos; 191 SDL_Surface *surf = layer->surface; 192 if ( pos->x <= x && x <= pos->x + clip->w 193 && pos->y <= y && y <= pos->y + clip->h) 194 { 195 Uint8 r, g, b, a; 196 Uint32 pixel = _get_pixel(surf, x - pos->x, y - pos->y); 197 SDL_GetRGBA( pixel, surf->format, &r, &g, &b, &a ); 198 199 if(a > 0) 200 match = bag; 201 } 202 } 203 204 if(match != NULL) 205 { 206 RETVAL = match; 207 SvREFCNT_inc(RETVAL); 208 } 209 else 210 XSRETURN_UNDEF; 211 OUTPUT: 212 RETVAL 213 214AV * 215lmx_ahead( manager, index ) 216 SDLx_LayerManager *manager 217 int index 218 CODE: 219 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 220 RETVAL = layers_ahead( layer ); 221 OUTPUT: 222 RETVAL 223 224AV * 225lmx_behind( manager, index ) 226 SDLx_LayerManager *manager 227 int index 228 CODE: 229 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 230 RETVAL = layers_behind( layer ); 231 OUTPUT: 232 RETVAL 233 234void 235lmx_attach( manager, ... ) 236 SDLx_LayerManager *manager 237 CODE: 238 manager->saved = 0; 239 int x = -1; 240 int y = -1; 241 242 if(SvIOK(ST(items - 1))) 243 { 244 y = SvIV(ST(items - 1)); 245 items--; 246 } 247 248 if(SvIOK(ST(items - 1))) 249 { 250 x = SvIV(ST(items - 1)); 251 items--; 252 } 253 254 if(-1 == x || -1 == y) 255 SDL_GetMouseState(&x, &y); 256 257 int i; 258 for( i = 1; i < items; i++ ) 259 { 260 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(ST(i)); 261 layer->attached = 1; 262 layer->attached_pos->x = layer->pos->x; 263 layer->attached_pos->y = layer->pos->y; 264 layer->attached_rel->x = layer->pos->x - x; 265 layer->attached_rel->y = layer->pos->y - y; 266 } 267 268AV * 269lmx_detach_xy( manager, x = -1, y = -1 ) 270 SDLx_LayerManager *manager 271 int x 272 int y 273 CODE: 274 RETVAL = newAV(); 275 int index = 0; 276 int length = av_len( manager->layers ) + 1; 277 int lower_x; 278 int lower_y; 279 int offset_x = 0; 280 int offset_y = 0; 281 while(index < length) 282 { 283 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 284 285 if(layer->attached == 1) 286 { 287 if(av_len(RETVAL) == -1) 288 { 289 lower_x = layer->attached_pos->x; 290 lower_y = layer->attached_pos->y; 291 offset_x = layer->attached_pos->x - x; 292 offset_y = layer->attached_pos->y - y; 293 av_push(RETVAL, newSViv(layer->attached_pos->x)); 294 av_push(RETVAL, newSViv(layer->attached_pos->y)); 295 } 296 297 layer->attached = 0; 298 layer->touched = 1; 299 layer->pos->x = layer->attached_pos->x - offset_x; 300 layer->pos->y = layer->attached_pos->y - offset_y; 301 } 302 303 index++; 304 } 305 manager->saved = 0; 306 OUTPUT: 307 RETVAL 308 309void 310lmx_detach_back( manager ) 311 SDLx_LayerManager *manager 312 CODE: 313 int index = 0; 314 int length = av_len( manager->layers ) + 1; 315 while(index < length) 316 { 317 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(*av_fetch(manager->layers, index, 0)); 318 319 if(layer->attached == 1) 320 { 321 layer->attached = 0; 322 layer->touched = 1; 323 layer->pos->x = layer->attached_pos->x; 324 layer->pos->y = layer->attached_pos->y; 325 } 326 327 index++; 328 } 329 manager->saved = 0; 330 331AV * 332lmx_foreground( manager, ... ) 333 SDLx_LayerManager *manager 334 CODE: 335 RETVAL = newAV(); 336 int x; 337 for(x = 1; x < items; x++) 338 { 339 SDLx_Layer *layer = (SDLx_Layer *)bag2obj(ST(x)); 340 SDLx_LayerManager *manager = layer->manager; 341 int index = layer->index; /* we cant trust its value */ 342 int i; 343 344 SV *fetched; 345 for(i = 0; i <= av_len(manager->layers); i++) 346 { 347 fetched = *av_fetch(manager->layers, i, 0); 348 if(fetched == ST(x)) /* what bag do we have? => finding the right layer index */ 349 { 350 index = i; 351 break; 352 } 353 } 354 355 for(i = index; i < av_len(manager->layers); i++) 356 { 357 AvARRAY(manager->layers)[i] = AvARRAY(manager->layers)[i + 1]; 358 } 359 360 AvARRAY(manager->layers)[i] = fetched; 361 manager->saved = 0; 362 } 363 OUTPUT: 364 RETVAL 365 366void 367lmx_DESTROY( manager ) 368 SDLx_LayerManager *manager 369 CODE: 370 safefree(manager);