From d9dcb546eed546b86f30ac1decfdcb9a971fbbb5 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 15:00:53 -0300 Subject: [PATCH 01/10] Refactor R_ParseSpriteInfo Co-authored-by: James R <justsomejames2@gmail.com> --- src/r_picformats.c | 155 +++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index a45c143b01..047068d5a7 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1479,19 +1479,61 @@ boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *to #endif #endif -// -// R_ParseSpriteInfoFrame -// -// Parse a SPRTINFO frame. -// -static void R_ParseSpriteInfoFrame(spriteinfo_t *info) +struct ParseSpriteInfoState { + boolean spr2; + spriteinfo_t *info; + spritenum_t sprnum; + playersprite_t spr2num; + INT32 skinnumbers[MAXSKINS]; + INT32 foundskins; +}; + +static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) +{ + char *sprinfoToken; + size_t sprinfoTokenLength; + + INT32 skinnum; + char *skinName = NULL; + + // Skin name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); + } + + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); + + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + + parser->skinnumbers[parser->foundskins] = skinnum; + parser->foundskins++; + + Z_Free(sprinfoToken); +} + +static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum) +{ + skin_t *skin = skins[skinnum]; + spriteinfo_t *sprinfo = skin->sprinfo; + + M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); +} + +static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) { char *sprinfoToken; size_t sprinfoTokenLength; char *frameChar = NULL; - UINT8 frameFrame = 0xFF; - INT16 frameXPivot = 0; - INT16 frameYPivot = 0; + UINT8 frameID = 0xFF; // Sprite identifier sprinfoToken = M_GetToken(NULL); @@ -1507,7 +1549,7 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) else frameChar = sprinfoToken; - frameFrame = R_Char2Frame(frameChar[0]); + frameID = R_Char2Frame(frameChar[0]); Z_Free(sprinfoToken); // Left Curly Brace @@ -1530,13 +1572,13 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); - frameXPivot = atoi(sprinfoToken); + parser->info->pivot[frameID].x = atoi(sprinfoToken); } else if (stricmp(sprinfoToken, "YPIVOT")==0) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); - frameYPivot = atoi(sprinfoToken); + parser->info->pivot[frameID].y = atoi(sprinfoToken); } else if (stricmp(sprinfoToken, "ROTAXIS")==0) { @@ -1555,9 +1597,22 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) Z_Free(sprinfoToken); } - // set fields - info->pivot[frameFrame].x = frameXPivot; - info->pivot[frameFrame].y = frameYPivot; + if (parser->spr2) + { + INT32 i; + + if (!parser->foundskins) + I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); + + for (i = 0; i < parser->foundskins; i++) + { + copy_to_skin(parser, parser->skinnumbers[i]); + } + } + else + { + M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + } } // @@ -1567,15 +1622,18 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) // static void R_ParseSpriteInfo(boolean spr2) { - spriteinfo_t *info; char *sprinfoToken; size_t sprinfoTokenLength; char newSpriteName[MAXSPRITENAME + 1]; // no longer dynamically allocated - spritenum_t sprnum = NUMSPRITES; - playersprite_t spr2num = NUMPLAYERSPRITES; + + struct ParseSpriteInfoState parser = { + .spr2 = spr2, + .sprnum = NUMSPRITES, + .spr2num = NUMPLAYERSPRITES, + .foundskins = 0, + }; + INT32 i; - UINT8 *skinnumbers = NULL; - INT32 foundskins = 0; // Sprite name sprinfoToken = M_GetToken(NULL); @@ -1583,17 +1641,19 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } + sprinfoTokenLength = strlen(sprinfoToken); if (sprinfoTokenLength > MAXSPRITENAME) I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" is longer than %d characters", sprinfoToken, MAXSPRITENAME); strcpy(newSpriteName, sprinfoToken); strupr(newSpriteName); // Just do this now so we don't have to worry about it + Z_Free(sprinfoToken); if (!spr2) { - sprnum = R_GetSpriteNumByName(newSpriteName); - if (sprnum == NUMSPRITES) + parser.sprnum = R_GetSpriteNumByName(newSpriteName); + if (parser.sprnum == NUMSPRITES) I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); } else @@ -1604,15 +1664,15 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unknown sprite2 name \"%s\"", newSpriteName); if (!memcmp(newSpriteName,spr2names[i],4)) { - spr2num = i; + parser.spr2num = i; break; } } } // allocate a spriteinfo - info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - info->available = true; + parser.info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + parser.info->available = true; // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1632,54 +1692,17 @@ static void R_ParseSpriteInfo(boolean spr2) { if (stricmp(sprinfoToken, "SKIN")==0) { - INT32 skinnum; - char *skinName = NULL; if (!spr2) I_Error("Error parsing SPRTINFO lump: \"SKIN\" token found outside of a sprite2 definition"); Z_Free(sprinfoToken); - // Skin name - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) - { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); - } - - // copy skin name yada yada - sprinfoTokenLength = strlen(sprinfoToken); - skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); - skinName[sprinfoTokenLength] = '\0'; - strlwr(skinName); - Z_Free(sprinfoToken); - - skinnum = R_SkinAvailable(skinName); - if (skinnum == -1) - I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - - if (skinnumbers == NULL) - skinnumbers = Z_Malloc(sizeof(UINT8) * numskins, PU_STATIC, NULL); - skinnumbers[foundskins] = (UINT8)skinnum; - foundskins++; + R_ParseSpriteInfoSkin(&parser); } else if (stricmp(sprinfoToken, "FRAME")==0) { - R_ParseSpriteInfoFrame(info); Z_Free(sprinfoToken); - if (spr2) - { - if (!foundskins) - I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); - for (i = 0; i < foundskins; i++) - { - skin_t *skin = skins[skinnumbers[i]]; - spriteinfo_t *sprinfo = skin->sprinfo; - M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); - } - } - else - M_Memcpy(&spriteinfo[sprnum], info, sizeof(spriteinfo_t)); + R_ParseSpriteInfoFrame(&parser); } else { @@ -1699,9 +1722,7 @@ static void R_ParseSpriteInfo(boolean spr2) } Z_Free(sprinfoToken); - Z_Free(info); - if (skinnumbers) - Z_Free(skinnumbers); + Z_Free(parser.info); } // -- GitLab From a464da0af1715fe26ae1a212fff8886d56942c13 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 15:59:14 -0300 Subject: [PATCH 02/10] Change spriteinfo_t.available to bit array Co-authored-by: James R <justsomejames2@gmail.com> --- src/deh_soc.c | 2 +- src/lua_infolib.c | 55 ++++++++++++++++++++++++++++--------------- src/r_patchrotation.c | 2 +- src/r_picformats.c | 8 ++++++- src/r_picformats.h | 8 ++++--- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 343beb3012..b9cb3adb9b 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -955,7 +955,6 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) // allocate a spriteinfo spriteinfo_t *info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - info->available = true; do { @@ -1074,6 +1073,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) // read sprite frame and store it in the spriteinfo_t struct readspriteframe(f, info, frame); + set_bit_array(info->available, frame); if (sprite2) { INT32 i; diff --git a/src/lua_infolib.c b/src/lua_infolib.c index a65ee23ebc..922b2068d6 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2024 by Sonic Team Junior. +// Copyright (C) 2012-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -236,6 +236,11 @@ static int lib_spr2namelen(lua_State *L) // SPRITE INFO // ///////////////// +struct PivotFrame { + spriteinfo_t *sprinfo; + UINT8 frame; +}; + // spriteinfo[] static int lib_getSpriteInfo(lua_State *L) { @@ -299,7 +304,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in default: TYPEERROR("pivot value", LUA_TNUMBER, lua_type(L, stk+2)) } - // finally set omg!!!!!!!!!!!!!!!!!! + // Set it if (ikey == 1 || (key && fastcmp(key, "x"))) pivot[idx].x = (INT32)value; else if (ikey == 2 || (key && fastcmp(key, "y"))) @@ -351,7 +356,7 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1); // the values in pivot[] are also tables if (PopPivotSubTable(info->pivot, L, stk+2, idx)) - info->available = true; + set_bit_array(info->available, idx); lua_pop(L, 1); } @@ -426,7 +431,7 @@ static int spriteinfo_get(lua_State *L) { // bypass LUA_PushUserdata void **userdata = lua_newuserdata(L, sizeof(void *)); - *userdata = &sprinfo->pivot; + *userdata = sprinfo; luaL_getmetatable(L, META_PIVOTLIST); lua_setmetatable(L, -2); @@ -465,9 +470,8 @@ static int spriteinfo_set(lua_State *L) // pivot[] is userdata else if (lua_isuserdata(L, 1)) { - spriteframepivot_t *pivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - memcpy(&sprinfo->pivot, pivot, sizeof(spriteframepivot_t)); - sprinfo->available = true; // Just in case? + spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + memcpy(sprinfo, copyinfo, sizeof(spriteinfo_t)); } } else @@ -490,8 +494,8 @@ static int spriteinfo_num(lua_State *L) // framepivot_t static int pivotlist_get(lua_State *L) { - void **userdata; - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + struct PivotFrame *container; + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); const char *field = luaL_checkstring(L, 2); UINT8 frame; @@ -500,8 +504,9 @@ static int pivotlist_get(lua_State *L) luaL_error(L, "invalid frame %s", field); // bypass LUA_PushUserdata - userdata = lua_newuserdata(L, sizeof(void *)); - *userdata = &framepivot[frame]; + container = lua_newuserdata(L, sizeof *container); + container->sprinfo = sprinfo; + container->frame = frame; luaL_getmetatable(L, META_FRAMEPIVOT); lua_setmetatable(L, -2); @@ -511,11 +516,10 @@ static int pivotlist_get(lua_State *L) static int pivotlist_set(lua_State *L) { - // Because I already know it's a spriteframepivot_t anyway - spriteframepivot_t *pivotlist = *((spriteframepivot_t **)lua_touserdata(L, 1)); - //spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); const char *field = luaL_checkstring(L, 2); UINT8 frame; + int okcool = 0; if (!lua_lumploading) return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!"); @@ -530,14 +534,18 @@ static int pivotlist_set(lua_State *L) // pivot[] is a table if (lua_istable(L, 3)) - return PopPivotSubTable(pivotlist, L, 3, frame); + okcool = PopPivotSubTable(sprinfo->pivot, L, 3, frame); // pivot[] is userdata else if (lua_isuserdata(L, 3)) { - spriteframepivot_t *copypivot = *((spriteframepivot_t **)luaL_checkudata(L, 3, META_FRAMEPIVOT)); - memcpy(&pivotlist[frame], copypivot, sizeof(spriteframepivot_t)); + struct PivotFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); + memcpy(&sprinfo->pivot[frame], &container->sprinfo->pivot[container->frame], sizeof(spriteframepivot_t)); + okcool = 1; } + if (okcool) + set_bit_array(sprinfo->available, frame); + return 0; } @@ -549,7 +557,8 @@ static int pivotlist_num(lua_State *L) static int framepivot_get(lua_State *L) { - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; const char *field = luaL_checkstring(L, 2); I_Assert(framepivot != NULL); @@ -572,7 +581,9 @@ static int framepivot_get(lua_State *L) static int framepivot_set(lua_State *L) { - spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; + UINT8 *available = container->sprinfo->available; const char *field = luaL_checkstring(L, 2); if (!lua_lumploading) @@ -585,9 +596,15 @@ static int framepivot_set(lua_State *L) I_Assert(framepivot != NULL); if (fastcmp("x", field)) + { framepivot->x = luaL_checkinteger(L, 3); + set_bit_array(available, container->frame); + } else if (fastcmp("y", field)) + { framepivot->y = luaL_checkinteger(L, 3); + set_bit_array(available, container->frame); + } // TODO: 2.3: delete else if (fastcmp("rotaxis", field)) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 989665d741..35b1e5d86d 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -96,7 +96,7 @@ patch_t *Patch_GetRotatedSprite( patch = W_CachePatchNum(lump, PU_SPRITE); - if (sprinfo->available) + if (R_IsSpriteInfoAvailable(sprinfo, frame)) { xpivot = sprinfo->pivot[frame].x; ypivot = sprinfo->pivot[frame].y; diff --git a/src/r_picformats.c b/src/r_picformats.c index 047068d5a7..b9c34f33d3 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1597,6 +1597,8 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) Z_Free(sprinfoToken); } + set_bit_array(parser->info->available, frameID); + if (parser->spr2) { INT32 i; @@ -1672,7 +1674,6 @@ static void R_ParseSpriteInfo(boolean spr2) // allocate a spriteinfo parser.info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); - parser.info->available = true; // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1788,3 +1789,8 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) R_ParseSPRTINFOLump(wadnum, i); } } + +boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT8 frame) +{ + return info && in_bit_array(info->available, frame); +} diff --git a/src/r_picformats.h b/src/r_picformats.h index 123dda976c..653a2eab3a 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2024 by Lactozilla. -// Copyright (C) 2019-2024 by Sonic Team Junior. +// Copyright (C) 2018-2025 by Lactozilla. +// Copyright (C) 2019-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -100,8 +100,8 @@ typedef struct typedef struct { + UINT8 available[BIT_ARRAY_SIZE(MAXFRAMENUM)]; spriteframepivot_t pivot[MAXFRAMENUM]; - boolean available; } spriteinfo_t; // PNG support @@ -126,4 +126,6 @@ extern spriteinfo_t spriteinfo[NUMSPRITES]; void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); +boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT8 frame); + #endif // __R_PICFORMATS__ -- GitLab From 4aa8eb4bf390dba87df6db90ec415f779f333c36 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 16:04:09 -0300 Subject: [PATCH 03/10] Update and extend R_ParseSpriteInfo for default pivot - Set default pivot with DEFAULT block - Use wildcard star (*) with Sprite/Sprite2Info/Skin to iterate over all sprites and/or skins Co-authored-by: James R <justsomejames2@gmail.com> --- src/r_patchrotation.c | 5 ++ src/r_picformats.c | 146 ++++++++++++++++++++++++++++++------------ src/r_picformats.h | 8 ++- 3 files changed, 115 insertions(+), 44 deletions(-) diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 35b1e5d86d..61129d608c 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -101,6 +101,11 @@ patch_t *Patch_GetRotatedSprite( xpivot = sprinfo->pivot[frame].x; ypivot = sprinfo->pivot[frame].y; } + else if (R_IsSpriteInfoAvailable(sprinfo, SPRINFO_DEFAULT_FRAME)) + { + xpivot = sprinfo->pivot[SPRINFO_DEFAULT_FRAME].x; + ypivot = sprinfo->pivot[SPRINFO_DEFAULT_FRAME].y; + } else { xpivot = patch->leftoffset; diff --git a/src/r_picformats.c b/src/r_picformats.c index b9c34f33d3..e0c6dd599a 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1484,10 +1484,14 @@ struct ParseSpriteInfoState { spriteinfo_t *info; spritenum_t sprnum; playersprite_t spr2num; + boolean any; INT32 skinnumbers[MAXSKINS]; INT32 foundskins; }; +#define PARSER_FRAME (false) +#define PARSER_DEFAULT (true) + static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) { char *sprinfoToken; @@ -1503,19 +1507,26 @@ static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); } - // copy skin name yada yada - sprinfoTokenLength = strlen(sprinfoToken); - skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); - skinName[sprinfoTokenLength] = '\0'; - strlwr(skinName); - - skinnum = R_SkinAvailable(skinName); - if (skinnum == -1) - I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - - parser->skinnumbers[parser->foundskins] = skinnum; - parser->foundskins++; + if (strcmp(sprinfoToken, "*")==0) // All skins + { + parser->foundskins = -1; + } + else + { + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); + + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + + parser->skinnumbers[parser->foundskins] = skinnum; + parser->foundskins++; + } Z_Free(sprinfoToken); } @@ -1525,32 +1536,48 @@ static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum) skin_t *skin = skins[skinnum]; spriteinfo_t *sprinfo = skin->sprinfo; - M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); + if (parser->any) + { + playersprite_t spr2num; + + for (spr2num = 0; spr2num < NUMPLAYERSPRITES; ++spr2num) + { + M_Memcpy(&sprinfo[spr2num], parser->info, sizeof(spriteinfo_t)); + } + } + else + { + M_Memcpy(&sprinfo[parser->spr2num], parser->info, sizeof(spriteinfo_t)); + } } -static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) +static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean all) { char *sprinfoToken; size_t sprinfoTokenLength; - char *frameChar = NULL; - UINT8 frameID = 0xFF; + UINT16 frameID = 0; - // Sprite identifier - sprinfoToken = M_GetToken(NULL); - if (sprinfoToken == NULL) + if (all) { - I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); - } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 1) - { - I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + frameID = SPRINFO_DEFAULT_FRAME; } else - frameChar = sprinfoToken; + { + // Sprite identifier + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); + } + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 1) + { + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + } - frameID = R_Char2Frame(frameChar[0]); - Z_Free(sprinfoToken); + frameID = R_Char2Frame(sprinfoToken[0]); + Z_Free(sprinfoToken); + } // Left Curly Brace sprinfoToken = M_GetToken(NULL); @@ -1606,14 +1633,36 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser) if (!parser->foundskins) I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); - for (i = 0; i < parser->foundskins; i++) + if (parser->foundskins < 0) { - copy_to_skin(parser, parser->skinnumbers[i]); + for (i = 0; i < numskins; i++) + { + copy_to_skin(parser, i); + } + } + else + { + for (i = 0; i < parser->foundskins; i++) + { + copy_to_skin(parser, parser->skinnumbers[i]); + } } } else { - M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + if (parser->any) + { + spritenum_t sprnum; + + for (sprnum = 0; sprnum < NUMSPRITES; ++sprnum) + { + M_Memcpy(&spriteinfo[sprnum], parser->info, sizeof(spriteinfo_t)); + } + } + else + { + M_Memcpy(&spriteinfo[parser->sprnum], parser->info, sizeof(spriteinfo_t)); + } } } @@ -1632,6 +1681,7 @@ static void R_ParseSpriteInfo(boolean spr2) .spr2 = spr2, .sprnum = NUMSPRITES, .spr2num = NUMPLAYERSPRITES, + .any = false, .foundskins = 0, }; @@ -1644,15 +1694,24 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength > MAXSPRITENAME) - I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" is longer than %d characters", sprinfoToken, MAXSPRITENAME); - strcpy(newSpriteName, sprinfoToken); - strupr(newSpriteName); // Just do this now so we don't have to worry about it + if (!strcmp(sprinfoToken, "*")) // All sprites + { + parser.any = true; + } + else + { + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength > MAXSPRITENAME) + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" is longer than %d characters", sprinfoToken, MAXSPRITENAME); + strcpy(newSpriteName, sprinfoToken); + strupr(newSpriteName); // Just do this now so we don't have to worry about it + } Z_Free(sprinfoToken); - if (!spr2) + if (parser.any) + ; + else if (!spr2) { parser.sprnum = R_GetSpriteNumByName(newSpriteName); if (parser.sprnum == NUMSPRITES) @@ -1703,7 +1762,12 @@ static void R_ParseSpriteInfo(boolean spr2) else if (stricmp(sprinfoToken, "FRAME")==0) { Z_Free(sprinfoToken); - R_ParseSpriteInfoFrame(&parser); + R_ParseSpriteInfoFrame(&parser, PARSER_FRAME); + } + else if (stricmp(sprinfoToken, "DEFAULT")==0) + { + Z_Free(sprinfoToken); + R_ParseSpriteInfoFrame(&parser, PARSER_DEFAULT); } else { @@ -1790,7 +1854,7 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) } } -boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT8 frame) +boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT16 frame) { - return info && in_bit_array(info->available, frame); + return info && frame <= SPRINFO_DEFAULT_FRAME && in_bit_array(info->available, frame); } diff --git a/src/r_picformats.h b/src/r_picformats.h index 653a2eab3a..1388be0134 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -98,10 +98,12 @@ typedef struct INT32 x, y; } spriteframepivot_t; +#define SPRINFO_DEFAULT_FRAME (MAXFRAMENUM) + typedef struct { - UINT8 available[BIT_ARRAY_SIZE(MAXFRAMENUM)]; - spriteframepivot_t pivot[MAXFRAMENUM]; + UINT8 available[BIT_ARRAY_SIZE(MAXFRAMENUM + 1)]; // 1 extra for default_frame + spriteframepivot_t pivot[MAXFRAMENUM + 1]; } spriteinfo_t; // PNG support @@ -126,6 +128,6 @@ extern spriteinfo_t spriteinfo[NUMSPRITES]; void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); -boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT8 frame); +boolean R_IsSpriteInfoAvailable(spriteinfo_t *info, UINT16 frame); #endif // __R_PICFORMATS__ -- GitLab From d812a085afc7dbdbff0a880479ee6a04586e60ad Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 18:36:47 -0300 Subject: [PATCH 04/10] Implement frame ranges for SpriteInfo --- src/lua_infolib.c | 14 +++--- src/r_picformats.c | 108 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 108 insertions(+), 14 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 922b2068d6..89780afa60 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -268,7 +268,7 @@ static int lib_getSpriteInfo(lua_State *L) #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e); #define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2))) -static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx) +static int PopPivotSubTable(spriteinfo_t *info, lua_State *L, int stk, int idx) { int okcool = 0; switch (lua_type(L, stk)) @@ -306,9 +306,9 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in } // Set it if (ikey == 1 || (key && fastcmp(key, "x"))) - pivot[idx].x = (INT32)value; + info->pivot[idx].x = (INT32)value; else if (ikey == 2 || (key && fastcmp(key, "y"))) - pivot[idx].y = (INT32)value; + info->pivot[idx].y = (INT32)value; // TODO: 2.3: Delete else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") @@ -355,7 +355,7 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) if ((idx < 0) || (idx >= MAXFRAMENUM)) return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1); // the values in pivot[] are also tables - if (PopPivotSubTable(info->pivot, L, stk+2, idx)) + if (PopPivotSubTable(info, L, stk+2, idx)) set_bit_array(info->available, idx); lua_pop(L, 1); } @@ -534,12 +534,14 @@ static int pivotlist_set(lua_State *L) // pivot[] is a table if (lua_istable(L, 3)) - okcool = PopPivotSubTable(sprinfo->pivot, L, 3, frame); + okcool = PopPivotSubTable(sprinfo, L, 3, frame); // pivot[] is userdata else if (lua_isuserdata(L, 3)) { struct PivotFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); - memcpy(&sprinfo->pivot[frame], &container->sprinfo->pivot[container->frame], sizeof(spriteframepivot_t)); + memcpy(&sprinfo->pivot[frame], + &container->sprinfo->pivot[container->frame], + sizeof(spriteframepivot_t)); okcool = 1; } diff --git a/src/r_picformats.c b/src/r_picformats.c index e0c6dd599a..8aa3eab516 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1551,11 +1551,39 @@ static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum) } } +struct ParsedSpriteInfoFrame { + INT32 pivotX; + INT32 pivotY; +}; + +static boolean define_spriteinfo_frame(struct ParsedSpriteInfoFrame *frame, spriteinfo_t *dest, UINT16 index) +{ + boolean defined = false; + + if (frame->pivotX != INT32_MAX) + { + dest->pivot[index].x = frame->pivotX; + defined = true; + } + if (frame->pivotY != INT32_MAX) + { + dest->pivot[index].y = frame->pivotY; + defined = true; + } + + return defined; +} + static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean all) { char *sprinfoToken; - size_t sprinfoTokenLength; UINT16 frameID = 0; + UINT16 frameEndID = UINT16_MAX; + + struct ParsedSpriteInfoFrame frame = { + .pivotX = INT32_MAX, + .pivotY = INT32_MAX + }; if (all) { @@ -1564,18 +1592,65 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean else { // Sprite identifier + char *frameToken = NULL; + char *startRange = NULL; + char *endRange = NULL; sprinfoToken = M_GetToken(NULL); if (sprinfoToken == NULL) { I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); } - sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 1) + + // Parse range + frameToken = Z_StrDup(sprinfoToken); + startRange = frameToken; + endRange = strstr(frameToken, ".."); + if (endRange != NULL) { - I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + *endRange = '\0'; + endRange += 2; + if (strstr(endRange, ".")) + I_Error("Error parsing SPRTINFO lump: Invalid range \"%s\"",sprinfoToken); + } + + int parseStartFrameID = -1; + if (!M_StringToNumber(startRange, &parseStartFrameID)) + { + if (strlen(startRange) != 1) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",startRange); + parseStartFrameID = R_Char2Frame(startRange[0]); + if (parseStartFrameID == 255) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",startRange); + } + if (parseStartFrameID < 0 || parseStartFrameID >= MAXFRAMENUM) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",startRange); + frameID = (UINT16)parseStartFrameID; + + // Parse range ID + if (endRange != NULL) + { + int parseEndFrameID = -1; + if (!M_StringToNumber(endRange, &parseEndFrameID)) + { + if (strlen(endRange) != 1) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",endRange); + parseEndFrameID = R_Char2Frame(endRange[0]); + if (parseEndFrameID == 255) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",endRange); + } + if (parseEndFrameID < 0 || parseEndFrameID >= MAXFRAMENUM) + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",endRange); + frameEndID = (UINT16)parseEndFrameID; + } + + Z_Free(frameToken); + + // Validate the range + if (frameEndID != UINT16_MAX && frameID >= frameEndID) + { + I_Error("Error parsing SPRTINFO lump: Invalid range \"%s\"",sprinfoToken); } - frameID = R_Char2Frame(sprinfoToken[0]); Z_Free(sprinfoToken); } @@ -1599,13 +1674,13 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); - parser->info->pivot[frameID].x = atoi(sprinfoToken); + frame.pivotX = atoi(sprinfoToken); } else if (stricmp(sprinfoToken, "YPIVOT")==0) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); - parser->info->pivot[frameID].y = atoi(sprinfoToken); + frame.pivotY = atoi(sprinfoToken); } else if (stricmp(sprinfoToken, "ROTAXIS")==0) { @@ -1624,7 +1699,24 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean Z_Free(sprinfoToken); } - set_bit_array(parser->info->available, frameID); + // Apply to the specified range of frames + if (frameEndID != UINT16_MAX) + { + for (UINT16 frameIter = frameID; frameIter <= frameEndID; frameIter++) + { + if (define_spriteinfo_frame(&frame, parser->info, frameIter)) + { + set_bit_array(parser->info->available, frameIter); + } + } + } + else + { + if (define_spriteinfo_frame(&frame, parser->info, frameID)) + { + set_bit_array(parser->info->available, frameID); + } + } if (parser->spr2) { -- GitLab From 1d100f9c898bdbdf305fbcb4463e8a312795f5ca Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 18:50:56 -0300 Subject: [PATCH 05/10] Lua spriteinfo default pivot support Co-authored-by: James R <justsomejames2@gmail.com> --- src/lua_infolib.c | 51 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 89780afa60..c714a6382f 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -238,9 +238,36 @@ static int lib_spr2namelen(lua_State *L) struct PivotFrame { spriteinfo_t *sprinfo; - UINT8 frame; + UINT16 frame; }; +static UINT16 GetSpriteInfoFrame(lua_State *L, int idx) +{ + if (lua_type(L, idx) == LUA_TSTRING) + { + const char *field = luaL_checkstring(L, idx); + + if (fastcmp("default", field)) + { + return SPRINFO_DEFAULT_FRAME; + } + else + { + UINT8 frame = R_Char2Frame(field[0]); + if (frame == 255) + return luaL_error(L, "invalid frame %s", field); + return (UINT16)frame; + } + } + else + { + int frameID = luaL_checknumber(L, idx); + if (frameID < 0 || frameID >= MAXFRAMENUM) + return luaL_error(L, "frame %d out of range (0 - %d)", frameID, MAXFRAMENUM - 1); + return (UINT16)frameID; + } +} + // spriteinfo[] static int lib_getSpriteInfo(lua_State *L) { @@ -339,21 +366,15 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) while (lua_next(L, stk)) { int idx = 0; - const char *framestr = NULL; switch (lua_type(L, stk+1)) { case LUA_TSTRING: - framestr = lua_tostring(L, stk+1); - idx = R_Char2Frame(framestr[0]); - break; case LUA_TNUMBER: - idx = lua_tonumber(L, stk+1); + idx = GetSpriteInfoFrame(L, stk+1); break; default: TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); } - if ((idx < 0) || (idx >= MAXFRAMENUM)) - return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1); // the values in pivot[] are also tables if (PopPivotSubTable(info, L, stk+2, idx)) set_bit_array(info->available, idx); @@ -496,12 +517,7 @@ static int pivotlist_get(lua_State *L) { struct PivotFrame *container; spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - const char *field = luaL_checkstring(L, 2); - UINT8 frame; - - frame = R_Char2Frame(field[0]); - if (frame == 255) - luaL_error(L, "invalid frame %s", field); + UINT16 frame = GetSpriteInfoFrame(L, 2); // bypass LUA_PushUserdata container = lua_newuserdata(L, sizeof *container); @@ -517,8 +533,7 @@ static int pivotlist_get(lua_State *L) static int pivotlist_set(lua_State *L) { spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - const char *field = luaL_checkstring(L, 2); - UINT8 frame; + UINT16 frame; int okcool = 0; if (!lua_lumploading) @@ -528,9 +543,7 @@ static int pivotlist_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!"); - frame = R_Char2Frame(field[0]); - if (frame == 255) - luaL_error(L, "invalid frame %s", field); + frame = GetSpriteInfoFrame(L, 2); // pivot[] is a table if (lua_istable(L, 3)) -- GitLab From 8aeb048f0aa11e573d910d42f9117d936751919d Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Thu, 30 Jan 2025 14:49:07 -0300 Subject: [PATCH 06/10] Refactor spriteframepivot_t into spriteinfoframe_t --- src/deh_soc.c | 4 ++-- src/lua_infolib.c | 12 ++++++------ src/r_patchrotation.c | 8 ++++---- src/r_picformats.c | 10 +++++----- src/r_picformats.h | 7 ++++++- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index b9cb3adb9b..001c6d2896 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -925,9 +925,9 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) value = atoi(word2); // used for numerical settings if (fastcmp(word, "XPIVOT")) - sprinfo->pivot[frame].x = value; + sprinfo->frames[frame].pivot.x = value; else if (fastcmp(word, "YPIVOT")) - sprinfo->pivot[frame].y = value; + sprinfo->frames[frame].pivot.y = value; // TODO: 2.3: Delete else if (fastcmp(word, "ROTAXIS")) deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed."); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index c714a6382f..44ced92e94 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -333,9 +333,9 @@ static int PopPivotSubTable(spriteinfo_t *info, lua_State *L, int stk, int idx) } // Set it if (ikey == 1 || (key && fastcmp(key, "x"))) - info->pivot[idx].x = (INT32)value; + info->frames[idx].pivot.x = (INT32)value; else if (ikey == 2 || (key && fastcmp(key, "y"))) - info->pivot[idx].y = (INT32)value; + info->frames[idx].pivot.y = (INT32)value; // TODO: 2.3: Delete else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") @@ -552,8 +552,8 @@ static int pivotlist_set(lua_State *L) else if (lua_isuserdata(L, 3)) { struct PivotFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); - memcpy(&sprinfo->pivot[frame], - &container->sprinfo->pivot[container->frame], + memcpy(&sprinfo->frames[frame].pivot, + &container->sprinfo->frames[container->frame].pivot, sizeof(spriteframepivot_t)); okcool = 1; } @@ -573,7 +573,7 @@ static int pivotlist_num(lua_State *L) static int framepivot_get(lua_State *L) { struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); - spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; + spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot; const char *field = luaL_checkstring(L, 2); I_Assert(framepivot != NULL); @@ -597,7 +597,7 @@ static int framepivot_get(lua_State *L) static int framepivot_set(lua_State *L) { struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); - spriteframepivot_t *framepivot = &container->sprinfo->pivot[container->frame]; + spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot; UINT8 *available = container->sprinfo->available; const char *field = luaL_checkstring(L, 2); diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 61129d608c..a84f0ad4a4 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -98,13 +98,13 @@ patch_t *Patch_GetRotatedSprite( if (R_IsSpriteInfoAvailable(sprinfo, frame)) { - xpivot = sprinfo->pivot[frame].x; - ypivot = sprinfo->pivot[frame].y; + xpivot = sprinfo->frames[frame].pivot.x; + ypivot = sprinfo->frames[frame].pivot.y; } else if (R_IsSpriteInfoAvailable(sprinfo, SPRINFO_DEFAULT_FRAME)) { - xpivot = sprinfo->pivot[SPRINFO_DEFAULT_FRAME].x; - ypivot = sprinfo->pivot[SPRINFO_DEFAULT_FRAME].y; + xpivot = sprinfo->frames[SPRINFO_DEFAULT_FRAME].pivot.x; + ypivot = sprinfo->frames[SPRINFO_DEFAULT_FRAME].pivot.y; } else { diff --git a/src/r_picformats.c b/src/r_picformats.c index 8aa3eab516..84fc980a3a 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1556,18 +1556,18 @@ struct ParsedSpriteInfoFrame { INT32 pivotY; }; -static boolean define_spriteinfo_frame(struct ParsedSpriteInfoFrame *frame, spriteinfo_t *dest, UINT16 index) +static boolean define_spriteinfo_frame(struct ParsedSpriteInfoFrame *frame, spriteinfoframe_t *dest) { boolean defined = false; if (frame->pivotX != INT32_MAX) { - dest->pivot[index].x = frame->pivotX; + dest->pivot.x = frame->pivotX; defined = true; } if (frame->pivotY != INT32_MAX) { - dest->pivot[index].y = frame->pivotY; + dest->pivot.y = frame->pivotY; defined = true; } @@ -1704,7 +1704,7 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean { for (UINT16 frameIter = frameID; frameIter <= frameEndID; frameIter++) { - if (define_spriteinfo_frame(&frame, parser->info, frameIter)) + if (define_spriteinfo_frame(&frame, &parser->info->frames[frameIter])) { set_bit_array(parser->info->available, frameIter); } @@ -1712,7 +1712,7 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean } else { - if (define_spriteinfo_frame(&frame, parser->info, frameID)) + if (define_spriteinfo_frame(&frame, &parser->info->frames[frameID])) { set_bit_array(parser->info->available, frameID); } diff --git a/src/r_picformats.h b/src/r_picformats.h index 1388be0134..b07b6a9485 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -98,12 +98,17 @@ typedef struct INT32 x, y; } spriteframepivot_t; +typedef struct +{ + spriteframepivot_t pivot; +} spriteinfoframe_t; + #define SPRINFO_DEFAULT_FRAME (MAXFRAMENUM) typedef struct { UINT8 available[BIT_ARRAY_SIZE(MAXFRAMENUM + 1)]; // 1 extra for default_frame - spriteframepivot_t pivot[MAXFRAMENUM + 1]; + spriteinfoframe_t frames[MAXFRAMENUM + 1]; } spriteinfo_t; // PNG support -- GitLab From 2968b348b9b1d0edfb27ed190e6ea70bedf95c19 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 23:13:05 -0300 Subject: [PATCH 07/10] Implement frame[] and followmobj_* fields for Lua SpriteInfo --- src/deh_soc.c | 16 ++ src/lua_baselib.c | 2 + src/lua_infolib.c | 377 ++++++++++++++++++++++++++++++++++-------- src/lua_libs.h | 2 + src/r_patchrotation.c | 26 ++- src/r_picformats.c | 3 + src/r_picformats.h | 1 + 7 files changed, 348 insertions(+), 79 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 001c6d2896..9d571610b6 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -874,6 +874,7 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) char *tmp; INT32 value; char *lastline; + boolean available = false; do { @@ -925,9 +926,15 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) value = atoi(word2); // used for numerical settings if (fastcmp(word, "XPIVOT")) + { sprinfo->frames[frame].pivot.x = value; + available = true; + } else if (fastcmp(word, "YPIVOT")) + { sprinfo->frames[frame].pivot.y = value; + available = true; + } // TODO: 2.3: Delete else if (fastcmp(word, "ROTAXIS")) deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed."); @@ -938,6 +945,10 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) } } } while (!myfeof(f)); // finish when the line is empty + + if (available) + sprinfo->frames[frame].pivot.available = true; + Z_Free(s); } @@ -1074,6 +1085,11 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) // read sprite frame and store it in the spriteinfo_t struct readspriteframe(f, info, frame); set_bit_array(info->available, frame); + + // TODO: 2.3: Delete + info->frames[SPRINFO_DEFAULT_FRAME].pivot.available = true; + set_bit_array(info->available, SPRINFO_DEFAULT_FRAME); + if (sprite2) { INT32 i; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index ecd1ee55e6..9e15284451 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -171,6 +171,8 @@ static const struct { {META_SKINCOLOR, "skincolor_t"}, {META_COLORRAMP, "skincolor_t.ramp"}, {META_SPRITEINFO, "spriteinfo_t"}, + {META_SPRITEINFOFRAMELIST,"spriteinfoframe_t[]"}, + {META_SPRITEINFOFRAME,"spriteinfoframe_t"}, {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 44ced92e94..d241dca3cd 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -236,12 +236,12 @@ static int lib_spr2namelen(lua_State *L) // SPRITE INFO // ///////////////// -struct PivotFrame { +struct SpriteInfoFrame { spriteinfo_t *sprinfo; UINT16 frame; }; -static UINT16 GetSpriteInfoFrame(lua_State *L, int idx) +static UINT16 GetSpriteInfoFrameIndex(lua_State *L, int idx) { if (lua_type(L, idx) == LUA_TSTRING) { @@ -295,89 +295,161 @@ static int lib_getSpriteInfo(lua_State *L) #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e); #define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2))) -static int PopPivotSubTable(spriteinfo_t *info, lua_State *L, int stk, int idx) +static int PopPivotSubTable(spriteinfoframe_t *frame, lua_State *L, int stk); + +static int PopFrameSubTable(spriteinfoframe_t *frame, lua_State *L, int stk) { int okcool = 0; + switch (lua_type(L, stk)) { - case LUA_TTABLE: - lua_pushnil(L); - while (lua_next(L, stk)) + case LUA_TTABLE: + lua_pushnil(L); + while (lua_next(L, stk)) + { + const char *key = luaL_checkstring(L, stk+1); + if (fastcmp(key, "pivot")) { - const char *key = NULL; - lua_Integer ikey = -1; - lua_Integer value = 0; - // x or y? - switch (lua_type(L, stk+1)) - { - case LUA_TSTRING: - key = lua_tostring(L, stk+1); - break; - case LUA_TNUMBER: - ikey = lua_tointeger(L, stk+1); - break; - default: - FIELDERROR("pivot key", va("string or number expected, got %s", luaL_typename(L, stk+1))) - } - // then get value - switch (lua_type(L, stk+2)) - { - case LUA_TNUMBER: - value = lua_tonumber(L, stk+2); - break; - case LUA_TBOOLEAN: - value = (UINT8)lua_toboolean(L, stk+2); - break; - default: - TYPEERROR("pivot value", LUA_TNUMBER, lua_type(L, stk+2)) - } - // Set it - if (ikey == 1 || (key && fastcmp(key, "x"))) - info->frames[idx].pivot.x = (INT32)value; - else if (ikey == 2 || (key && fastcmp(key, "y"))) - info->frames[idx].pivot.y = (INT32)value; - // TODO: 2.3: Delete - else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) - LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") - else if (ikey == -1 && (key != NULL)) - FIELDERROR("pivot key", va("invalid option %s", key)); - okcool = 1; - lua_pop(L, 1); + if (PopPivotSubTable(frame, L, stk+2)) + okcool = 1; } - break; - default: - TYPEERROR("sprite pivot", LUA_TTABLE, lua_type(L, stk)) + else + { + FIELDERROR("sprite info frame key", va("invalid option %s", key)); + } + + okcool = 1; + + lua_pop(L, 1); + } + break; + default: + TYPEERROR("sprite info frame", LUA_TTABLE, lua_type(L, stk)) } + return okcool; } -static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) +static int PopFrameTable(spriteinfo_t *info, lua_State *L, int stk) { - // Just in case? - if (!lua_istable(L, stk)) - TYPEERROR("pivot table", LUA_TTABLE, lua_type(L, stk)); - lua_pushnil(L); - // stk = 0 has the pivot table - // stk = 1 has the frame key - // stk = 2 has the frame table - // stk = 3 has either a string or a number as key - // stk = 4 has the value for the key mentioned above + while (lua_next(L, stk)) { int idx = 0; switch (lua_type(L, stk+1)) { + case LUA_TSTRING: + case LUA_TNUMBER: + idx = GetSpriteInfoFrameIndex(L, stk+1); + break; + default: + TYPEERROR("sprite info frame", LUA_TNUMBER, lua_type(L, stk+1)); + } + + // the values in frames[] are also tables + if (PopFrameSubTable(&info->frames[idx], L, stk+2)) + set_bit_array(info->available, idx); + + lua_pop(L, 1); + } + + return 0; +} + +static int PopPivotSubTable(spriteinfoframe_t *frame, lua_State *L, int stk) +{ + int okcool = 0; + + switch (lua_type(L, stk)) + { + case LUA_TTABLE: + lua_pushnil(L); + while (lua_next(L, stk)) + { + const char *key = NULL; + lua_Integer ikey = -1; + lua_Integer value = 0; + + // x or y? + switch (lua_type(L, stk+1)) + { case LUA_TSTRING: + key = lua_tostring(L, stk+1); + break; + case LUA_TNUMBER: + ikey = lua_tointeger(L, stk+1); + break; + default: + FIELDERROR("pivot key", va("string or number expected, got %s", luaL_typename(L, stk+1))) + } + + // then get value + switch (lua_type(L, stk+2)) + { case LUA_TNUMBER: - idx = GetSpriteInfoFrame(L, stk+1); + value = lua_tonumber(L, stk+2); + break; + case LUA_TBOOLEAN: + value = (UINT8)lua_toboolean(L, stk+2); break; default: - TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); + TYPEERROR("pivot value", LUA_TNUMBER, lua_type(L, stk+2)) + } + + // Set it + if (ikey == 1 || (key && fastcmp(key, "x"))) + frame->pivot.x = (INT32)value; + else if (ikey == 2 || (key && fastcmp(key, "y"))) + frame->pivot.y = (INT32)value; + // TODO: 2.3: Delete + else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) + LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") + else if (ikey == -1 && (key != NULL)) + FIELDERROR("pivot key", va("invalid option %s", key)); + + okcool = 1; + + lua_pop(L, 1); + } + break; + default: + TYPEERROR("sprite pivot", LUA_TTABLE, lua_type(L, stk)) + } + + if (okcool) + frame->pivot.available = true; + + return okcool; +} + +static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) +{ + lua_pushnil(L); + + while (lua_next(L, stk)) + { + int idx = 0; + switch (lua_type(L, stk+1)) + { + case LUA_TSTRING: + case LUA_TNUMBER: + idx = GetSpriteInfoFrameIndex(L, stk+1); + break; + default: + TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); } + // the values in pivot[] are also tables - if (PopPivotSubTable(info, L, stk+2, idx)) + if (PopPivotSubTable(&info->frames[idx], L, stk+2)) + { set_bit_array(info->available, idx); + + // TODO: 2.3: Delete + info->frames[SPRINFO_DEFAULT_FRAME].pivot.available = true; + set_bit_array(info->available, SPRINFO_DEFAULT_FRAME); + } + lua_pop(L, 1); } @@ -423,6 +495,14 @@ static int lib_setSpriteInfo(lua_State *L) else FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) } + else if (str && fastcmp(str, "frames")) + { + // frames[] is a table + if (lua_istable(L, 3)) + return PopFrameTable(info, L, 3); + else + FIELDERROR("frames", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) + } lua_pop(L, 1); } @@ -448,9 +528,9 @@ static int spriteinfo_get(lua_State *L) I_Assert(sprinfo != NULL); // push spriteframepivot_t userdata + // TODO: 2.3: delete if (fastcmp(field, "pivot")) { - // bypass LUA_PushUserdata void **userdata = lua_newuserdata(L, sizeof(void *)); *userdata = sprinfo; luaL_getmetatable(L, META_PIVOTLIST); @@ -459,6 +539,15 @@ static int spriteinfo_get(lua_State *L) // stack is left with the userdata on top, as if getting it had originally succeeded. return 1; } + else if (fastcmp(field, "frames")) + { + void **userdata = lua_newuserdata(L, sizeof(void *)); + *userdata = sprinfo; + luaL_getmetatable(L, META_SPRITEINFOFRAMELIST); + lua_setmetatable(L, -2); + + return 1; + } else return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); @@ -492,7 +581,27 @@ static int spriteinfo_set(lua_State *L) else if (lua_isuserdata(L, 1)) { spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - memcpy(sprinfo, copyinfo, sizeof(spriteinfo_t)); + for (UINT16 i = 0; i <= MAXFRAMENUM; i++) + { + if (in_bit_array(copyinfo->available, i)) + memcpy(&sprinfo->frames[i].pivot, ©info->frames[i].pivot, sizeof(spriteframepivot_t)); + } + } + } + else if (fastcmp(field, "frames")) + { + // frames[] is a table + if (lua_istable(L, 1)) + return PopFrameTable(sprinfo, L, 1); + // frames[] is userdata + else if (lua_isuserdata(L, 1)) + { + spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST)); + for (UINT16 i = 0; i <= MAXFRAMENUM; i++) + { + if (in_bit_array(copyinfo->available, i)) + memcpy(&sprinfo->frames[i], ©info->frames[i], sizeof(spriteinfoframe_t)); + } } } else @@ -512,14 +621,138 @@ static int spriteinfo_num(lua_State *L) return 1; } +// spriteinfoframe_t +static int framelist_get(lua_State *L) +{ + struct SpriteInfoFrame *container; + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST)); + UINT16 frame = GetSpriteInfoFrameIndex(L, 2); + + container = lua_newuserdata(L, sizeof *container); + container->sprinfo = sprinfo; + container->frame = frame; + luaL_getmetatable(L, META_SPRITEINFOFRAME); + lua_setmetatable(L, -2); + + // stack is left with the userdata on top, as if getting it had originally succeeded. + return 1; +} + +static int framelist_set(lua_State *L) +{ + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST)); + UINT16 frame; + int okcool = 0; + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteinfoframe_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteinfoframe_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteinfoframe_t in CMD building code!"); + + frame = GetSpriteInfoFrameIndex(L, 2); + + // frames[] is a table + if (lua_istable(L, 3)) + okcool = PopFrameSubTable(&sprinfo->frames[frame], L, 3); + // frames[] is userdata + else if (lua_isuserdata(L, 3)) + { + struct SpriteInfoFrame *container = luaL_checkudata(L, 3, META_SPRITEINFOFRAME); + memcpy(&sprinfo->frames[frame], + &container->sprinfo->frames[container->frame], + sizeof(spriteinfoframe_t)); + okcool = 1; + } + + if (okcool) + set_bit_array(sprinfo->available, frame); + + return 0; +} + +static int framelist_num(lua_State *L) +{ + lua_pushinteger(L, MAXFRAMENUM); + return 1; +} + +// spriteinfoframe_t +static int sprinfoframe_get(lua_State *L) +{ + struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_SPRITEINFOFRAME); + spriteinfoframe_t *frame = &container->sprinfo->frames[container->frame]; + const char *field = luaL_checkstring(L, 2); + + I_Assert(frame != NULL); + + if (fastcmp("pivot", field)) + { + struct SpriteInfoFrame *other_container = lua_newuserdata(L, sizeof *container); + memcpy(other_container, container, sizeof *container); + luaL_getmetatable(L, META_FRAMEPIVOT); + lua_setmetatable(L, -2); + } + else + return luaL_error(L, "Field %s does not exist in spriteinfoframe_t", field); + + return 1; +} + +static int sprinfoframe_set(lua_State *L) +{ + struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_SPRITEINFOFRAME); + spriteinfoframe_t *frame = &container->sprinfo->frames[container->frame]; + UINT8 *available = container->sprinfo->available; + const char *field = luaL_checkstring(L, 2); + boolean is_available = false; + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteinfoframe_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteinfoframe_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteinfoframe_t in CMD building code!"); + + I_Assert(frame != NULL); + + if (fastcmp("pivot", field)) + { + // pivot[] is a table + if (lua_istable(L, 3)) + { + if (PopPivotSubTable(frame, L, 3)) + is_available = true; + } + // pivot[] is userdata + else if (lua_isuserdata(L, 3)) + { + struct SpriteInfoFrame *other_container = luaL_checkudata(L, 3, META_FRAMEPIVOT); + memcpy(&frame->pivot, + &other_container->sprinfo->frames[other_container->frame].pivot, + sizeof(spriteframepivot_t)); + is_available = true; + } + } + else + return luaL_error(L, "Field %s does not exist in spriteframepivot_t", field); + + if (is_available) + { + set_bit_array(available, container->frame); + } + + return 0; +} + // framepivot_t static int pivotlist_get(lua_State *L) { - struct PivotFrame *container; + struct SpriteInfoFrame *container; spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); - UINT16 frame = GetSpriteInfoFrame(L, 2); + UINT16 frame = GetSpriteInfoFrameIndex(L, 2); - // bypass LUA_PushUserdata container = lua_newuserdata(L, sizeof *container); container->sprinfo = sprinfo; container->frame = frame; @@ -543,15 +776,15 @@ static int pivotlist_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!"); - frame = GetSpriteInfoFrame(L, 2); + frame = GetSpriteInfoFrameIndex(L, 2); // pivot[] is a table if (lua_istable(L, 3)) - okcool = PopPivotSubTable(sprinfo, L, 3, frame); + okcool = PopPivotSubTable(&sprinfo->frames[frame], L, 3); // pivot[] is userdata else if (lua_isuserdata(L, 3)) { - struct PivotFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); + struct SpriteInfoFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT); memcpy(&sprinfo->frames[frame].pivot, &container->sprinfo->frames[container->frame].pivot, sizeof(spriteframepivot_t)); @@ -572,7 +805,7 @@ static int pivotlist_num(lua_State *L) static int framepivot_get(lua_State *L) { - struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot; const char *field = luaL_checkstring(L, 2); @@ -596,7 +829,7 @@ static int framepivot_get(lua_State *L) static int framepivot_set(lua_State *L) { - struct PivotFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); + struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT); spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot; UINT8 *available = container->sprinfo->available; const char *field = luaL_checkstring(L, 2); @@ -1941,6 +2174,8 @@ int LUA_InfoLib(lua_State *L) LUA_RegisterUserdataMetatable(L, META_COLORRAMP, colorramp_get, colorramp_set, colorramp_len); LUA_RegisterUserdataMetatable(L, META_SFXINFO, sfxinfo_get, sfxinfo_set, sfxinfo_num); LUA_RegisterUserdataMetatable(L, META_SPRITEINFO, spriteinfo_get, spriteinfo_set, spriteinfo_num); + LUA_RegisterUserdataMetatable(L, META_SPRITEINFOFRAMELIST, framelist_get, framelist_set, framelist_num); + LUA_RegisterUserdataMetatable(L, META_SPRITEINFOFRAME, sprinfoframe_get, sprinfoframe_set, NULL); LUA_RegisterUserdataMetatable(L, META_PIVOTLIST, pivotlist_get, pivotlist_set, pivotlist_num); LUA_RegisterUserdataMetatable(L, META_FRAMEPIVOT, framepivot_get, framepivot_set, framepivot_num); LUA_RegisterUserdataMetatable(L, META_LUABANKS, lib_getluabanks, lib_setluabanks, lib_luabankslen); diff --git a/src/lua_libs.h b/src/lua_libs.h index e1585f488a..b6e61456a8 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -29,6 +29,8 @@ extern boolean ignoregameinputs; #define META_SKINCOLOR "SKINCOLOR_T*" #define META_COLORRAMP "SKINCOLOR_T*RAMP" #define META_SPRITEINFO "SPRITEINFO_T*" +#define META_SPRITEINFOFRAMELIST "SPRITEINFOFRAME_T[]" +#define META_SPRITEINFOFRAME "SPRITEINFOFRAME_T*" #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index a84f0ad4a4..8df1084824 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -63,6 +63,16 @@ patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip) return rotsprite->patches[angle]; } +static spriteframepivot_t *GetSpriteInfoRotationPivot(spriteinfo_t *info, UINT16 frame) +{ + if (R_IsSpriteInfoAvailable(info, frame) && info->frames[frame].pivot.available) + { + return &info->frames[frame].pivot; + } + + return NULL; +} + patch_t *Patch_GetRotatedSprite( spriteframe_t *sprite, size_t frame, size_t spriteangle, @@ -90,21 +100,21 @@ patch_t *Patch_GetRotatedSprite( patch_t *patch; INT32 xpivot = 0, ypivot = 0; lumpnum_t lump = sprite->lumppat[spriteangle]; + spriteframepivot_t *pivot; if (lump == LUMPERROR) return NULL; patch = W_CachePatchNum(lump, PU_SPRITE); - if (R_IsSpriteInfoAvailable(sprinfo, frame)) - { - xpivot = sprinfo->frames[frame].pivot.x; - ypivot = sprinfo->frames[frame].pivot.y; - } - else if (R_IsSpriteInfoAvailable(sprinfo, SPRINFO_DEFAULT_FRAME)) + pivot = GetSpriteInfoRotationPivot(sprinfo, frame); + if (pivot == NULL) + pivot = GetSpriteInfoRotationPivot(sprinfo, SPRINFO_DEFAULT_FRAME); + + if (pivot != NULL) { - xpivot = sprinfo->frames[SPRINFO_DEFAULT_FRAME].pivot.x; - ypivot = sprinfo->frames[SPRINFO_DEFAULT_FRAME].pivot.y; + xpivot = pivot->x; + ypivot = pivot->y; } else { diff --git a/src/r_picformats.c b/src/r_picformats.c index 84fc980a3a..645b5c1e6e 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1563,11 +1563,13 @@ static boolean define_spriteinfo_frame(struct ParsedSpriteInfoFrame *frame, spri if (frame->pivotX != INT32_MAX) { dest->pivot.x = frame->pivotX; + dest->pivot.available = true; defined = true; } if (frame->pivotY != INT32_MAX) { dest->pivot.y = frame->pivotY; + dest->pivot.available = true; defined = true; } @@ -1682,6 +1684,7 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean sprinfoToken = M_GetToken(NULL); frame.pivotY = atoi(sprinfoToken); } + // TODO: 2.3: Delete else if (stricmp(sprinfoToken, "ROTAXIS")==0) { Z_Free(sprinfoToken); diff --git a/src/r_picformats.h b/src/r_picformats.h index b07b6a9485..9c6d788b22 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -96,6 +96,7 @@ typedef enum typedef struct { INT32 x, y; + boolean available; } spriteframepivot_t; typedef struct -- GitLab From cd3bca34871dd71d15ba2b241786c1b3274966a8 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Thu, 30 Jan 2025 15:26:13 -0300 Subject: [PATCH 08/10] Remove unused variable That's a surprise tool that will help us later. --- src/lua_infolib.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index d241dca3cd..54ec2bf790 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -682,11 +682,8 @@ static int framelist_num(lua_State *L) static int sprinfoframe_get(lua_State *L) { struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_SPRITEINFOFRAME); - spriteinfoframe_t *frame = &container->sprinfo->frames[container->frame]; const char *field = luaL_checkstring(L, 2); - I_Assert(frame != NULL); - if (fastcmp("pivot", field)) { struct SpriteInfoFrame *other_container = lua_newuserdata(L, sizeof *container); -- GitLab From d400ee30abb75f73cb91b76f9914ca695efa6a0d Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Thu, 30 Jan 2025 15:29:19 -0300 Subject: [PATCH 09/10] Update copyrights --- src/lua_infolib.c | 1 + src/r_picformats.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 54ec2bf790..84f787d1e3 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,5 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2024 by Kart Krew. // Copyright (C) 2012-2016 by John "JTE" Muniz. // Copyright (C) 2012-2025 by Sonic Team Junior. // diff --git a/src/r_picformats.c b/src/r_picformats.c index 645b5c1e6e..5e90353591 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,8 +2,9 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2024 by Lactozilla. -// Copyright (C) 2019-2024 by Sonic Team Junior. +// Copyright (C) 2024 by Kart Krew. +// Copyright (C) 2018-2025 by Lactozilla. +// Copyright (C) 2019-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. -- GitLab From e531c5d4e37acfa517e100e4d22726d8958801a3 Mon Sep 17 00:00:00 2001 From: Lactozilla <jp6781615@gmail.com> Date: Wed, 29 Jan 2025 23:14:24 -0300 Subject: [PATCH 10/10] Rename XPivot and YPivot to RotationXPivot and RotationYPivot XPivot and YPivot have been kept for backwards compatibility. --- src/r_picformats.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index 5e90353591..94452e20e8 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1583,6 +1583,8 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean UINT16 frameID = 0; UINT16 frameEndID = UINT16_MAX; + boolean usingDeprecatedPivot = false; + struct ParsedSpriteInfoFrame frame = { .pivotX = INT32_MAX, .pivotY = INT32_MAX @@ -1673,17 +1675,33 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean } while (strcmp(sprinfoToken,"}")!=0) { - if (stricmp(sprinfoToken, "XPIVOT")==0) + if (stricmp(sprinfoToken, "ROTATIONXPIVOT")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frame.pivotX = atoi(sprinfoToken); + } + else if (stricmp(sprinfoToken, "ROTATIONYPIVOT")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frame.pivotY = atoi(sprinfoToken); + } + // TODO: 2.3: Delete + else if (stricmp(sprinfoToken, "XPIVOT")==0) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); frame.pivotX = atoi(sprinfoToken); + usingDeprecatedPivot = true; } + // TODO: 2.3: Delete else if (stricmp(sprinfoToken, "YPIVOT")==0) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); frame.pivotY = atoi(sprinfoToken); + usingDeprecatedPivot = true; } // TODO: 2.3: Delete else if (stricmp(sprinfoToken, "ROTAXIS")==0) @@ -1722,6 +1740,13 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean } } + // TODO: 2.3: Delete + if (usingDeprecatedPivot) + { + parser->info->frames[SPRINFO_DEFAULT_FRAME].pivot.available = true; + set_bit_array(parser->info->available, SPRINFO_DEFAULT_FRAME); + } + if (parser->spr2) { INT32 i; -- GitLab