/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FCDParameterAnimatable.h" #if !defined (__APPLE__) && !defined(LINUX) #include "FCDParameterAnimatable.hpp" #endif #include "FCDAnimated.h" #include #include #include #include // // FCDParameterAnimatable // FCDParameterAnimatable::FCDParameterAnimatable(FUParameterizable* _parent) : parent(_parent) { } FCDParameterAnimatable::~FCDParameterAnimatable() { parent = NULL; } FCDAnimated* FCDParameterAnimatable::GetAnimated() { if (animated == NULL) animated = CreateAnimated(); return animated; } const FCDAnimated* FCDParameterAnimatable::GetAnimated() const { if (animated == NULL) { FCDParameterAnimatable* _this = const_cast(this); _this->animated = _this->CreateAnimated(); } return animated; } bool FCDParameterAnimatable::IsAnimated() const { return animated != NULL && animated->HasCurve(); } FCDAnimated* FCDParameterAnimatable::CreateAnimated() { // Implemented below in template specializations of FCDParameterAnimatableT. return NULL; } FCDParameterAnimatable& FCDParameterAnimatable::operator= (FCDParameterAnimatable& UNUSED(parameter)) { // This empty copy operator is necessary to avoid the default copy operator // generated by the compiler which copies the parent pointer. return *this; } // // FCDParameterAnimatableT // template <> FCDAnimated* FCDParameterAnimatableFloat::CreateAnimated() { float* values[1] = { &value }; return new FCDAnimated((FCDObject*) GetParent(), 1, FCDAnimatedStandardQualifiers::EMPTY, values); } template <> FCDAnimated* FCDParameterAnimatableVector2::CreateAnimated() { float* values[2] = { &value.x, &value.y }; return new FCDAnimated((FCDObject*) GetParent(), 2, FCDAnimatedStandardQualifiers::XYZW, values); } template <> FCDAnimated* FCDParameterAnimatableVector3::CreateAnimated() { float* values[3] = { &value.x, &value.y, &value.z }; return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::XYZW, values); } template <> FCDAnimated* FCDParameterAnimatableColor3::CreateAnimated() { float* values[3] = { &value.x, &value.y, &value.z }; return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::RGBA, values); } template <> FCDAnimated* FCDParameterAnimatableVector4::CreateAnimated() { float* values[4] = { &value.x, &value.y, &value.z, &value.w }; return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::XYZW, values); } template <> FCDAnimated* FCDParameterAnimatableColor4::CreateAnimated() { float* values[4] = { &value.x, &value.y, &value.z, &value.w }; return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::RGBA, values); } template <> FCDAnimated* FCDParameterAnimatableMatrix44::CreateAnimated() { float* values[16] = { &value[0][0], &value[1][0], &value[2][0], &value[3][0], &value[0][1], &value[1][1], &value[2][1], &value[3][1], &value[0][2], &value[1][2], &value[2][2], &value[3][2], &value[0][3], &value[1][3], &value[2][3], &value[3][3] }; return new FCDAnimated((FCDObject*) GetParent(), 16, FCDAnimatedStandardQualifiers::MATRIX, values); } template <> FCDAnimated* FCDParameterAnimatableAngleAxis::CreateAnimated() { float* values[4] = { &value.axis.x, &value.axis.y, &value.axis.z, &value.angle }; return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::ROTATE_AXIS, values); } template <> FCDAnimated* FCDParameterAnimatableLookAt::CreateAnimated() { float* values[9] = { &value.position.x, &value.position.y, &value.position.z, &value.target.x, &value.target.y, &value.target.z, &value.up.x, &value.up.y, &value.up.z }; return new FCDAnimated((FCDObject*) GetParent(), 9, FCDAnimatedStandardQualifiers::LOOKAT, values); } template <> FCDAnimated* FCDParameterAnimatableSkew::CreateAnimated() { float* values[7] = { &value.rotateAxis.x, &value.rotateAxis.y, &value.rotateAxis.z, &value.aroundAxis.x, &value.aroundAxis.y, &value.aroundAxis.z, &value.angle }; return new FCDAnimated((FCDObject*) GetParent(), 7, FCDAnimatedStandardQualifiers::LOOKAT, values); } // // FCDParameterListAnimatable // FCDParameterListAnimatable::FCDParameterListAnimatable(FUParameterizable* _parent) : parent(_parent) { } FCDParameterListAnimatable::~FCDParameterListAnimatable() { parent = NULL; } const FCDAnimated* FCDParameterListAnimatable::GetAnimated(size_t index) const { return const_cast(const_cast(this)->GetAnimated(index)); } FCDAnimated* FCDParameterListAnimatable::GetAnimated(size_t index) { // Check for existing size_t mid = BinarySearch(index); if (mid < animateds.size() && animateds[mid]->GetArrayElement() == (int32) index) { return animateds[mid]; } // Create new animated value. FCDAnimated* animated = CreateAnimated(index); animated->SetArrayElement((int32) index); animateds.insert(mid, animated); return animated; } bool FCDParameterListAnimatable::IsAnimated(size_t index) const { size_t animatedCount = animateds.size(); if (index == ~(size_t)0) { for (size_t i = 0; i < animatedCount; ++i) { if (animateds[i]->HasCurve()) return true; } return false; } else { size_t i = BinarySearch(index); return i < animatedCount && animateds[i]->GetArrayElement() == (int32) index && animateds[i]->HasCurve(); } } void FCDParameterListAnimatable::OnInsertion(size_t offset, size_t count) { // Push forward all the array element indices starting at "offset" by "count". for (size_t i = BinarySearch(offset); i < animateds.size(); ++i) { int32 arrayElement = animateds[i]->GetArrayElement(); FUAssert(arrayElement >= (int32) offset, continue); animateds[i]->SetArrayElement(arrayElement + (int32) count); } } void FCDParameterListAnimatable::OnRemoval(size_t offset, size_t count) { // Release all the animated helpers for the removed values. for (size_t i = BinarySearch(offset); i < animateds.size();) { int32 arrayElement = animateds[i]->GetArrayElement(); FUAssert(arrayElement >= (int32) offset, continue); if (arrayElement >= (int32) (offset + count)) break; animateds[i]->Release(); // automatic removal from this array.. } // Push back all the array element indices starting at "offset + count" by "count". for (size_t i = BinarySearch(offset + count); i < animateds.size(); ++i) { int32 arrayElement = animateds[i]->GetArrayElement(); FUAssert(arrayElement >= (int32) (offset + count), continue); animateds[i]->SetArrayElement(arrayElement - (int32) count); } } size_t FCDParameterListAnimatable::BinarySearch(size_t arrayElementIndex) const { // Binary search.. size_t start = 0, end = animateds.size(); size_t mid; for (mid = (end + start) / 2; start < end; mid = (end + start) / 2) { int32 arrayElement = animateds[mid]->GetArrayElement(); if (arrayElement < (int32) arrayElementIndex) start = mid + 1; else if (arrayElement > (int32) arrayElementIndex) end = mid; else break; } return mid; } FCDAnimated* FCDParameterListAnimatable::CreateAnimated(size_t UNUSED(index)) { // Implemented by the specialized template functions below. return NULL; } // // FCDParameterListAnimatableT // template <> FCDAnimated* FCDParameterListAnimatableFloat::CreateAnimated(size_t index) { float* _values[1] = { &values[index] }; return new FCDAnimated((FCDObject*) GetParent(), 1, FCDAnimatedStandardQualifiers::EMPTY, _values); } template <> FCDAnimated* FCDParameterListAnimatableVector2::CreateAnimated(size_t index) { float* _values[2] = { &values[index].x, &values[index].y }; return new FCDAnimated((FCDObject*) GetParent(), 2, FCDAnimatedStandardQualifiers::XYZW, _values); } template <> FCDAnimated* FCDParameterListAnimatableVector3::CreateAnimated(size_t index) { float* _values[3] = { &values[index].x, &values[index].y, &values[index].z }; return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::XYZW, _values); } template <> FCDAnimated* FCDParameterListAnimatableColor3::CreateAnimated(size_t index) { float* _values[3] = { &values[index].x, &values[index].y, &values[index].z }; return new FCDAnimated((FCDObject*) GetParent(), 3, FCDAnimatedStandardQualifiers::RGBA, _values); } template <> FCDAnimated* FCDParameterListAnimatableVector4::CreateAnimated(size_t index) { float* _values[4] = { &values[index].x, &values[index].y, &values[index].z, &values[index].w }; return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::XYZW, _values); } template <> FCDAnimated* FCDParameterListAnimatableColor4::CreateAnimated(size_t index) { float* _values[4] = { &values[index].x, &values[index].y, &values[index].z, &values[index].w }; return new FCDAnimated((FCDObject*) GetParent(), 4, FCDAnimatedStandardQualifiers::RGBA, _values); } // // Templatization Trick // template void TrickLinkerFCDParameterAnimatableT(const T& value) { FCDParameterAnimatableT v1((FUParameterizable*) NULL), v2((FUParameterizable*) NULL, value); if (v1 == value) v1 = value; T bb = (T) v1; (void) bb; T& bb2 = (T&) v1; (void) bb2; const T& bb3 = (const T&) v2; (void) bb3; *v1; v1.operator->(); v1.operator*(); *const_cast&>(v1); const_cast&>(v1).operator->(); const_cast&>(v1).operator*(); FCDAnimated* aa = v1.GetAnimated(); if (v1.IsAnimated()) ++aa; } template void TrickLinkerFCDParameterListAnimatableT(const T& value) { FCDParameterListAnimatableT v1((FUParameterizable*) NULL); v1.push_back(value); v1 = v1; v1.set(0, value); v1.clear(); v1.insert(0, value); v1.insert(0, &value, 1); v1.insert(0, 5, value); v1.erase((size_t) 5); v1.erase(value); v1.erase((size_t) 0, (size_t) 4); v1.push_back(v1.front()); v1.push_front(v1.back()); v1.pop_back(); v1.pop_front(); v1.resize(4); v1.resize(6, value); v1.empty(); v1.size(); if (v1.contains(value) && v1.empty()) v1.find(value); v1[0]; v1.at(0); FCDAnimated* aa = v1.GetAnimated(0); v1.GetDataList(); if (v1.IsAnimated()) ++aa; const_cast&>(v1).front(); const_cast&>(v1).back(); const_cast&>(v1).GetDataList(); } extern void TrickLinkerFCDParameterAnimatable() { // Primitive animatables TrickLinkerFCDParameterAnimatableT(0.03f); TrickLinkerFCDParameterAnimatableT(FMVector2::XAxis); TrickLinkerFCDParameterAnimatableT(FMVector3::YAxis); TrickLinkerFCDParameterAnimatableT(FMVector3::YAxis); TrickLinkerFCDParameterAnimatableT(FMVector4::Zero); TrickLinkerFCDParameterAnimatableT(FMVector4::Zero); TrickLinkerFCDParameterAnimatableT(FMMatrix44::Identity); TrickLinkerFCDParameterAnimatableT(FMSkew()); TrickLinkerFCDParameterAnimatableT(FMLookAt()); TrickLinkerFCDParameterAnimatableT(FMAngleAxis()); // Primitive list animatables TrickLinkerFCDParameterListAnimatableT(0.03f); TrickLinkerFCDParameterListAnimatableT(FMVector2::XAxis); TrickLinkerFCDParameterListAnimatableT(FMVector3::YAxis); TrickLinkerFCDParameterListAnimatableT(FMVector3::YAxis); TrickLinkerFCDParameterListAnimatableT(FMVector4::Zero); TrickLinkerFCDParameterListAnimatableT(FMVector4::Zero); }