2025-03-22 23:25:21 -06:00
# include "arc/graphics/config.h"
2025-03-26 04:27:02 -06:00
# include "spritesheet.h"
2025-03-22 23:25:21 -06:00
# 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"
2025-03-26 04:27:02 -06:00
# 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>
2025-03-22 23:25:21 -06:00
void ARC_Config_InitGraphics ( ARC_Config * config , ARC_Renderer * renderer ) {
2025-03-26 04:27:02 -06:00
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 } ) ;
2025-03-22 23:25:21 -06:00
}
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 ;
}
}
2025-03-25 04:54:13 -06:00
void ARC_ConfigType_SpritesheetDestroyFn ( ARC_Config * config , void * type ) {
2025-03-22 23:25:21 -06:00
ARC_Spritesheet_Destroy ( ( ARC_Spritesheet * ) type ) ;
}
void ARC_ConfigType_SpriteCopyFn ( void * * type , ARC_ParserTagToken * parsedData , ARC_Config * config , void * userdata ) {
2025-03-25 04:54:13 -06:00
//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 ) ;
2025-03-26 04:27:02 -06:00
if ( ARC_Vector_GetSize ( valueArgsTagToken - > tagTokens ) = = 1 ) {
//TODO: error here
}
2025-03-25 04:54:13 -06:00
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 ] ;
2025-04-12 00:45:51 -06:00
sprintf ( pointerCString , " %p " , ( void * ) sprite ) ;
2025-03-25 04:54:13 -06:00
2025-03-26 04:27:02 -06:00
/* ~ spritesheet ~ */
2025-03-25 04:54:13 -06:00
//<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 ) ;
}
2025-03-26 04:27:02 -06:00
//set the spritesheet to the sprite
sprite - > spritesheet = spritesheet ;
2025-03-25 19:19:47 -06:00
//cleanup
2025-03-25 04:54:13 -06:00
ARC_String_Destroy ( valueString ) ;
valueString = NULL ;
2025-03-25 19:19:47 -06:00
/* ~ bounds aka frames ~ */
2025-03-26 04:27:02 -06:00
//<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 ) ;
2025-03-25 04:54:13 -06:00
//check if bounds exist
ARC_String_Create ( & valueString , NULL , 0 ) ;
ARC_ParserData_HelperRecurseStringAdd ( & valueString , valueTagToken ) ;
2025-03-26 04:27:02 -06:00
ARC_Array * bounds = ( ARC_Array * ) ARC_Config_Get ( config , valueString ) ;
2025-03-25 04:54:13 -06:00
if ( bounds = = NULL ) {
2025-03-26 04:27:02 -06:00
//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 ) ;
2025-03-25 04:54:13 -06:00
}
2025-03-26 04:27:02 -06:00
//set the bounds to the frames
sprite - > frames = * bounds ;
//cleanup
2025-03-25 04:54:13 -06:00
ARC_String_Destroy ( valueString ) ;
2025-03-25 19:19:47 -06:00
2025-03-26 04:27:02 -06:00
//set the type
2025-03-25 19:19:47 -06:00
* type = sprite ;
2025-03-22 23:25:21 -06:00
}
2025-03-25 04:54:13 -06:00
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 ] ;
2025-04-12 00:45:51 -06:00
sprintf ( pointerCString , " %p " , ( void * ) sprite ) ;
2025-03-25 04:54:13 -06:00
2025-03-26 04:27:02 -06:00
/* ~ spritesheet ~ */
2025-03-25 04:54:13 -06:00
//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 " ) ;
2025-04-11 04:34:00 -06:00
//TODO: FIX THIS
2025-03-25 04:54:13 -06:00
//remove the spritesheet from the config (it won't error if it doesn't exist)
2025-04-11 04:34:00 -06:00
//ARC_Config_RemoveWithCStr(config, spritesheetName->data, ARC_False);
2025-03-26 04:27:02 -06:00
/* ~ 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 " ) ;
2025-04-11 04:34:00 -06:00
//TODO: FIX THIS
2025-03-26 04:27:02 -06:00
//remove the ARC_FRect from the config (it won't error if it doesn't exist)
2025-04-11 04:34:00 -06:00
//ARC_Config_RemoveWithCStr(config, boundsName->data, ARC_False);
2025-03-25 04:54:13 -06:00
//cleanup
2025-03-26 04:27:02 -06:00
ARC_String_Destroy ( boundsName ) ;
2025-03-25 04:54:13 -06:00
ARC_String_Destroy ( spritesheetName ) ;
2025-03-22 23:25:21 -06:00
}