225 lines
8.9 KiB
C
225 lines
8.9 KiB
C
#include "arc/graphics/config.h"
|
|
|
|
#include "spritesheet.h"
|
|
#include "arc/graphics/sprite.h"
|
|
#include "arc/graphics/spritesheet.h"
|
|
#include "arc/math/config.h"
|
|
#include "arc/math/point.h"
|
|
#include "arc/math/rectangle.h"
|
|
#include "arc/std/errno.h"
|
|
#include "arc/std/string.h"
|
|
#include "arc/std/parser/helpers.h"
|
|
#include "arc/std/vector/inline.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <SDL3_image/SDL_image.h>
|
|
|
|
void ARC_Config_InitGraphics(ARC_Config *config, ARC_Renderer *renderer){
|
|
ARC_Config_RegisterTypeWithCStr(config, "ARC_Spritesheet", (ARC_ConfigType){ sizeof(ARC_Spritesheet), ARC_ConfigType_SpritesheetCopyFn, ARC_ConfigType_SpritesheetDestroyFn, renderer});
|
|
ARC_Config_RegisterTypeWithCStr(config, "ARC_Sprite" , (ARC_ConfigType){ sizeof(ARC_Sprite) , ARC_ConfigType_SpriteCopyFn , ARC_ConfigType_SpriteDestroyFn , renderer});
|
|
}
|
|
|
|
void ARC_ConfigType_SpritesheetString(void **type, ARC_ParserTagToken *parsedData, ARC_Config *config, void *userdata){
|
|
ARC_Renderer *renderer = (ARC_Renderer *)userdata;
|
|
|
|
//get the string chars between the quotes
|
|
ARC_ParserTagToken *stringCharsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(parsedData->tagTokens, 1);
|
|
|
|
//get the path
|
|
ARC_String *path;
|
|
ARC_String_Create(&path, NULL, 0);
|
|
ARC_ParserData_HelperRecurseStringAdd(&path, stringCharsTagToken);
|
|
|
|
//read in and set the texture
|
|
ARC_Spritesheet_CreateFromFile((ARC_Spritesheet **)type, renderer, path);
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(path);
|
|
}
|
|
|
|
void ARC_ConfigType_SpritesheetCopyFn(void **type, ARC_ParserTagToken *parsedData, ARC_Config *config, void *userdata){
|
|
ARC_ParserTagToken *valueTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(parsedData->tagTokens, 0);
|
|
|
|
switch(valueTagToken->id){
|
|
case ARC_CONFIG_STRING:
|
|
ARC_ConfigType_SpritesheetString(type, valueTagToken, config, userdata);
|
|
break;
|
|
|
|
case ARC_CONFIG_NESTED_VALUE:
|
|
return;
|
|
|
|
default:
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
ARC_DEBUG_LOG_ERROR("ARC_ConfigType_SpritesheetCopyFn(type, parsedData, config, userdata), cannot use a value that is not a string or nested value. Look at documention for this function for more info");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ARC_ConfigType_SpritesheetDestroyFn(ARC_Config *config, void *type){
|
|
ARC_Spritesheet_Destroy((ARC_Spritesheet *)type);
|
|
}
|
|
|
|
void ARC_ConfigType_SpriteCopyFn(void **type, ARC_ParserTagToken *parsedData, ARC_Config *config, void *userdata){
|
|
//go into the <nestedValue> tag
|
|
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(parsedData->tagTokens, 0);
|
|
if(childTagToken->id != ARC_CONFIG_NESTED_VALUE){
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
ARC_DEBUG_LOG_ERROR("ARC_ConfigType_SpriteCopyFn(type, parsedData, config, userdata), parsed data was not a <nestedValue>");
|
|
*type = NULL;
|
|
return;
|
|
}
|
|
|
|
//<nestedValue> -> OPEN_CURLY_BRACE <whitespace> <valueArgs> <whitespace> CLOSE_CURLY_BRACE
|
|
ARC_ParserTagToken *valueArgsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(childTagToken->tagTokens, 2);
|
|
if(ARC_Vector_GetSize(valueArgsTagToken->tagTokens) == 1){
|
|
//TODO: error here
|
|
}
|
|
|
|
ARC_Sprite *sprite;
|
|
ARC_Sprite_Create(&sprite, NULL, (ARC_Array){ 0, NULL });
|
|
|
|
//really large number in case a system has 64 digit pointer addresses
|
|
char pointerCString[64];
|
|
sprintf(pointerCString, "%p", sprite);
|
|
|
|
/* ~ spritesheet ~ */
|
|
|
|
//<valueArgs> -> <value> <whitespace> COMMA <whitespace> <valueArgs> | <value>
|
|
ARC_ParserTagToken *valueTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueArgsTagToken->tagTokens, 0);
|
|
|
|
//check if spritesheet exist
|
|
ARC_String *valueString;
|
|
ARC_String_Create(&valueString, NULL, 0);
|
|
ARC_ParserData_HelperRecurseStringAdd(&valueString, valueTagToken);
|
|
|
|
ARC_Spritesheet *spritesheet = (ARC_Spritesheet *)ARC_Config_Get(config, valueString);
|
|
if(spritesheet == NULL){
|
|
//create a name based on the type and the sprite pointer to have a unique name for cleanup on remove
|
|
ARC_String *spritesheetName;
|
|
ARC_String_CreateWithStrlen(&spritesheetName, pointerCString);
|
|
ARC_String_AppendCStringWithStrlen(&spritesheetName, "ARC_Spritesheet");
|
|
|
|
//copy the spritesheet
|
|
ARC_Spritesheet *sheet;
|
|
ARC_ConfigType_SpritesheetCopyFn((void *)&sheet, valueTagToken, config, userdata);
|
|
|
|
//add the new spritesheet type to the config
|
|
ARC_Config_AddWithCStr(config, "ARC_Spritesheet", spritesheetName->data, (void *)sheet);
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(spritesheetName);
|
|
}
|
|
|
|
//set the spritesheet to the sprite
|
|
sprite->spritesheet = spritesheet;
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(valueString);
|
|
valueString = NULL;
|
|
|
|
/* ~ bounds aka frames ~ */
|
|
|
|
//<valueArgs> -> <value> <whitespace> COMMA <whitespace> <valueArgs> | <value>
|
|
valueArgsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueArgsTagToken->tagTokens, 4);
|
|
if(ARC_Vector_GetSize(valueArgsTagToken->tagTokens) == 1){
|
|
//TODO: error here
|
|
}
|
|
|
|
//<valueArgs> -> <value> <whitespace> COMMA <whitespace> <valueArgs> | <value>
|
|
valueTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueArgsTagToken->tagTokens, 0);
|
|
|
|
//check if bounds exist
|
|
ARC_String_Create(&valueString, NULL, 0);
|
|
ARC_ParserData_HelperRecurseStringAdd(&valueString, valueTagToken);
|
|
|
|
ARC_Array *bounds = (ARC_Array *)ARC_Config_Get(config, valueString);
|
|
if(bounds == NULL){
|
|
//create a temporary vector to read in the array
|
|
ARC_VectorInline *typeVector;
|
|
ARC_VectorInline_Create(&typeVector, sizeof(ARC_FRect), NULL, NULL);
|
|
|
|
//<value> -> <variable> | <float> | <numberSign> | <string> | <nestedValue>
|
|
valueArgsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueTagToken->tagTokens, 0);
|
|
|
|
//<valueArgs> -> <value> <whitespace> COMMA <whitespace> <valueArgs> | <value>
|
|
while(valueArgsTagToken->id == ARC_CONFIG_VALUE_ARGS){
|
|
valueTagToken = ARC_Vector_Get(valueArgsTagToken->tagTokens, 0);
|
|
|
|
//copy the type and store it in the vector
|
|
void *typeData = NULL;
|
|
ARC_ConfigType_FRectCopyFn(&typeData, valueTagToken, config, userdata);
|
|
ARC_VectorInline_Add(typeVector, typeData);
|
|
|
|
//if this value args was the last one break
|
|
if(ARC_Vector_GetSize(valueArgsTagToken->tagTokens) == 1){
|
|
break;
|
|
}
|
|
|
|
//get the next valueArgs
|
|
valueArgsTagToken = ARC_Vector_Get(valueArgsTagToken->tagTokens, 4);
|
|
}
|
|
|
|
//copy the data in an ARC_Array
|
|
ARC_Array typeVectorArray = ARC_VectorInline_GetData(typeVector);
|
|
bounds = (ARC_Array *)malloc(sizeof(ARC_Array));
|
|
bounds->size = typeVectorArray.size;
|
|
bounds->data = NULL;
|
|
|
|
if(typeVectorArray.size != 0){
|
|
//copy the vector into the array's data
|
|
bounds->data = (void *)malloc(sizeof(ARC_FRect) * typeVectorArray.size);
|
|
memcpy(bounds->data, typeVectorArray.data, typeVectorArray.size);
|
|
}
|
|
|
|
//create a name based on the type and the sprite pointer to have a unique name for cleanup on remove
|
|
ARC_String *boundsName;
|
|
ARC_String_CreateWithStrlen(&boundsName, pointerCString);
|
|
ARC_String_AppendCStringWithStrlen(&boundsName, "ARC_FRect");
|
|
|
|
//add the new ARC_FRect as ARC_Array type to the config
|
|
ARC_Config_AddWithCStr(config, "ARC_FRect", boundsName->data, (void *)bounds);
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(boundsName);
|
|
}
|
|
|
|
//set the bounds to the frames
|
|
sprite->frames = *bounds;
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(valueString);
|
|
|
|
//set the type
|
|
*type = sprite;
|
|
}
|
|
|
|
void ARC_ConfigType_SpriteDestroyFn(ARC_Config *config, void *type){
|
|
ARC_Sprite *sprite = (ARC_Sprite *)type;
|
|
|
|
//really large number in case a system has 64 digit pointer addresses
|
|
char pointerCString[64];
|
|
sprintf(pointerCString, "%p", sprite);
|
|
|
|
/* ~ spritesheet ~ */
|
|
//create a name based on the type and the sprite pointer to have a unique name for cleanup on remove
|
|
ARC_String *spritesheetName;
|
|
ARC_String_CreateWithStrlen(&spritesheetName, pointerCString);
|
|
ARC_String_AppendCStringWithStrlen(&spritesheetName, "ARC_Spritesheet");
|
|
|
|
//remove the spritesheet from the config (it won't error if it doesn't exist)
|
|
ARC_Config_RemoveWithCStr(config, spritesheetName->data, ARC_False);
|
|
|
|
/* ~ ARC_FRect Array ~ */
|
|
//create a name based on the type and the sprite pointer to have a unique name for cleanup on remove
|
|
ARC_String *boundsName;
|
|
ARC_String_CreateWithStrlen(&boundsName, pointerCString);
|
|
ARC_String_AppendCStringWithStrlen(&boundsName, "ARC_FRect");
|
|
|
|
//remove the ARC_FRect from the config (it won't error if it doesn't exist)
|
|
ARC_Config_RemoveWithCStr(config, boundsName->data, ARC_False);
|
|
|
|
//cleanup
|
|
ARC_String_Destroy(boundsName);
|
|
ARC_String_Destroy(spritesheetName);
|
|
|
|
}
|