Files
libakgl/src/sprite.c

175 lines
6.2 KiB
C
Raw Normal View History

#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <string.h>
#include <jansson.h>
#include <akerror.h>
#include <libgen.h>
#include <sdl3game/game.h>
#include <sdl3game/sprite.h>
#include <sdl3game/json_helpers.h>
#include <sdl3game/heap.h>
#include <sdl3game/registry.h>
#include <sdl3game/staticstring.h>
#include <sdl3game/iterator.h>
static akerr_ErrorContext *akgl_sprite_load_json_spritesheet(json_t *json, akgl_SpriteSheet **sheet, char *relative_path)
{
PREPARE_ERROR(errctx);
json_t *spritesheet_json = NULL;
int ss_frame_width = 0;
int ss_frame_height = 0;
akgl_String *ss_filename = NULL;
akgl_String *tmpstr = NULL;
ATTEMPT {
CATCH(errctx, akgl_heap_next_string(&tmpstr));
CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
CATCH(errctx, akgl_get_json_object_value((json_t *)json, "spritesheet", &spritesheet_json));
CATCH(errctx, akgl_get_json_string_value((json_t *)spritesheet_json, "filename", &ss_filename));
if ( ss_filename->data[0] != '/' ) {
SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s/%s", relative_path, ss_filename->data);
} else {
SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s", ss_filename->data);
}
*sheet = SDL_GetPointerProperty(
AKGL_AKGL_REGISTRY_SPRITESHEET,
(char *)&tmpstr->data,
NULL
);
if ( *sheet == NULL ) {
CATCH(errctx, akgl_heap_next_spritesheet(sheet));
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_width", &ss_frame_width));
CATCH(errctx, akgl_get_json_integer_value((json_t *)spritesheet_json, "frame_height", &ss_frame_width));
CATCH(errctx,
akgl_spritesheet_initialize(
(akgl_SpriteSheet *)*sheet,
ss_frame_width,
ss_frame_height,
(char *)&tmpstr->data)
);
}
} CLEANUP {
IGNORE(akgl_heap_release_string(ss_filename));
IGNORE(akgl_heap_release_string(tmpstr));
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx);
}
akerr_ErrorContext *akgl_sprite_load_json(char *filename)
{
PREPARE_ERROR(errctx);
json_t *json = NULL;
json_t *frames = NULL;
json_error_t error;
akgl_Sprite *obj = NULL;
akgl_SpriteSheet *sheet = NULL;
akgl_String *spritename = NULL;
//string *tmpstr = NULL;
int i = 0;
FAIL_ZERO_RETURN(errctx, filename, AKERR_NULLPOINTER, "Received null filename");
ATTEMPT {
CATCH(errctx, akgl_heap_next_sprite(&obj));
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
CATCH(errctx, akgl_heap_next_string(&spritename));
CATCH(errctx, akgl_string_initialize(spritename, NULL));
//SDL_snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
json = (json_t *)json_load_file(filename, 0, &error);
FAIL_ZERO_BREAK(
errctx,
json,
AKERR_NULLPOINTER,
"Error while loading sprite from %s on line %d: %s", filename, error.line, error.text
);
CATCH(errctx, akgl_sprite_load_json_spritesheet((json_t *)json, &sheet, dirname(filename)));
CATCH(errctx, akgl_get_json_string_value((json_t *)json, "name", &spritename));
CATCH(errctx,
akgl_sprite_initialize(
(akgl_Sprite *)obj,
spritename->data,
(akgl_SpriteSheet *)sheet)
);
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "width", &obj->width));
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &obj->height));
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "speed", (int *)&obj->speed));
obj->speed = obj->speed * AKGL_TIME_ONESEC_MS;
CATCH(errctx, akgl_get_json_boolean_value((json_t *)json, "loop", &obj->loop));
CATCH(errctx, akgl_get_json_boolean_value((json_t *)json, "loopReverse", &obj->loopReverse));
CATCH(errctx, akgl_get_json_array_value((json_t *)json, "frames", &frames));
obj->frames = json_array_size((json_t *)frames);
for ( i = 0 ; i < obj->frames; i++ ) {
CATCH(errctx, akgl_get_json_array_index_integer((json_t *)frames, i, &obj->frameids[i]));
}
} CLEANUP {
if ( errctx != NULL && errctx->status != 0 ) {
IGNORE(akgl_heap_release_sprite(obj));
IGNORE(akgl_heap_release_spritesheet(sheet));
}
IGNORE(akgl_heap_release_string(spritename));
//IGNORE(akgl_heap_release_string(tmpstr));
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx);
}
akerr_ErrorContext *akgl_sprite_initialize(akgl_Sprite *spr, char *name, akgl_SpriteSheet *sheet)
{
PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, spr, AKERR_NULLPOINTER, "Null sprite reference");
FAIL_ZERO_RETURN(errctx, name, AKERR_NULLPOINTER, "Empty sprite name");
FAIL_ZERO_RETURN(errctx, sheet, AKERR_NULLPOINTER, "Null spritesheet reference");
memset(spr, 0x00, sizeof(akgl_Sprite));
memcpy(spr->name, name, AKGL_SPRITE_MAX_NAME_LENGTH);
spr->sheet = sheet;
FAIL_ZERO_RETURN(
errctx,
SDL_SetPointerProperty(AKGL_REGISTRY_SPRITE, (char *)&spr->name, (void *)spr),
AKERR_KEY,
"Unable to add sprite to registry");
spr->refcount += 1;
SUCCEED_RETURN(errctx);
}
akerr_ErrorContext *akgl_spritesheet_initialize(akgl_SpriteSheet *sheet, int sprite_w, int sprite_h, char *filename)
{
PREPARE_ERROR(errctx);
//akgl_String *tmpstr = NULL;
ATTEMPT {
FAIL_ZERO_BREAK(errctx, sheet, AKERR_NULLPOINTER, "Null spritesheet pointer");
FAIL_ZERO_BREAK(errctx, filename, AKERR_NULLPOINTER, "Null filename pointer");
memset(sheet, 0x00, sizeof(akgl_SpriteSheet));
//CATCH(errctx, akgl_heap_next_string(&tmpstr));
//CATCH(errctx, akgl_string_initialize(tmpstr, NULL));
strncpy((char *)&sheet->name, filename, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH);
//snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
sheet->texture = IMG_LoadTexture(renderer, filename);
FAIL_ZERO_BREAK(errctx, sheet->texture, AKGL_ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError());
FAIL_ZERO_BREAK(
errctx,
SDL_SetPointerProperty(AKGL_AKGL_REGISTRY_SPRITESHEET, (char *)sheet->name, (void *)sheet),
AKERR_KEY,
"Unable to add spritesheet to registry: %s",
SDL_GetError());
sheet->refcount += 1;
} CLEANUP {
//IGNORE(akgl_heap_release_string(tmpstr));
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx);
}