#include #include #include #include #include #include #include #include #include akgl_Actor HEAP_ACTOR[AKGL_MAX_HEAP_ACTOR]; akgl_Sprite HEAP_SPRITE[AKGL_MAX_HEAP_SPRITE]; akgl_SpriteSheet HEAP_SPRITESHEET[AKGL_MAX_HEAP_SPRITESHEET]; akgl_Character HEAP_CHARACTER[AKGL_MAX_HEAP_CHARACTER]; akgl_String HEAP_STRING[AKGL_MAX_HEAP_STRING]; akerr_ErrorContext *akgl_heap_init() { PREPARE_ERROR(errctx); int i = 0; akerr_name_for_status(AKGL_ERR_SDL, "SDL Error"); for ( i = 0; i < AKGL_MAX_HEAP_ACTOR; i++) { memset(&HEAP_ACTOR[i], 0x00, sizeof(akgl_Actor)); } for ( i = 0; i < AKGL_MAX_HEAP_SPRITE; i++) { memset(&HEAP_SPRITE[i], 0x00, sizeof(akgl_Sprite)); } for ( i = 0; i < AKGL_MAX_HEAP_SPRITESHEET; i++) { memset(&HEAP_SPRITESHEET[i], 0x00, sizeof(akgl_SpriteSheet)); } for ( i = 0; i < AKGL_MAX_HEAP_CHARACTER; i++) { memset(&HEAP_CHARACTER[i], 0x00, sizeof(akgl_Character)); } for ( i = 0; i < AKGL_MAX_HEAP_STRING; i++) { memset(&HEAP_STRING[i], 0x00, sizeof(akgl_String)); } SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_heap_next_actor(akgl_Actor **dest) { PREPARE_ERROR(errctx); for (int i = 0; i < AKGL_MAX_HEAP_ACTOR; i++ ) { if ( HEAP_ACTOR[i].refcount != 0 ) { continue; } *dest = &HEAP_ACTOR[i]; SUCCEED_RETURN(errctx); } FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused actor on the heap"); } akerr_ErrorContext *akgl_heap_next_sprite(akgl_Sprite **dest) { PREPARE_ERROR(errctx); for (int i = 0; i < AKGL_MAX_HEAP_SPRITE; i++ ) { if ( HEAP_SPRITE[i].refcount != 0 ) { continue; } *dest = &HEAP_SPRITE[i]; SUCCEED_RETURN(errctx); } FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused sprite on the heap"); } akerr_ErrorContext *akgl_heap_next_spritesheet(akgl_SpriteSheet **dest) { PREPARE_ERROR(errctx); for (int i = 0; i < AKGL_MAX_HEAP_SPRITESHEET; i++ ) { if ( HEAP_SPRITESHEET[i].refcount != 0 ) { continue; } *dest = &HEAP_SPRITESHEET[i]; SUCCEED_RETURN(errctx); } FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused spritesheet on the heap"); } akerr_ErrorContext *akgl_heap_next_character(akgl_Character **dest) { PREPARE_ERROR(errctx); for (int i = 0; i < AKGL_MAX_HEAP_CHARACTER; i++ ) { if ( HEAP_CHARACTER[i].refcount != 0 ) { continue; } *dest = &HEAP_CHARACTER[i]; SUCCEED_RETURN(errctx); } FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused character on the heap"); } akerr_ErrorContext *akgl_heap_next_string(akgl_String **dest) { PREPARE_ERROR(errctx); for (int i = 0; i < AKGL_MAX_HEAP_STRING; i++ ) { if ( HEAP_STRING[i].refcount != 0 ) { continue; } *dest = &HEAP_STRING[i]; SUCCEED_RETURN(errctx); } FAIL_RETURN(errctx, AKERR_HEAP, "Unable to find unused string on the heap"); } akerr_ErrorContext *akgl_heap_release_actor(akgl_Actor *ptr) { int i = 0; PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "NULL actor reference"); if ( ptr->refcount > 0 ) { ptr->refcount -= 1; } if ( ptr->refcount == 0 ) { for ( i = 0; i < AKGL_ACTOR_MAX_CHILDREN; i++ ) { if ( ptr->children[i] != NULL ) { CATCH_AND_RETURN(errctx, akgl_heap_release_actor(ptr->children[i])); } } if ( ptr->basechar != NULL ) { CATCH_AND_RETURN(errctx, akgl_heap_release_character(ptr->basechar)); } memset(ptr, 0x00, sizeof(akgl_Actor)); SDL_ClearProperty(AKGL_REGISTRY_ACTOR, (char *)&ptr->name); } SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_heap_release_character(akgl_Character *basechar) { PREPARE_ERROR(errctx); akgl_Iterator opflags; FAIL_ZERO_RETURN(errctx, basechar, AKERR_NULLPOINTER, "NULL character reference"); AKGL_BITMASK_CLEAR(opflags.flags); AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_RELEASE); if ( basechar->refcount > 0 ) { basechar->refcount -= 1; } if ( basechar->refcount == 0 ) { SDL_EnumerateProperties(basechar->state_sprites, &akgl_character_state_sprites_iterate, (void *)&opflags); SDL_ClearProperty(AKGL_REGISTRY_CHARACTER, (char *)&basechar->name); } SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_heap_release_sprite(akgl_Sprite *ptr) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL sprite reference"); if ( ptr->refcount > 0 ) { ptr->refcount -= 1; } if ( ptr->refcount == 0 ) { ATTEMPT { CATCH(errctx, akgl_heap_release_spritesheet(ptr->sheet)); } CLEANUP { SDL_ClearProperty(AKGL_REGISTRY_SPRITE, (char *)&ptr->name); } PROCESS(errctx) { } FINISH(errctx, true); } SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_heap_release_spritesheet(akgl_SpriteSheet *ptr) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL spritesheet reference"); if ( ptr->refcount > 0 ) { ptr->refcount -= 1; } if ( ptr->refcount == 0 ) { // TODO : If we go threaded, make sure this is only happening on the main thread SDL_ClearProperty(AKGL_AKGL_REGISTRY_SPRITESHEET, (char *)&ptr->name); if ( ptr-> texture != NULL ) SDL_DestroyTexture(ptr->texture); ptr->texture = NULL; } SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_heap_release_string(akgl_String *ptr) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, ptr, AKERR_NULLPOINTER, "Received NULL string reference"); if ( ptr->refcount > 0 ) { ptr->refcount -= 1; } if ( ptr->refcount == 0 ) { memset(&ptr->data, 0x00, AKGL_MAX_STRING_LENGTH); } SUCCEED_RETURN(errctx); }