2026-07-30 01:10:31 -04:00
|
|
|
/**
|
|
|
|
|
* @file registry.c
|
|
|
|
|
* @brief Implements the registry subsystem.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-08-03 10:07:35 -04:00
|
|
|
#include <SDL3/SDL.h>
|
2026-01-05 08:58:06 -05:00
|
|
|
#include <akerror.h>
|
2026-05-08 22:01:56 -04:00
|
|
|
#include <jansson.h>
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-13 04:55:19 -04:00
|
|
|
#include <akstdlib.h>
|
2026-05-08 22:01:56 -04:00
|
|
|
#include <akgl/heap.h>
|
2026-05-07 22:20:10 -04:00
|
|
|
#include <akgl/sprite.h>
|
|
|
|
|
#include <akgl/registry.h>
|
|
|
|
|
#include <akgl/iterator.h>
|
|
|
|
|
#include <akgl/actor.h>
|
2026-05-08 22:01:56 -04:00
|
|
|
#include <akgl/json_helpers.h>
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-26 10:36:31 -04:00
|
|
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR_STATE_STRINGS = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_SPRITE = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_SPRITESHEET = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_CHARACTER = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_MUSIC = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_FONT = 0;
|
|
|
|
|
SDL_PropertiesID AKGL_REGISTRY_PROPERTIES = 0;
|
2025-08-03 10:07:35 -04:00
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
ATTEMPT {
|
2026-05-06 23:18:42 -04:00
|
|
|
CATCH(errctx, akgl_registry_init_spritesheet());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_sprite());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_character());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_actor());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_actor_state_strings());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_font());
|
|
|
|
|
CATCH(errctx, akgl_registry_init_music());
|
2025-08-03 10:07:35 -04:00
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_actor()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-26 10:36:31 -04:00
|
|
|
if ( AKGL_REGISTRY_ACTOR != 0 ) {
|
2026-05-25 21:29:18 -04:00
|
|
|
SDL_DestroyProperties(AKGL_REGISTRY_ACTOR);
|
|
|
|
|
}
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_REGISTRY_ACTOR = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_ACTOR, AKERR_NULLPOINTER, "Error initializing actor registry");
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_init_font()
|
2026-05-06 11:12:42 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_REGISTRY_FONT = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_FONT, AKERR_NULLPOINTER, "Error initializing font registry");
|
2026-05-06 11:12:42 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_music()
|
2026-05-06 11:12:42 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_REGISTRY_MUSIC = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_MUSIC, AKERR_NULLPOINTER, "Error initializing music registry");
|
2026-05-06 11:12:42 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-08 10:16:33 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_properties()
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
AKGL_REGISTRY_PROPERTIES = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_PROPERTIES, AKERR_NULLPOINTER, "Error initializing properties registry");
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_actor_state_strings()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int flag = 0;
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-09 14:45:37 -04:00
|
|
|
AKGL_REGISTRY_ACTOR_STATE_STRINGS = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_ACTOR_STATE_STRINGS, AKERR_NULLPOINTER, "Error initializing actor state strings registry");
|
2026-05-06 23:18:42 -04:00
|
|
|
for ( i = 0 ; i < AKGL_ACTOR_MAX_STATES; i++ ) {
|
2025-08-03 10:07:35 -04:00
|
|
|
flag = (1 << i);
|
|
|
|
|
SDL_SetNumberProperty(
|
2026-05-09 14:45:37 -04:00
|
|
|
AKGL_REGISTRY_ACTOR_STATE_STRINGS,
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_ACTOR_STATE_STRING_NAMES[i],
|
2025-08-03 10:07:35 -04:00
|
|
|
flag);
|
|
|
|
|
}
|
|
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_sprite()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
2026-05-06 11:12:42 -04:00
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_REGISTRY_SPRITE = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_SPRITE, AKERR_NULLPOINTER, "Error initializing sprite registry");
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_spritesheet()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-09 14:45:37 -04:00
|
|
|
AKGL_REGISTRY_SPRITESHEET = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_SPRITESHEET, AKERR_NULLPOINTER, "Error initializing spritesheet registry");
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-06 23:18:42 -04:00
|
|
|
akerr_ErrorContext *akgl_registry_init_character()
|
2025-08-03 10:07:35 -04:00
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(errctx);
|
2026-05-06 23:18:42 -04:00
|
|
|
AKGL_REGISTRY_CHARACTER = SDL_CreateProperties();
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, AKGL_REGISTRY_CHARACTER, AKERR_NULLPOINTER, "Error initializing character registry");
|
2025-08-03 10:07:35 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
|
|
|
|
}
|
2026-05-08 22:01:56 -04:00
|
|
|
|
|
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_registry_load_properties(char *fname)
|
|
|
|
|
{
|
|
|
|
|
json_t *json = NULL;
|
|
|
|
|
json_t *props = NULL;
|
|
|
|
|
const char *pkey = NULL;
|
|
|
|
|
json_t *pvalue = NULL;
|
|
|
|
|
|
|
|
|
|
json_error_t error;
|
|
|
|
|
akgl_String *tmpstr;
|
|
|
|
|
|
|
|
|
|
PREPARE_ERROR(errctx);
|
|
|
|
|
FAIL_ZERO_RETURN(errctx, fname, AKERR_NULLPOINTER, "null filename");
|
|
|
|
|
ATTEMPT {
|
|
|
|
|
SDL_Log("Loading from %s", fname);
|
|
|
|
|
json = json_load_file(fname, 0, &error);
|
|
|
|
|
FAIL_ZERO_BREAK(
|
|
|
|
|
errctx,
|
|
|
|
|
json,
|
|
|
|
|
AKERR_NULLPOINTER,
|
|
|
|
|
"Error while loading properties from %s on line %d: %s-",
|
|
|
|
|
fname,
|
|
|
|
|
error.line,
|
|
|
|
|
error.text);
|
|
|
|
|
CATCH(errctx, akgl_get_json_object_value(json, "properties", &props));
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
|
|
|
|
|
|
|
|
|
json_object_foreach(props, pkey, pvalue) {
|
|
|
|
|
ATTEMPT {
|
|
|
|
|
CATCH(errctx, akgl_heap_next_string(&tmpstr));
|
|
|
|
|
CATCH(errctx, akgl_get_json_string_value(props, (char *)pkey, &tmpstr));
|
|
|
|
|
SDL_SetStringProperty(AKGL_REGISTRY_PROPERTIES, pkey, tmpstr->data);
|
2026-05-13 04:55:19 -04:00
|
|
|
SDL_Log("Set property %s = %s", pkey, tmpstr->data);
|
2026-05-08 22:01:56 -04:00
|
|
|
CATCH(errctx, akgl_heap_release_string(tmpstr));
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(errctx) {
|
|
|
|
|
} FINISH(errctx, true);
|
|
|
|
|
}
|
|
|
|
|
SDL_Log("Properties loaded");
|
2026-05-21 21:43:51 -04:00
|
|
|
SUCCEED_RETURN(errctx);
|
2026-05-08 22:01:56 -04:00
|
|
|
}
|
2026-05-13 04:55:19 -04:00
|
|
|
|
|
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_set_property(char *name, char *src)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(e);
|
|
|
|
|
FAIL_ZERO_RETURN(e, name, AKERR_NULLPOINTER, "NULL char *");
|
|
|
|
|
FAIL_ZERO_RETURN(e, src, AKERR_NULLPOINTER, "NULL char *");
|
|
|
|
|
SDL_SetStringProperty(AKGL_REGISTRY_PROPERTIES, name, src);
|
|
|
|
|
SUCCEED_RETURN(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_property(char *name, akgl_String **dest, char *def)
|
|
|
|
|
{
|
|
|
|
|
PREPARE_ERROR(e);
|
|
|
|
|
FAIL_ZERO_RETURN(e, name, AKERR_NULLPOINTER, "NULL char *");
|
|
|
|
|
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "NULL akgl_String *");
|
|
|
|
|
ATTEMPT {
|
|
|
|
|
if ( *dest == NULL ) {
|
|
|
|
|
CATCH(e, akgl_heap_next_string(dest));
|
|
|
|
|
}
|
|
|
|
|
CATCH(e,
|
|
|
|
|
aksl_memcpy(
|
|
|
|
|
(*dest)->data,
|
|
|
|
|
(void *)SDL_GetStringProperty(AKGL_REGISTRY_PROPERTIES, (const char *)name, (const char *)def),
|
|
|
|
|
AKGL_MAX_STRING_LENGTH)
|
|
|
|
|
);
|
|
|
|
|
} CLEANUP {
|
|
|
|
|
} PROCESS(e) {
|
|
|
|
|
} FINISH(e, true);
|
|
|
|
|
SUCCEED_RETURN(e);
|
|
|
|
|
}
|
|
|
|
|
|