summaryrefslogtreecommitdiff
path: root/Runtime/Animation/AnimationClip.h
blob: 1c4c1c22341e8a6d25957029112a593383dafd12 (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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#ifndef ANIMATIONCLIP_H
#define ANIMATIONCLIP_H

#include "Runtime/BaseClasses/NamedObject.h"
#include "Runtime/Serialize/SerializeTraits.h"
#include "Runtime/Utilities/LinkedList.h"
#include "Runtime/Math/Quaternion.h"
#include "Runtime/Math/Vector2.h"
#include "Runtime/Geometry/AABB.h"
#include "Runtime/Math/AnimationCurve.h"
#include "AnimationEvent.h"
#include "Runtime/Mono/MonoScript.h"
#include "Runtime/mecanim/memory.h"
#include "AnimationClipBindings.h"
#include "PPtrKeyframes.h"

#include "Motion.h"

#if UNITY_EDITOR
#include "AnimationClipSettings.h"
#endif 

namespace mecanim
{ 
	namespace animation
	{ 
		struct ClipMuscleConstant; 
		struct ClipMuscleInput;
	}
}

struct AnimationClipStats;

namespace Unity { class GameObject; }
using namespace Unity;

class BaseAnimationTrack;
class NewAnimationTrack;
class MonoScript;
class Animation;
class AnimationState;
class CompressedAnimationCurve;

/*
	TODO:
	* We currently don't handle double cover operator automatically for rotation curves
	* We are not synchronizing animation state cached range correctly
	* GetCurve is not implemented yet
*/

class AnimationClip : public Motion
{
public:	
	struct QuaternionCurve
	{
		UnityStr path;
		AnimationCurveQuat curve;
		int            hash;
		
		QuaternionCurve () { hash = 0; }
		void CopyWithoutCurve(QuaternionCurve& other) const
		{
			other.path = path;
			other.hash = hash;
		}
		
		DECLARE_SERIALIZE (QuaternionCurve)
	};

	struct Vector3Curve
	{
		UnityStr path;
		AnimationCurveVec3 curve;
		int            hash;
		
		Vector3Curve () { hash = 0; }
		void CopyWithoutCurve(Vector3Curve& other) const
		{
			other.path = path;
			other.hash = hash;
		}
		
		DECLARE_SERIALIZE (Vector3Curve)
	};
	
public:

	
	struct PPtrCurve
	{
		UnityStr        path;
		UnityStr        attribute;
		int             classID;
		MonoScriptPPtr  script;
		PPtrKeyframes   curve;
		
		PPtrCurve () {  }
		
		DECLARE_SERIALIZE (PPtrCurve)
	};
	
	struct FloatCurve
	{
		UnityStr path;
		UnityStr attribute;
		int    classID;
		MonoScriptPPtr script;
		AnimationCurve curve;
		int            hash;
		
		FloatCurve () { hash = 0; }
		void CopyWithoutCurve(FloatCurve& other) const
		{
			other.path = path;
			other.attribute = attribute;
			other.classID = classID;
			other.script = script;
			other.hash = hash;
		}
		
		DECLARE_SERIALIZE (FloatCurve)
	};

	typedef UNITY_VECTOR(kMemAnimation, QuaternionCurve) QuaternionCurves;
	typedef UNITY_VECTOR(kMemAnimation, CompressedAnimationCurve) CompressedQuaternionCurves;
	typedef UNITY_VECTOR(kMemAnimation, Vector3Curve) Vector3Curves;
	typedef UNITY_VECTOR(kMemAnimation, FloatCurve) FloatCurves;
	typedef UNITY_VECTOR(kMemAnimation, PPtrCurve) PPtrCurves;
	typedef UNITY_VECTOR(kMemAnimation, AnimationEvent) Events;

	enum AnimationType
	{
		kLegacy   = 1,
		kGeneric  = 2,
		kHumanoid = 3
	};
	
	
	
	REGISTER_DERIVED_CLASS (AnimationClip, Motion)
	DECLARE_OBJECT_SERIALIZE (AnimationClip)
	
	static void InitializeClass ();
	static void CleanupClass () {  }
	
	AnimationClip (MemLabelId label, ObjectCreationMode mode);	
	// virtual ~AnimationClip(); declared-by-macro

	virtual void AwakeFromLoad(AwakeFromLoadMode mode);
	virtual void CheckConsistency();
	
	
	/// Assigns curve to the curve defined by path, classID and attribute
	/// If curve is null the exisiting curve will be removed.
	void SetCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, AnimationCurve* curve, bool syncEditorCurves);
	bool GetCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, AnimationCurve* outCurve);

	void ClearCurves ();
	void EnsureQuaternionContinuity ();

	bool HasAnimationEvents ();
	void FireAnimationEvents (float lastTime, float now, Unity::Component& source);
	
	#if UNITY_EDITOR
	void							SetEditorCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, const AnimationCurve* curve, bool syncEditorCurves = true);
	bool							GetEditorCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, AnimationCurve* outCurve);
	FloatCurves&					GetEditorCurvesSync();

	void							SetEditorPPtrCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, PPtrKeyframes* keyframes);
	bool							GetEditorPPtrCurve (const std::string& path, int classID, MonoScriptPPtr script, const std::string& attribute, PPtrKeyframes* outKeyframes);
	PPtrCurves&						GetEditorPPtrCurves() { return m_PPtrCurves; }

	// Callback for telling animation window when an animclip got reloaded
	typedef void					OnAnimationClipAwake(AnimationClip* clip);
	static void						SetOnAnimationClipAwake (OnAnimationClipAwake *callback);

	void							SyncEditorCurves();	
	void							SyncMuscleCurvesBackwardCompatibility();
	
	void							SetEvents (const AnimationEvent* events, int size, bool sort = false);
	void							ClearEvents ();
	FloatCurves&					GetEulerEditorCurves()												{ return m_EulerEditorCurves; }
	virtual void					CloneAdditionalEditorProperties (Object& src);
	FloatCurves&					GetEditorCurvesNoConversion ()										{ return m_EditorCurves; } 
		
	
	const AnimationClipSettings&	GetAnimationClipSettings() const									{ return m_AnimationClipSettings; }
	void							SetAnimationClipSettingsNoDirty (AnimationClipSettings &clipInfo);
	void							SetAnimationClipSettings (const AnimationClipSettings&clipInfo)		{ m_AnimationClipSettings = clipInfo; SetDirty(); } 
	
	void							GenerateMuscleClip();		
		
	void							SetAnimationType (AnimationType type);
	
	
	// overloads from Motion	
	virtual float					GetAverageDuration();
	virtual float					GetAverageAngularSpeed();
	virtual Vector3f				GetAverageSpeed();
	virtual float					GetApparentSpeed();
	
	virtual bool					ValidateIfRetargetable(bool showWarning = true);	
	virtual bool					IsLooping();
		
	#endif

	virtual bool					IsAnimatorMotion()const;
	
	// Returns the smallest and largest keyframe time of any channel in the animation
	// if no keyframes are contained make_pair (infinity, -infinity) is returned
	std::pair<float, float> GetRange ();

	// Animation State support
	typedef List< ListNode<AnimationState> > AnimationStateList;
	typedef void DidModifyClipCallback(AnimationClip* clip, AnimationStateList& states);

	static void SetDidModifyClipCallback(DidModifyClipCallback* callback);
	void AddAnimationState(ListNode<AnimationState>& node) { m_AnimationStates.push_back(node); }

	void SetSampleRate (float s);
	float GetSampleRate () { return m_SampleRate; }

	void SetCompressionEnabled (bool s) { m_Compressed = s; }
	bool GetCompressionEnabled () { return m_Compressed; }
