summaryrefslogtreecommitdiff
path: root/src/rwanim.h
blob: e6dd1d558575c053b3ff76771ff9813c87270b9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <stddef.h>

namespace rw {

struct Animation;

// These sizes of these are sadly not platform independent
// because pointer sizes can vary.

struct KeyFrameHeader
{
	KeyFrameHeader *prev;
	float32 time;

	KeyFrameHeader *next(int32 sz){
		return (KeyFrameHeader*)((uint8*)this + sz); }
};

struct InterpFrameHeader
{
	KeyFrameHeader *keyFrame1;
	KeyFrameHeader *keyFrame2;
};

struct AnimInterpolatorInfo
{
	typedef void (*ApplyCB)(void *result, void *frame);
	typedef void (*BlendCB)(void *out, void *in1, void *in2, float32 a);
	typedef void (*InterpCB)(void *out, void *in1, void *in2, float32 t,
	                         void *custom);
	typedef void (*AddCB)(void *out, void *in1, void *in2);
	typedef void (*MulRecipCB)(void *frame, void *start);

	int32      id;
	int32      interpKeyFrameSize;
	int32      animKeyFrameSize;
	int32      customDataSize;

	ApplyCB    applyCB;
	BlendCB    blendCB;
	InterpCB   interpCB;
	AddCB      addCB;
	MulRecipCB mulRecipCB;
	void (*streamRead)(Stream *stream, Animation *anim);
	void (*streamWrite)(Stream *stream, Animation *anim);
	uint32 (*streamGetSize)(Animation *anim);

	static void registerInterp(AnimInterpolatorInfo *interpInfo);
	static void unregisterInterp(AnimInterpolatorInfo *interpInfo);
	static AnimInterpolatorInfo *find(int32 id);
};

struct Animation
{
	AnimInterpolatorInfo *interpInfo;
	int32    numFrames;
	int32    flags;
	float32  duration;
	void    *keyframes;
	void    *customData;

	static Animation *create(AnimInterpolatorInfo*, int32 numFrames,
	                         int32 flags, float duration);
	void destroy(void);
	int32 getNumNodes(void);
	KeyFrameHeader *getAnimFrame(int32 n){
		return (KeyFrameHeader*)((uint8*)this->keyframes +
		                         n*this->interpInfo->animKeyFrameSize);
	}
	static Animation *streamRead(Stream *stream);
	static Animation *streamReadLegacy(Stream *stream);
	bool streamWrite(Stream *stream);
	bool streamWriteLegacy(Stream *stream);
	uint32 streamGetSize(void);
};

struct AnimInterpolator
{
	Animation *currentAnim;
	float32    currentTime;
	void      *nextFrame;
	int32      maxInterpKeyFrameSize;
	int32      currentInterpKeyFrameSize;
	int32      currentAnimKeyFrameSize;
	int32      numNodes;
	// TODO some callbacks, parent/sub
	// cached from the InterpolatorInfo
	AnimInterpolatorInfo::ApplyCB    applyCB;
	AnimInterpolatorInfo::BlendCB    blendCB;
	AnimInterpolatorInfo::InterpCB   interpCB;
	AnimInterpolatorInfo::AddCB      addCB;
	// after this interpolated frames

	static AnimInterpolator *create(int32 numNodes, int32 maxKeyFrameSize);
	void destroy(void);
	bool32 setCurrentAnim(Animation *anim);
	void addTime(float32 t);
	void *getFrames(void){ return this+1;}
	InterpFrameHeader *getInterpFrame(int32 n){
		return (InterpFrameHeader*)((uint8*)getFrames() +
		                            n*currentInterpKeyFrameSize);
	}
	KeyFrameHeader *getAnimFrame(int32 n){
		return (KeyFrameHeader*)((uint8*)currentAnim->keyframes +
		                         n*currentAnimKeyFrameSize);
	}
};

//
// UV anim
//

struct UVAnimParamData
{
	float32 theta;	// rotation
	float32 s0;	// scale x
	float32 s1;	// scale y
	float32 skew;	// skew
	float32 x;	// x pos
	float32 y;	// y pos
};

struct UVAnimKeyFrame
{
	UVAnimKeyFrame *prev;
	float32 time;
	float32 uv[6];
};

struct UVAnimInterpFrame
{
	UVAnimKeyFrame *keyFrame1;
	UVAnimKeyFrame *keyFrame2;
	float32 uv[6];
};

struct UVAnimDictionary;

// RW does it differently...maybe we should implement RtDict
// and make it more general?

struct UVAnimCustomData
{
	char name[32];
	int32 nodeToUVChannel[8];
	int32 refCount;

	void destroy(Animation *anim);
	static UVAnimCustomData *get(Animation *anim){
		return (UVAnimCustomData*)anim->customData; }
};

// This should be more general probably
struct UVAnimDictEntry
{
	Animation *anim;
	LLLink inDict;
	static UVAnimDictEntry *fromDict(LLLink *lnk){
		return LLLinkGetData(lnk, UVAnimDictEntry, inDict); }
};

// This too
struct UVAnimDictionary
{
	LinkList animations;

	static UVAnimDictionary *create(void);
	void destroy(void);
	int32 count(void) { return this->animations.count(); }
	void add(Animation *anim);
	Animation *find(const char *name);

	static UVAnimDictionary *streamRead(Stream *stream);
	bool streamWrite(Stream *stream);
	uint32 streamGetSize(void);
};

extern UVAnimDictionary *currentUVAnimDictionary;

// Material plugin
struct UVAnim
{
	Matrix *uv[2];
	AnimInterpolator *interp[8];

	static bool32 exists(Material *mat);
	static void addTime(Material *mat, float32 t);
	static void applyUpdate(Material *mat);
};

extern int32 uvAnimOffset;

void registerUVAnimPlugin(void);

}