diff --git a/src/graphics/sdl/config.c b/src/graphics/sdl/config.c new file mode 100644 index 0000000..a90142e --- /dev/null +++ b/src/graphics/sdl/config.c @@ -0,0 +1,274 @@ +#ifdef ARC_SDL +#include "arc/graphics/config.h" + +#include +#include +#include "arc/std/string.h" +#include "arc/std/errno.h" +#include "arc/graphics/sdl/renderer.h" +#include "arc/graphics/sprite.h" +#include "arc/graphics/sdl/sprite.h" +#include "arc/graphics/spritesheet.h" +#include "arc/graphics/sdl/spritesheet.h" + +// #define ARC_DEFAULT_CONFIG +#include "arc/std/defaults/config.h" + +SDL_Renderer *global_renderer; + +int32_t ARC_SDL_Rect_Read (ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value); +int32_t ARC_SDL_Texture_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value); +int32_t ARC_Spritesheet_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value); +int32_t ARC_Sprite_Read (ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value); + +int32_t ARC_SDL_Rect_Delete (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value); +int32_t ARC_SDL_Texture_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value); +int32_t ARC_Spritesheet_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value); +int32_t ARC_Sprite_Delete (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value); + +void ARC_GraphicsConfig_Init(ARC_Config *config, ARC_Renderer *renderer){ + global_renderer = renderer->renderer; + ARC_ConfigKey_Add(config, (char *)"SDL_Rect" , (ARC_ConfigKeyRead) ARC_SDL_Rect_Read , (ARC_ConfigKeyDelete) ARC_SDL_Rect_Delete ); + ARC_ConfigKey_Add(config, (char *)"SDL_Texture" , (ARC_ConfigKeyRead) ARC_SDL_Texture_Read, (ARC_ConfigKeyDelete) ARC_SDL_Texture_Delete); + ARC_ConfigKey_Add(config, (char *)"ARC_Spritesheet", (ARC_ConfigKeyRead) ARC_Spritesheet_Read, (ARC_ConfigKeyDelete) ARC_Spritesheet_Delete); + ARC_ConfigKey_Add(config, (char *)"ARC_Sprite" , (ARC_ConfigKeyRead) ARC_Sprite_Read , (ARC_ConfigKeyDelete) ARC_Sprite_Delete ); +} + +int32_t ARC_SDL_Texture_Load(const char *path, SDL_Texture **texture){ + IMG_Init(IMG_INIT_PNG); + SDL_Surface *surface = IMG_Load(path); + if(!surface){ + printf("Error: reading png '%s'\nSDL_Image Error: %s", path, IMG_GetError()); + return 1; // GE_SDL_ERRNO_ + } + + *texture = SDL_CreateTextureFromSurface(global_renderer, surface); + + SDL_FreeSurface(surface); + IMG_Quit(); + + return 0; +} + +int32_t ARC_SDL_Rect_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){ + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + if(data[subdata->index] != '{' || data[subdata->index + subdata->length - 1] != '}'){ return ARC_ERRNO_DATA; } + subdata->index++; + subdata->length -= 2; + + uint64_t split; + *value = malloc(sizeof(SDL_Rect)); + + //x + int32_t err = ARC_String_Find(((char *)data) + subdata->index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + ARC_StringSubstr temp = { subdata->index, split }; + ((SDL_Rect *) *value)->x = (int)ARC_String_ToUint64_t(data, &temp); + + //y + temp.index = subdata->index + split + 1; + err = ARC_String_Find(((char *)data) + temp.index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + temp.length = split; + ((SDL_Rect *) *value)->y = (int)ARC_String_ToUint64_t(data, &temp); + + //w + temp.index = temp.index + split + 1; + err = ARC_String_Find(((char *)data) + temp.index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + temp.length = split; + ((SDL_Rect *) *value)->w = (int)ARC_String_ToUint64_t(data, &temp); + + //hhttps://w2g.tv/8r0knvefgpciytccsw + temp = (ARC_StringSubstr){ temp.index + split + 1, subdata->length - split - 1 }; + ((SDL_Rect *) *value)->h = (int)ARC_String_ToUint64_t(data, &temp); + + SDL_Rect *ntemp = ((SDL_Rect *) *value); + return 0; +} + +int32_t ARC_SDL_Texture_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){ + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + ARC_StringSubstr_StripEnds((char *)data, (char *)"\"", subdata); + + char path[subdata->length + 1]; + strncpy(path, data + subdata->index, subdata->length); + path[subdata->length] = 0; + + return ARC_SDL_Texture_Load(path, (SDL_Texture **)value); +} + +int32_t ARC_Spritesheet_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){ + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + if(data[subdata->index] != '{'){ + SDL_Texture *texture = (SDL_Texture *)ARC_Config_GetReference(config, (char *)data, subdata); + if(!texture && data[subdata->index] != '"'){ return ARC_ERRNO_DATA; } + + if(!texture){ + int32_t err = ARC_SDL_Texture_Read(config, data, subdata, (void **)&texture); + if(err){ return ARC_ERRNO_DATA; } + } + + *value = malloc(sizeof(ARC_Spritesheet)); + ((ARC_Spritesheet *) *value)->texture = texture; + ((ARC_Spritesheet *) *value)->size = NULL; + return 0; + } + + if(data[subdata->index + subdata->length - 1] != '}'){ return ARC_ERRNO_DATA; } + subdata->index++; + subdata->length -= 2; //remove the starting { and ending } + + //Texture + uint64_t split; + int32_t err = ARC_String_Find(((char *)data) + subdata->index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + + ARC_StringSubstr temp = { subdata->index, split }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + SDL_Texture *texture = (SDL_Texture *)ARC_Config_GetReference(config, (char *)data, &temp); + if(!texture && data[temp.index] != '"'){ return ARC_ERRNO_DATA; } + + if(!texture){ + err = ARC_SDL_Texture_Read(config, data, &temp, (void **)&texture); + if(err){ return ARC_ERRNO_DATA; } + } + + //uint32_t size + temp = (ARC_StringSubstr){ subdata->index + split + 1, subdata->length - split - 1 }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + uint32_t *size = (uint32_t *)ARC_Config_GetReference(config, (char *)data, &temp); + if(!size){ + ARC_ConfigKey_Read_Uint64_t(config, data, &temp, (void **)&size); + if(err){ return ARC_ERRNO_DATA; } + } + + *value = malloc(sizeof(ARC_Spritesheet)); + ((ARC_Spritesheet *) *value)->texture = texture; + ((ARC_Spritesheet *) *value)->size = size; + + return 0; +} + +int32_t ARC_Sprite_Read(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){ + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + if(data[subdata->index] != '{' || data[subdata->index + subdata->length - 1] != '}'){ return ARC_ERRNO_DATA; } + subdata->index++; + subdata->length -= 2; //remove the starting { and ending } + + uint64_t split; + int32_t err = ARC_String_Find(((char *)data) + subdata->index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + + //spritesheet + ARC_StringSubstr temp = { subdata->index, split }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + ARC_Spritesheet *spritesheet = (ARC_Spritesheet *)ARC_Config_GetReference(config, (char *)data, &temp); + + if(!spritesheet){ + err = ARC_Spritesheet_Read(config, data, &temp, (void **)&spritesheet); + if(err){ return ARC_ERRNO_DATA; } + } + + //bounds + temp = (ARC_StringSubstr){ subdata->index + split + 1, subdata->length - split - 1 }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + SDL_Rect *bounds = (SDL_Rect *)ARC_Config_GetReference(config, (char *)data, &temp); + + if(!bounds){ + ARC_ConfigKey_Read_Uint64_t(config, data, &temp, (void **)&bounds); + if(err){ return ARC_ERRNO_DATA; } + } + + *value = malloc(sizeof(ARC_Sprite)); + ((ARC_Sprite *) *value)->spritesheet = spritesheet; + ((ARC_Sprite *) *value)->bounds = bounds; + + return 0; +} + +int32_t ARC_SDL_Rect_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ + if((SDL_Rect *)value){ free((SDL_Rect *)value); } + return 0; +} + +int32_t ARC_SDL_Texture_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ + //if((SDL_Texture *) value){ SDL_DestroyTexture((SDL_Texture *) value); } + return 0; +} + +int32_t ARC_Spritesheet_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ + ARC_Spritesheet *spritesheet = (ARC_Spritesheet *) value; + if(!data){ //there is no data, kill everything, most likely was called by a data type being destroyed + free(spritesheet); + return 0; + } + + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + if(data[subdata->index] != '{'){ + SDL_Texture *texture = (SDL_Texture *)ARC_Config_GetReference(config, (char *)data, subdata); + if(!texture){ ARC_SDL_Texture_Delete(config, data, subdata, (void *)spritesheet->texture); } + + free(spritesheet); + return 0; + } + + uint64_t split; + int32_t err = ARC_String_Find(((char *)data) + subdata->index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + + ARC_StringSubstr temp = { subdata->index, split }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + SDL_Texture *texture = (SDL_Texture *)ARC_Config_GetReference(config, (char *)data, &temp); + if(!texture){ ARC_SDL_Texture_Delete(config, data, &temp, (void *)spritesheet->texture); } + + temp = (ARC_StringSubstr){ subdata->index + split + 1, subdata->length - split - 1 }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + uint32_t *size = (uint32_t *)ARC_Config_GetReference(config, (char *)data, &temp); + if(!size){ ARC_ConfigKey_Delete_Uint64_t(config, data, &temp, (void *)spritesheet->size); } + + free(spritesheet); + return 0; +} + +int32_t ARC_Sprite_Delete(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ + ARC_Sprite *sprite = (ARC_Sprite *) value; + if(!data){ + free(sprite); + return 0; + } + + ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata); + if(data[subdata->index] != '{' || data[subdata->index + subdata->length - 1] != '}'){ return ARC_ERRNO_DATA; } + subdata->index++; + subdata->length -= 2; //remove the starting { and ending } + + uint64_t split; + int32_t err = ARC_String_Find(((char *)data) + subdata->index, (char *)",", &split); + if(err){ return err; } + if(split == ~((uint64_t)0) || split > subdata->length){ return ARC_ERRNO_DATA; } + + //spritesheet + ARC_StringSubstr temp = { subdata->index, split }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + ARC_Spritesheet *spritesheet = (ARC_Spritesheet *)ARC_Config_GetReference(config, (char *)data, &temp); + if(!spritesheet){ ARC_Spritesheet_Delete(config, data, &temp, (void *)sprite->spritesheet); } + + //bounds + temp = (ARC_StringSubstr){ subdata->index + split + 1, subdata->length - split - 1 }; + ARC_StringSubstr_StripWhitespaceEnds((char *)data, &temp); + SDL_Rect *bounds = (SDL_Rect *)ARC_Config_GetReference(config, (char *)data, &temp); + + if(!bounds){ ARC_SDL_Rect_Delete(config, data, &temp, (void *)sprite->bounds); } + + free(sprite); + return 0; +} + +#endif //ARC_SDL \ No newline at end of file