#if UNITY_EDITOR
	void SetUseHighQualityCurve (bool s) { m_UseHighQualityCurve = s; }
	bool GetUseHighQualityCurve ()const { return m_UseHighQualityCurve; }
#endif
	void SetWrapMode (int wrap) { m_WrapMode = wrap; SetDirty (); }
	int GetWrapMode () { return m_WrapMode; }

	Events& GetEvents () { return m_Events; }
	void AddRuntimeEvent (AnimationEvent& event);

	void AddRotationCurve (const AnimationCurveQuat& quat, const std::string& path);
	void AddPositionCurve (const AnimationCurveVec3& quat, const std::string& path);
	void AddScaleCurve (const AnimationCurveVec3& quat, const std::string& path);
	void AddFloatCurve (const AnimationCurve& curve, const std::string& path, int classID, const std::string& attribute);

	QuaternionCurves& GetRotationCurves() { return m_RotationCurves; } 
	Vector3Curves& GetPositionCurves() { return m_PositionCurves; } 
	Vector3Curves& GetScaleCurves() { return m_ScaleCurves; } 
	FloatCurves& GetFloatCurves() { return m_FloatCurves; } 

	const QuaternionCurves& GetRotationCurves() const { return m_RotationCurves; } 
	const Vector3Curves& GetPositionCurves() const { return m_PositionCurves; } 
	const Vector3Curves& GetScaleCurves() const { return m_ScaleCurves; } 
	const FloatCurves& GetFloatCurves() const { return m_FloatCurves; } 

	void SetBounds(const AABB& bounds) { m_Bounds = bounds; SetDirty(); }
	const AABB& GetBounds() const { return m_Bounds; }

	static void RevertAllPlaymodeAnimationEvents ();

	bool IsHumanMotion();

	AnimationType GetAnimationType () const { return m_AnimationType; }

	
	UnityEngine::Animation::AnimationClipBindingConstant* GetBindingConstant () { return &m_ClipBindingConstant; }
	mecanim::animation::ClipMuscleConstant*	GetRuntimeAsset();

	void GetStats(AnimationClipStats& stats);
	
	void ClipWasModifiedAndUpdateMuscleRange ();
	void UpdateMuscleClipRange ();

	
