#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 #include #include 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 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 "); *type = NULL; return; } // -> OPEN_CURLY_BRACE 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 ~ */ // -> COMMA | 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 ~ */ // -> COMMA | valueArgsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueArgsTagToken->tagTokens, 4); if(ARC_Vector_GetSize(valueArgsTagToken->tagTokens) == 1){ //TODO: error here } // -> COMMA | 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); // -> | | | | valueArgsTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(valueTagToken->tagTokens, 0); // -> COMMA | 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); }