Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/Animation.hpp
1162 views
1
#ifndef ANIMATION_H
2
#define ANIMATION_H
3
4
namespace RSDK
5
{
6
7
#define SPRFILE_COUNT (0x400)
8
#define SPRITEFRAME_COUNT (0x400)
9
#define SPRITEANIM_COUNT (0x40)
10
11
#define FRAMEHITBOX_COUNT (0x8)
12
13
#define RSDK_SIGNATURE_SPR (0x525053) // "SPR"
14
15
enum RotationStyles { ROTSTYLE_NONE, ROTSTYLE_FULL, ROTSTYLE_45DEG, ROTSTYLE_90DEG, ROTSTYLE_180DEG, ROTSTYLE_STATICFRAMES };
16
17
struct Hitbox {
18
int16 left;
19
int16 top;
20
int16 right;
21
int16 bottom;
22
};
23
24
// this is all the data the game can access
25
typedef struct {
26
int16 sprX;
27
int16 sprY;
28
int16 width;
29
int16 height;
30
int16 pivotX;
31
int16 pivotY;
32
uint16 duration;
33
uint16 unicodeChar;
34
uint8 sheetID;
35
} GameSpriteFrameType;
36
37
static GameSpriteFrameType GameSpriteFrame;
38
39
// hitboxCount & hitboxes are "private"
40
// the proof of this is that "GetHitbox(animator, uint8 hitboxID)" exists, which means that Animator::frames must be a void*
41
// otherwise you could just do animator->frames[x].hitboxes[y]
42
// further proof of this is SVAR_SPRITEFRAME, to which the ONLY matching in the entire engine struct is "SpriteFrame" without the hitbox stuff.
43
struct SpriteFrame : public GameSpriteFrameType {
44
typedef decltype(GameSpriteFrame) frame;
45
46
uint8 hitboxCount;
47
Hitbox hitboxes[FRAMEHITBOX_COUNT];
48
};
49
50
struct SpriteAnimationEntry {
51
RETRO_HASH_MD5(hash);
52
int32 frameListOffset;
53
uint16 frameCount;
54
int16 animationSpeed;
55
uint8 loopIndex;
56
uint8 rotationStyle;
57
};
58
59
struct SpriteAnimation {
60
RETRO_HASH_MD5(hash);
61
SpriteFrame *frames;
62
SpriteAnimationEntry *animations;
63
uint16 animCount;
64
uint8 scope;
65
};
66
67
struct Animator {
68
SpriteFrame *frames;
69
int32 frameID;
70
int16 animationID;
71
int16 prevAnimationID;
72
int16 speed;
73
int16 timer;
74
int16 frameDuration;
75
int16 frameCount;
76
uint8 loopIndex;
77
uint8 rotationStyle;
78
};
79
80
extern SpriteAnimation spriteAnimationList[SPRFILE_COUNT];
81
82
uint16 LoadSpriteAnimation(const char *filename, uint8 scope);
83
uint16 CreateSpriteAnimation(const char *filename, uint32 frameCount, uint32 animCount, uint8 scope);
84
85
inline uint16 FindSpriteAnimation(uint16 aniFrames, const char *name)
86
{
87
if (aniFrames >= SPRFILE_COUNT)
88
return 0;
89
90
SpriteAnimation *spr = &spriteAnimationList[aniFrames];
91
92
RETRO_HASH_MD5(hash);
93
GEN_HASH_MD5(name, hash);
94
95
for (int32 a = 0; a < spr->animCount; ++a) {
96
if (HASH_MATCH_MD5(hash, spr->animations[a].hash))
97
return a;
98
}
99
100
return -1;
101
}
102
103
inline SpriteFrame *GetFrame(uint16 aniFrames, uint16 anim, int32 frame)
104
{
105
if (aniFrames >= SPRFILE_COUNT)
106
return NULL;
107
108
SpriteAnimation *spr = &spriteAnimationList[aniFrames];
109
if (anim >= spr->animCount)
110
return NULL;
111
112
return &spr->frames[frame + spr->animations[anim].frameListOffset];
113
}
114
115
inline Hitbox *GetHitbox(Animator *animator, uint8 hitboxID)
116
{
117
if (animator && animator->frames)
118
return &animator->frames[animator->frameID].hitboxes[hitboxID & (FRAMEHITBOX_COUNT - 1)];
119
else
120
return NULL;
121
}
122
123
inline int16 GetFrameID(Animator *animator)
124
{
125
if (animator && animator->frames)
126
return animator->frames[animator->frameID].unicodeChar;
127
128
return 0;
129
}
130
131
void ProcessAnimation(Animator *animator);
132
133
inline void SetSpriteAnimation(uint16 aniFrames, uint16 animationID, Animator *animator, bool32 forceApply, int32 frameID)
134
{
135
if (aniFrames >= SPRFILE_COUNT || !animator) {
136
if (animator)
137
animator->frames = NULL;
138
return;
139
}
140
141
SpriteAnimation *spr = &spriteAnimationList[aniFrames];
142
if (animationID >= spr->animCount)
143
return;
144
145
SpriteAnimationEntry *anim = &spr->animations[animationID];
146
SpriteFrame *frames = &spr->frames[anim->frameListOffset];
147
if (animator->frames == frames && !forceApply)
148
return;
149
150
animator->frames = frames;
151
animator->timer = 0;
152
animator->frameID = frameID;
153
animator->frameCount = anim->frameCount;
154
animator->frameDuration = animator->frames[frameID].duration;
155
animator->speed = anim->animationSpeed;
156
animator->rotationStyle = anim->rotationStyle;
157
animator->loopIndex = anim->loopIndex;
158
animator->prevAnimationID = animator->animationID;
159
animator->animationID = animationID;
160
}
161
162
inline void EditSpriteAnimation(uint16 aniFrames, uint16 animID, const char *name, int32 frameOffset, uint16 frameCount, int16 animSpeed,
163
uint8 loopIndex, uint8 rotationStyle)
164
{
165
if (aniFrames < SPRFILE_COUNT) {
166
SpriteAnimation *spr = &spriteAnimationList[aniFrames];
167
if (animID < spr->animCount) {
168
SpriteAnimationEntry *anim = &spr->animations[animID];
169
GEN_HASH_MD5(name, anim->hash);
170
anim->frameListOffset = frameOffset;
171
anim->frameCount = frameCount;
172
anim->animationSpeed = animSpeed;
173
anim->loopIndex = loopIndex;
174
anim->rotationStyle = rotationStyle;
175
}
176
}
177
}
178
179
int32 GetStringWidth(uint16 aniFrames, uint16 animID, String *string, int32 startIndex, int32 length, int32 spacing);
180
void SetSpriteString(uint16 aniFrames, uint16 animID, String *string);
181
182
inline void ClearSpriteAnimations()
183
{
184
// Unload animations
185
for (int32 s = 0; s < SPRFILE_COUNT; ++s) {
186
if (spriteAnimationList[s].scope != SCOPE_GLOBAL) {
187
MEM_ZERO(spriteAnimationList[s]);
188
spriteAnimationList[s].scope = SCOPE_NONE;
189
}
190
}
191
}
192
193
#if RETRO_REV0U
194
#include "Legacy/AnimationLegacy.hpp"
195
#endif
196
197
} // namespace RSDK
198
199
#endif
200
201