Path: blob/master/RSDKv5/RSDK/Graphics/Animation.hpp
1162 views
#ifndef ANIMATION_H1#define ANIMATION_H23namespace RSDK4{56#define SPRFILE_COUNT (0x400)7#define SPRITEFRAME_COUNT (0x400)8#define SPRITEANIM_COUNT (0x40)910#define FRAMEHITBOX_COUNT (0x8)1112#define RSDK_SIGNATURE_SPR (0x525053) // "SPR"1314enum RotationStyles { ROTSTYLE_NONE, ROTSTYLE_FULL, ROTSTYLE_45DEG, ROTSTYLE_90DEG, ROTSTYLE_180DEG, ROTSTYLE_STATICFRAMES };1516struct Hitbox {17int16 left;18int16 top;19int16 right;20int16 bottom;21};2223// this is all the data the game can access24typedef struct {25int16 sprX;26int16 sprY;27int16 width;28int16 height;29int16 pivotX;30int16 pivotY;31uint16 duration;32uint16 unicodeChar;33uint8 sheetID;34} GameSpriteFrameType;3536static GameSpriteFrameType GameSpriteFrame;3738// hitboxCount & hitboxes are "private"39// the proof of this is that "GetHitbox(animator, uint8 hitboxID)" exists, which means that Animator::frames must be a void*40// otherwise you could just do animator->frames[x].hitboxes[y]41// further proof of this is SVAR_SPRITEFRAME, to which the ONLY matching in the entire engine struct is "SpriteFrame" without the hitbox stuff.42struct SpriteFrame : public GameSpriteFrameType {43typedef decltype(GameSpriteFrame) frame;4445uint8 hitboxCount;46Hitbox hitboxes[FRAMEHITBOX_COUNT];47};4849struct SpriteAnimationEntry {50RETRO_HASH_MD5(hash);51int32 frameListOffset;52uint16 frameCount;53int16 animationSpeed;54uint8 loopIndex;55uint8 rotationStyle;56};5758struct SpriteAnimation {59RETRO_HASH_MD5(hash);60SpriteFrame *frames;61SpriteAnimationEntry *animations;62uint16 animCount;63uint8 scope;64};6566struct Animator {67SpriteFrame *frames;68int32 frameID;69int16 animationID;70int16 prevAnimationID;71int16 speed;72int16 timer;73int16 frameDuration;74int16 frameCount;75uint8 loopIndex;76uint8 rotationStyle;77};7879extern SpriteAnimation spriteAnimationList[SPRFILE_COUNT];8081uint16 LoadSpriteAnimation(const char *filename, uint8 scope);82uint16 CreateSpriteAnimation(const char *filename, uint32 frameCount, uint32 animCount, uint8 scope);8384inline uint16 FindSpriteAnimation(uint16 aniFrames, const char *name)85{86if (aniFrames >= SPRFILE_COUNT)87return 0;8889SpriteAnimation *spr = &spriteAnimationList[aniFrames];9091RETRO_HASH_MD5(hash);92GEN_HASH_MD5(name, hash);9394for (int32 a = 0; a < spr->animCount; ++a) {95if (HASH_MATCH_MD5(hash, spr->animations[a].hash))96return a;97}9899return -1;100}101102inline SpriteFrame *GetFrame(uint16 aniFrames, uint16 anim, int32 frame)103{104if (aniFrames >= SPRFILE_COUNT)105return NULL;106107SpriteAnimation *spr = &spriteAnimationList[aniFrames];108if (anim >= spr->animCount)109return NULL;110111return &spr->frames[frame + spr->animations[anim].frameListOffset];112}113114inline Hitbox *GetHitbox(Animator *animator, uint8 hitboxID)115{116if (animator && animator->frames)117return &animator->frames[animator->frameID].hitboxes[hitboxID & (FRAMEHITBOX_COUNT - 1)];118else119return NULL;120}121122inline int16 GetFrameID(Animator *animator)123{124if (animator && animator->frames)125return animator->frames[animator->frameID].unicodeChar;126127return 0;128}129130void ProcessAnimation(Animator *animator);131132inline void SetSpriteAnimation(uint16 aniFrames, uint16 animationID, Animator *animator, bool32 forceApply, int32 frameID)133{134if (aniFrames >= SPRFILE_COUNT || !animator) {135if (animator)136animator->frames = NULL;137return;138}139140SpriteAnimation *spr = &spriteAnimationList[aniFrames];141if (animationID >= spr->animCount)142return;143144SpriteAnimationEntry *anim = &spr->animations[animationID];145SpriteFrame *frames = &spr->frames[anim->frameListOffset];146if (animator->frames == frames && !forceApply)147return;148149animator->frames = frames;150animator->timer = 0;151animator->frameID = frameID;152animator->frameCount = anim->frameCount;153animator->frameDuration = animator->frames[frameID].duration;154animator->speed = anim->animationSpeed;155animator->rotationStyle = anim->rotationStyle;156animator->loopIndex = anim->loopIndex;157animator->prevAnimationID = animator->animationID;158animator->animationID = animationID;159}160161inline void EditSpriteAnimation(uint16 aniFrames, uint16 animID, const char *name, int32 frameOffset, uint16 frameCount, int16 animSpeed,162uint8 loopIndex, uint8 rotationStyle)163{164if (aniFrames < SPRFILE_COUNT) {165SpriteAnimation *spr = &spriteAnimationList[aniFrames];166if (animID < spr->animCount) {167SpriteAnimationEntry *anim = &spr->animations[animID];168GEN_HASH_MD5(name, anim->hash);169anim->frameListOffset = frameOffset;170anim->frameCount = frameCount;171anim->animationSpeed = animSpeed;172anim->loopIndex = loopIndex;173anim->rotationStyle = rotationStyle;174}175}176}177178int32 GetStringWidth(uint16 aniFrames, uint16 animID, String *string, int32 startIndex, int32 length, int32 spacing);179void SetSpriteString(uint16 aniFrames, uint16 animID, String *string);180181inline void ClearSpriteAnimations()182{183// Unload animations184for (int32 s = 0; s < SPRFILE_COUNT; ++s) {185if (spriteAnimationList[s].scope != SCOPE_GLOBAL) {186MEM_ZERO(spriteAnimationList[s]);187spriteAnimationList[s].scope = SCOPE_NONE;188}189}190}191192#if RETRO_REV0U193#include "Legacy/AnimationLegacy.hpp"194#endif195196} // namespace RSDK197198#endif199200201