private:
	void CompressCurves (CompressedQuaternionCurves& compressedRotationCurves);
	void DecompressCurves (CompressedQuaternionCurves& compressedRotationCurves);

	void ClipWasModified (bool cleanupMecanimData = true);

	void ReloadEditorEulerCurves (const string& path);
	void ReloadEditorQuaternionCurves (const string& path);

	void ConvertToNewCurveFormat (NewAnimationTrack& curves, int classID, const std::string& path);
	void ConvertToNewCurveFormat ();

	void CleanupMecanimData();

	mecanim::memory::ChainedAllocator					m_ClipAllocator;

private:
	AnimationStateList m_AnimationStates;

	float           m_SampleRate;
	bool			m_Compressed;
	bool            m_UseHighQualityCurve;
	int             m_WrapMode;///< enum { Default = 0, Once = 1, Loop = 2, PingPong = 4, ClampForever = 8 }
	
	QuaternionCurves   m_RotationCurves;
	Vector3Curves      m_PositionCurves;
	Vector3Curves      m_ScaleCurves;
	FloatCurves        m_FloatCurves;
	PPtrCurves         m_PPtrCurves;
	Events             m_Events;
	AnimationType      m_AnimationType;

#if UNITY_EDITOR
	AnimationClipSettings m_AnimationClipSettings;
#endif//#if UNITY_EDITOR
	
	mecanim::animation::ClipMuscleConstant*		m_MuscleClip;
	mecanim::uint32_t							m_MuscleClipSize;
	UnityEngine::Animation::AnimationClipBindingConstant m_ClipBindingConstant;

	/// TODO: Serialiaze and do not compute it at all on startup
	std::pair<float, float> m_CachedRange;

	AABB m_Bounds;
	
	#if UNITY_EDITOR

	// Keep a copy of events setup from edit mode so we can safely revert events after playmode
	Events             m_EditModeEvents;
	FloatCurves        m_EditorCurves;
	FloatCurves        m_EulerEditorCurves;
		
	struct ChildTrack
	{
		UnityStr path;
		int classID;
		PPtr<BaseAnimationTrack> track;
		DECLARE_SERIALIZE (ChildTrack)
	};

	typedef vector_map<SInt32, PPtr<BaseAnimationTrack> > ClassIDToTrack;
	typedef ClassIDToTrack::iterator iterator;
	typedef std::vector<ChildTrack> ChildTracks;
	typedef ChildTracks::iterator child_iterator;

	ClassIDToTrack	m_ClassIDToTrack;
	ChildTracks     m_ChildTracks;
	
	friend class StripCurvesForMecanimClips;

	#endif
	
	friend class AnimationManager;
};

typedef std::vector<PPtr<AnimationClip> > AnimationClipVector;

#endif