1 /*
2 	Copyright (C) 2005-2007 Feeling Software Inc.
3 	Portions of the code are:
4 	Copyright (C) 2005-2007 Sony Computer Entertainment America
5 
6 	MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8 
9 #include "StdAfx.h"
10 #include "FCDParameterAnimatable.h"
11 #if !defined (__APPLE__) && !defined(LINUX)
12 #include "FCDParameterAnimatable.hpp"
13 #endif
14 #include "FCDAnimated.h"
15 #include <FUtils/FUParameterizable.h>
16 #include <FMath/FMAngleAxis.h>
17 #include <FMath/FMLookAt.h>
18 #include <FMath/FMSkew.h>
19 
20 //
21 // FCDParameterAnimatable
22 //
23 
FCDParameterAnimatable(FUParameterizable * _parent)24 FCDParameterAnimatable::FCDParameterAnimatable(FUParameterizable* _parent)
25 :	parent(_parent)
26 {
27 }
28 
~FCDParameterAnimatable()29 FCDParameterAnimatable::~FCDParameterAnimatable()
30 {
31 	parent = NULL;
32 }
33 
GetAnimated()34 FCDAnimated* FCDParameterAnimatable::GetAnimated() { if (animated == NULL) animated = CreateAnimated(); return animated; }
GetAnimated() const35 const FCDAnimated* FCDParameterAnimatable::GetAnimated() const
36 {
37 	if (animated == NULL)
38 	{
39 		FCDParameterAnimatable* _this = const_cast<FCDParameterAnimatable*>(this);
40 		_this->animated = _this->CreateAnimated();
41 	}
42 	return animated;
43 }
44 
IsAnimated() const45 bool FCDParameterAnimatable::IsAnimated() const
46 {
47 	return animated != NULL && animated->HasCurve();
48 }
49 
CreateAnimated()50 FCDAnimated* FCDParameterAnimatable::CreateAnimated()
51 {
52 	// Implemented below in template specializations of FCDParameterAnimatableT.
53 	return NULL;
54 }
55 
operator =(FCDParameterAnimatable & UNUSED (parameter))56 FCDParameterAnimatable& FCDParameterAnimatable::operator= (FCDParameterAnimatable& UNUSED(parameter))
57 {
58 	// This empty copy operator is necessary to avoid the default copy operator
59 	// generated by the compiler which copies the parent pointer.
60 	return *this;
61 }
62 
63 //
64 // FCDParameterAnimatableT
65 //
66 
CreateAnimated()67 template <> FCDAnimated* FCDParameterAnimatableFloat::CreateAnimated()
68 {
69 	float* values[1] = { &value };
70 	return new FCDAnimated((FCDObject*) GetParent(), 1, FCDAnimatedStandardQualifiers::EMPTY, values);
71 }
72 
CreateAnimated()73 template <> FCDAnimated* FCDParameterAnimatableVector2::CreateAnimated()
74 {
75 	float* values[2] = { &value.x, &value.y };
76 	return new FCDAnimated((FCDObject*) GetParent(), 2, FCDAnimatedStandardQualifiers::XYZW, values);
77 }
78 
CreateAnimated()79 template <> FCDAnimated* FCDParameterAnimatableVector3::CreateAnimated()
80 {
81 	float* values[3] = { &value.x, &value.y, &value.z };
82 	return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::XYZW, values);
83 }
84 
CreateAnimated()85 template <> FCDAnimated* FCDParameterAnimatableColor3::CreateAnimated()
86 {
87 	float* values[3] = { &value.x, &value.y, &value.z };
88 	return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::RGBA, values);
89 }
90 
CreateAnimated()91 template <> FCDAnimated* FCDParameterAnimatableVector4::CreateAnimated()
92 {
93 	float* values[4] = { &value.x, &value.y, &value.z, &value.w };
94 	return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::XYZW, values);
95 }
96 
CreateAnimated()97 template <> FCDAnimated* FCDParameterAnimatableColor4::CreateAnimated()
98 {
99 	float* values[4] = { &value.x, &value.y, &value.z, &value.w };
100 	return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::RGBA, values);
101 }
102 
CreateAnimated()103 template <> FCDAnimated* FCDParameterAnimatableMatrix44::CreateAnimated()
104 {
105 	float* values[16] =
106 	{
107 		&value[0][0], &value[1][0], &value[2][0], &value[3][0],
108 		&value[0][1], &value[1][1], &value[2][1], &value[3][1],
109 		&value[0][2], &value[1][2], &value[2][2], &value[3][2],
110 		&value[0][3], &value[1][3], &value[2][3], &value[3][3]
111 	};
112 	return new FCDAnimated((FCDObject*) GetParent(), 16, FCDAnimatedStandardQualifiers::MATRIX, values);
113 }
114 
CreateAnimated()115 template <> FCDAnimated* FCDParameterAnimatableAngleAxis::CreateAnimated()
116 {
117 	float* values[4] = { &value.axis.x, &value.axis.y, &value.axis.z, &value.angle };
118 	return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::ROTATE_AXIS, values);
119 }
120 
CreateAnimated()121 template <> FCDAnimated* FCDParameterAnimatableLookAt::CreateAnimated()
122 {
123 	float* values[9] =
124 	{
125 		&value.position.x, &value.position.y, &value.position.z,
126 		&value.target.x, &value.target.y, &value.target.z,
127 		&value.up.x, &value.up.y, &value.up.z
128 	};
129 	return new FCDAnimated((FCDObject*) GetParent(), 9, FCDAnimatedStandardQualifiers::LOOKAT, values);
130 }
131 
CreateAnimated()132 template <> FCDAnimated* FCDParameterAnimatableSkew::CreateAnimated()
133 {
134 	float* values[7] =
135 	{
136 		&value.rotateAxis.x, &value.rotateAxis.y, &value.rotateAxis.z,
137 		&value.aroundAxis.x, &value.aroundAxis.y, &value.aroundAxis.z,
138 		&value.angle
139 	};
140 	return new FCDAnimated((FCDObject*) GetParent(), 7, FCDAnimatedStandardQualifiers::LOOKAT, values);
141 }
142 
143 //
144 // FCDParameterListAnimatable
145 //
FCDParameterListAnimatable(FUParameterizable * _parent)146 FCDParameterListAnimatable::FCDParameterListAnimatable(FUParameterizable* _parent)
147 :	parent(_parent)
148 {
149 }
150 
~FCDParameterListAnimatable()151 FCDParameterListAnimatable::~FCDParameterListAnimatable()
152 {
153 	parent = NULL;
154 }
155 
GetAnimated(size_t index) const156 const FCDAnimated* FCDParameterListAnimatable::GetAnimated(size_t index) const { return const_cast<const FCDAnimated*>(const_cast<FCDParameterListAnimatable*>(this)->GetAnimated(index)); }
GetAnimated(size_t index)157 FCDAnimated* FCDParameterListAnimatable::GetAnimated(size_t index)
158 {
159 	// Check for existing
160 	size_t mid = BinarySearch(index);
161 	if (mid < animateds.size() && animateds[mid]->GetArrayElement() == (int32) index)
162 	{
163 		return animateds[mid];
164 	}
165 
166 	// Create new animated value.
167 	FCDAnimated* animated = CreateAnimated(index);
168 	animated->SetArrayElement((int32) index);
169 	animateds.insert(mid, animated);
170 	return animated;
171 }
172 
IsAnimated(size_t index) const173 bool FCDParameterListAnimatable::IsAnimated(size_t index) const
174 {
175 	size_t animatedCount = animateds.size();
176 	if (index == ~(size_t)0)
177 	{
178 		for (size_t i = 0; i < animatedCount; ++i)
179 		{
180 			if (animateds[i]->HasCurve()) return true;
181 		}
182 		return false;
183 	}
184 	else
185 	{
186 		size_t i = BinarySearch(index);
187 		return i < animatedCount && animateds[i]->GetArrayElement() == (int32) index && animateds[i]->HasCurve();
188 	}
189 }
190 
OnInsertion(size_t offset,size_t count)191 void FCDParameterListAnimatable::OnInsertion(size_t offset, size_t count)
192 {
193 	// Push forward all the array element indices starting at "offset" by "count".
194 	for (size_t i = BinarySearch(offset); i < animateds.size(); ++i)
195 	{
196 		int32 arrayElement = animateds[i]->GetArrayElement();
197 		FUAssert(arrayElement >= (int32) offset, continue);
198 		animateds[i]->SetArrayElement(arrayElement + (int32) count);
199 	}
200 }
201 
OnRemoval(size_t offset,size_t count)202 void FCDParameterListAnimatable::OnRemoval(size_t offset, size_t count)
203 {
204 	// Release all the animated helpers for the removed values.
205 	for (size_t i = BinarySearch(offset); i < animateds.size();)
206 	{
207 		int32 arrayElement = animateds[i]->GetArrayElement();
208 		FUAssert(arrayElement >= (int32) offset, continue);
209 		if (arrayElement >= (int32) (offset + count)) break;
210 		animateds[i]->Release(); // automatic removal from this array..
211 	}
212 
213 	// Push back all the array element indices starting at "offset + count" by "count".
214 	for (size_t i = BinarySearch(offset + count); i < animateds.size(); ++i)
215 	{
216 		int32 arrayElement = animateds[i]->GetArrayElement();
217 		FUAssert(arrayElement >= (int32) (offset + count), continue);
218 		animateds[i]->SetArrayElement(arrayElement - (int32) count);
219 	}
220 }
221 
BinarySearch(size_t arrayElementIndex) const222 size_t FCDParameterListAnimatable::BinarySearch(size_t arrayElementIndex) const
223 {
224 	// Binary search..
225 	size_t start = 0, end = animateds.size();
226 	size_t mid;
227 	for (mid = (end + start) / 2; start < end; mid = (end + start) / 2)
228 	{
229 		int32 arrayElement = animateds[mid]->GetArrayElement();
230 		if (arrayElement < (int32) arrayElementIndex) start = mid + 1;
231 		else if (arrayElement > (int32) arrayElementIndex) end = mid;
232 		else break;
233 	}
234 	return mid;
235 }
236 
CreateAnimated(size_t UNUSED (index))237 FCDAnimated* FCDParameterListAnimatable::CreateAnimated(size_t UNUSED(index))
238 {
239 	// Implemented by the specialized template functions below.
240 	return NULL;
241 }
242 
243 //
244 // FCDParameterListAnimatableT
245 //
246 
CreateAnimated(size_t index)247 template <> FCDAnimated* FCDParameterListAnimatableFloat::CreateAnimated(size_t index)
248 {
249 	float* _values[1] = { &values[index] };
250 	return new FCDAnimated((FCDObject*) GetParent(), 1, FCDAnimatedStandardQualifiers::EMPTY, _values);
251 }
252 
CreateAnimated(size_t index)253 template <> FCDAnimated* FCDParameterListAnimatableVector2::CreateAnimated(size_t index)
254 {
255 	float* _values[2] = { &values[index].x, &values[index].y };
256 	return new FCDAnimated((FCDObject*) GetParent(), 2, FCDAnimatedStandardQualifiers::XYZW, _values);
257 }
258 
CreateAnimated(size_t index)259 template <> FCDAnimated* FCDParameterListAnimatableVector3::CreateAnimated(size_t index)
260 {
261 	float* _values[3] = { &values[index].x, &values[index].y, &values[index].z };
262 	return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::XYZW, _values);
263 }
264 
CreateAnimated(size_t index)265 template <> FCDAnimated* FCDParameterListAnimatableColor3::CreateAnimated(size_t index)
266 {
267 	float* _values[3] = { &values[index].x, &values[index].y, &values[index].z };
268 	return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::RGBA, _values);
269 }
270 
CreateAnimated(size_t index)271 template <> FCDAnimated* FCDParameterListAnimatableVector4::CreateAnimated(size_t index)
272 {
273 	float* _values[4] = { &values[index].x, &values[index].y, &values[index].z, &values[index].w };
274 	return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::XYZW, _values);
275 }
276 
CreateAnimated(size_t index)277 template <> FCDAnimated* FCDParameterListAnimatableColor4::CreateAnimated(size_t index)
278 {
279 	float* _values[4] = { &values[index].x, &values[index].y, &values[index].z, &values[index].w };
280 	return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::RGBA, _values);
281 }
282 
283 //
284 // Templatization Trick
285 //
TrickLinkerFCDParameterAnimatableT(const T & value)286 template <class T, int Q> void TrickLinkerFCDParameterAnimatableT(const T& value)
287 {
288 	FCDParameterAnimatableT<T, Q> v1((FUParameterizable*) NULL), v2((FUParameterizable*) NULL, value);
289 	if (v1 == value) v1 = value;
290 	T bb = (T) v1; (void) bb;
291 	T& bb2 = (T&) v1; (void) bb2;
292 	const T& bb3 = (const T&) v2; (void) bb3;
293 	*v1;
294 	v1.operator->();
295 	v1.operator*();
296 	*const_cast<const FCDParameterAnimatableT<T, Q>&>(v1);
297 	const_cast<const FCDParameterAnimatableT<T, Q>&>(v1).operator->();
298 	const_cast<const FCDParameterAnimatableT<T, Q>&>(v1).operator*();
299 	FCDAnimated* aa = v1.GetAnimated();
300 	if (v1.IsAnimated()) ++aa;
301 }
302 
303 
TrickLinkerFCDParameterListAnimatableT(const T & value)304 template <class T, int Q> void TrickLinkerFCDParameterListAnimatableT(const T& value)
305 {
306 	FCDParameterListAnimatableT<T, Q> v1((FUParameterizable*) NULL);
307 	v1.push_back(value);
308 	v1 = v1;
309 	v1.set(0, value);
310 	v1.clear();
311 	v1.insert(0, value);
312 	v1.insert(0, &value, 1);
313 	v1.insert(0, 5, value);
314 	v1.erase((size_t) 5);
315 	v1.erase(value);
316 	v1.erase((size_t) 0, (size_t) 4);
317 	v1.push_back(v1.front());
318 	v1.push_front(v1.back());
319 	v1.pop_back();
320 	v1.pop_front();
321 	v1.resize(4);
322 	v1.resize(6, value);
323 	v1.empty();
324 	v1.size();
325 	if (v1.contains(value) && v1.empty()) v1.find(value);
326 	v1[0];
327 	v1.at(0);
328 	FCDAnimated* aa = v1.GetAnimated(0);
329 	v1.GetDataList();
330 	if (v1.IsAnimated()) ++aa;
331 	const_cast<const FCDParameterListAnimatableT<T, Q>&>(v1).front();
332 	const_cast<const FCDParameterListAnimatableT<T, Q>&>(v1).back();
333 	const_cast<const FCDParameterListAnimatableT<T, Q>&>(v1).GetDataList();
334 }
335 
TrickLinkerFCDParameterAnimatable()336 extern void TrickLinkerFCDParameterAnimatable()
337 {
338 	// Primitive animatables
339 	TrickLinkerFCDParameterAnimatableT<float, 0>(0.03f);
340 	TrickLinkerFCDParameterAnimatableT<FMVector2, 0>(FMVector2::XAxis);
341 	TrickLinkerFCDParameterAnimatableT<FMVector3, 0>(FMVector3::YAxis);
342 	TrickLinkerFCDParameterAnimatableT<FMVector3, 1>(FMVector3::YAxis);
343 	TrickLinkerFCDParameterAnimatableT<FMVector4, 0>(FMVector4::Zero);
344 	TrickLinkerFCDParameterAnimatableT<FMVector4, 1>(FMVector4::Zero);
345 	TrickLinkerFCDParameterAnimatableT<FMMatrix44, 0>(FMMatrix44::Identity);
346 	TrickLinkerFCDParameterAnimatableT<FMSkew, 0>(FMSkew());
347 	TrickLinkerFCDParameterAnimatableT<FMLookAt, 0>(FMLookAt());
348 	TrickLinkerFCDParameterAnimatableT<FMAngleAxis, 0>(FMAngleAxis());
349 
350 	// Primitive list animatables
351 	TrickLinkerFCDParameterListAnimatableT<float, 0>(0.03f);
352 	TrickLinkerFCDParameterListAnimatableT<FMVector2, 0>(FMVector2::XAxis);
353 	TrickLinkerFCDParameterListAnimatableT<FMVector3, 0>(FMVector3::YAxis);
354 	TrickLinkerFCDParameterListAnimatableT<FMVector3, 1>(FMVector3::YAxis);
355 	TrickLinkerFCDParameterListAnimatableT<FMVector4, 0>(FMVector4::Zero);
356 	TrickLinkerFCDParameterListAnimatableT<FMVector4, 1>(FMVector4::Zero);
357 }
358 
359