summaryrefslogtreecommitdiffstats
path: root/src/dm/systems/cores/SimpleAnimationCore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dm/systems/cores/SimpleAnimationCore.cpp')
-rw-r--r--src/dm/systems/cores/SimpleAnimationCore.cpp618
1 files changed, 618 insertions, 0 deletions
diff --git a/src/dm/systems/cores/SimpleAnimationCore.cpp b/src/dm/systems/cores/SimpleAnimationCore.cpp
new file mode 100644
index 0000000..00d6df4
--- /dev/null
+++ b/src/dm/systems/cores/SimpleAnimationCore.cpp
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSDMPrefix.h"
+#include "SimpleAnimationCore.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4503) // decorated name length exceeded
+#endif
+
+typedef long INT32;
+typedef float FLOAT;
+#define DATALOGGER_CUBICROOT 0
+
+struct SPerfLogEvent
+{
+ SPerfLogEvent(int) {}
+};
+
+typedef SPerfLogEvent TPerfLogMathEvent1;
+
+#include "Qt3DSCubicRoots.h"
+#include "Qt3DSCubicRootsImpl.h"
+#include "Qt3DSBezierEval.h"
+using namespace std;
+
+namespace qt3dsdm {
+
+Qt3DSDMAnimationHandle
+CSimpleAnimationCore::CreateAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
+ Qt3DSDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType, bool inFirstKeyframeDynamic)
+{
+ if (GetAnimation(inSlide, inInstance, inProperty, inIndex).Valid())
+ throw AnimationExists(L"");
+
+ int nextId = GetNextId();
+ Qt3DSDMAnimationHandle retval = CreateAnimationWithHandle(
+ nextId, inSlide, inInstance, inProperty, inIndex, inAnimationType, inFirstKeyframeDynamic);
+ AddAnimationToLookupCache(retval);
+ return retval;
+}
+
+void CSimpleAnimationCore::DeleteAnimation(Qt3DSDMAnimationHandle inAnimation)
+{
+ RemoveAnimationFromLookupCache(inAnimation);
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ do_all(theItem->m_Keyframes, std::bind(EraseHandle,
+ std::placeholders::_1, std::ref(m_Objects)));
+ EraseHandle(inAnimation, m_Objects);
+}
+
+void CSimpleAnimationCore::EnsureAnimationCache() const
+{
+ if (m_AnimationMatchesCache.size() == 0) {
+ for (THandleObjectMap::const_iterator theIter = m_Objects.begin(), theEnd = m_Objects.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack)
+ AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theIter->second));
+ }
+ }
+}
+
+Qt3DSDMAnimationHandle CSimpleAnimationCore::GetAnimation(Qt3DSDMSlideHandle inSlide,
+ Qt3DSDMInstanceHandle inInstance,
+ Qt3DSDMPropertyHandle inProperty,
+ size_t inIndex) const
+{
+ EnsureAnimationCache();
+
+ pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator>
+ theRange(m_AnimationMatchesCache.equal_range(
+ make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue())));
+ for (TStateInstanceAnimationMap::const_iterator theIter = theRange.first;
+ theIter != theRange.second; ++theIter) {
+ std::shared_ptr<SAnimationTrack> theItem = theIter->second;
+ if (inSlide.GetHandleValue() == theItem->m_Slide
+ && inInstance.GetHandleValue() == theItem->m_Instance
+ && inProperty.GetHandleValue() == theItem->m_Property && inIndex == theItem->m_Index)
+ return theItem->m_Handle;
+ }
+ return 0;
+}
+
+SAnimationInfo CSimpleAnimationCore::GetAnimationInfo(Qt3DSDMAnimationHandle inAnimation) const
+{
+ if (m_Objects.find(inAnimation) != m_Objects.end()) {
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property,
+ theItem->m_Index, theItem->m_AnimationType,
+ theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited);
+ }
+ return SAnimationInfo();
+}
+
+inline void AddIfAnimation(const THandleObjectPair &inPair, TAnimationHandleList &outAnimations)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack)
+ outAnimations.push_back(inPair.first);
+}
+
+void CSimpleAnimationCore::GetAnimations(TAnimationHandleList &outAnimations) const
+{
+ outAnimations.clear();
+ do_all(m_Objects, std::bind(AddIfAnimation, std::placeholders::_1, std::ref(outAnimations)));
+}
+
+void CSimpleAnimationCore::GetAnimations(TAnimationInfoList &outAnimations,
+ Qt3DSDMSlideHandle inMaster,
+ Qt3DSDMSlideHandle inSlide) const
+{
+ outAnimations.clear();
+ for (THandleObjectMap::const_iterator iter = m_Objects.begin(), end = m_Objects.end();
+ iter != end; ++iter) {
+ if (iter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) {
+ const SAnimationTrack *theItem =
+ static_cast<const SAnimationTrack *>(iter->second.get());
+ // If either master or slide is valid, then item slide must match.
+ // If item slide matches neither, then we ignore unless neither are valid.
+ bool keep = (theItem->m_Slide == inMaster || theItem->m_Slide == inSlide)
+ || (inMaster.Valid() == false && inSlide.Valid() == false);
+ if (keep) {
+ outAnimations.push_back(
+ CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property,
+ theItem->m_Index, theItem->m_AnimationType,
+ theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited));
+ }
+ }
+ }
+}
+
+inline void AddSpecificAnimationsIf(const THandleObjectPair &inPair, Qt3DSDMSlideHandle inSlide,
+ Qt3DSDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) {
+ const SAnimationTrack *theTrack = static_cast<const SAnimationTrack *>(inPair.second.get());
+ if (theTrack->m_Slide == inSlide && theTrack->m_Instance == inInstance)
+ outAnimations.push_back(inPair.first);
+ }
+}
+
+void CSimpleAnimationCore::GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide,
+ Qt3DSDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations)
+{
+ EnsureAnimationCache();
+ pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator>
+ theRange(m_AnimationMatchesCache.equal_range(
+ make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue())));
+ for (TStateInstanceAnimationMap::const_iterator iter = theRange.first; iter != theRange.second;
+ ++iter)
+ outAnimations.push_back(iter->second->m_Handle);
+}
+
+void CSimpleAnimationCore::SetFirstKeyframeDynamic(Qt3DSDMAnimationHandle inAnimation, bool inValue)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ theItem->m_FirstKeyframeDynamic = inValue;
+ SetIsArtistEdited(inAnimation);
+}
+
+inline void CheckKeyframeType(EAnimationType inExpected, const TKeyframe &inKeyframe)
+{
+ if (inExpected != GetKeyframeType(inKeyframe))
+ throw AnimationKeyframeTypeError(L"");
+}
+
+// keyframe manipulation
+Qt3DSDMKeyframeHandle CSimpleAnimationCore::InsertKeyframe(Qt3DSDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ CheckKeyframeType(theItem->m_AnimationType, inKeyframe);
+ int nextId = GetNextId();
+ m_Objects.insert(
+ make_pair(nextId, (THandleObjectPtr) new SKeyframe(nextId, inAnimation, inKeyframe)));
+ theItem->m_Keyframes.push_back(nextId);
+ theItem->m_KeyframesDirty = true;
+ SetIsArtistEdited(inAnimation);
+ return nextId;
+}
+
+void CSimpleAnimationCore::EraseKeyframe(Qt3DSDMKeyframeHandle inKeyframe)
+{
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ int theAnimHandle(theKeyframe->m_Animation);
+ SAnimationTrack *theItem = GetAnimationNF(theAnimHandle, m_Objects);
+ EraseHandle(inKeyframe, m_Objects);
+ erase_if(theItem->m_Keyframes, std::bind(equal_to<int>(),
+ std::placeholders::_1, inKeyframe.GetHandleValue()));
+ SetIsArtistEdited(theAnimHandle);
+}
+
+void CSimpleAnimationCore::DeleteAllKeyframes(Qt3DSDMAnimationHandle inAnimation)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ do_all(theItem->m_Keyframes, std::bind(EraseHandle,
+ std::placeholders::_1, std::ref(m_Objects)));
+ theItem->m_Keyframes.clear();
+ SetIsArtistEdited(inAnimation);
+}
+
+Qt3DSDMAnimationHandle
+CSimpleAnimationCore::GetAnimationForKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const
+{
+ const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ return theKeyframe->m_Animation;
+}
+
+TKeyframe CSimpleAnimationCore::GetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe) const
+{
+ const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ return theKeyframe->m_Keyframe;
+}
+
+void CSimpleAnimationCore::SetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe, const TKeyframe &inData)
+{
+ DoSetKeyframeData(inKeyframe, inData);
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ SetIsArtistEdited(theKeyframe->m_Animation);
+}
+
+void CSimpleAnimationCore::DoSetKeyframeData(Qt3DSDMKeyframeHandle inKeyframe,
+ const TKeyframe &inData)
+{
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ CheckKeyframeType(GetKeyframeType(theKeyframe->m_Keyframe), inData);
+ theKeyframe->m_Keyframe = inData;
+ SAnimationTrack *theItem = GetAnimationNF(theKeyframe->m_Animation, m_Objects);
+ theItem->m_KeyframesDirty = true;
+}
+
+bool KeyframeLessThan(int inLeftSide, int inRightSide, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theLeft = CSimpleAnimationCore::GetKeyframeNF(inLeftSide, inObjects);
+ const SKeyframe *theRight = CSimpleAnimationCore::GetKeyframeNF(inRightSide, inObjects);
+ return KeyframeTime(theLeft->m_Keyframe) < KeyframeTime(theRight->m_Keyframe);
+}
+
+void SortKeyframes(TKeyframeHandleList &inKeyframes, const THandleObjectMap &inObjects)
+{
+ return stable_sort(inKeyframes.begin(), inKeyframes.end(),
+ std::bind(KeyframeLessThan, std::placeholders::_1,
+ std::placeholders::_2, std::ref(inObjects)));
+}
+
+void CheckKeyframesSorted(const SAnimationTrack *theItem, const THandleObjectMap &inObjects)
+{
+ if (theItem->m_KeyframesDirty) {
+ SAnimationTrack *theNonConst = const_cast<SAnimationTrack *>(theItem);
+ SortKeyframes(theNonConst->m_Keyframes, inObjects);
+ theNonConst->m_KeyframesDirty = false;
+ }
+}
+
+void CSimpleAnimationCore::GetKeyframes(Qt3DSDMAnimationHandle inAnimation,
+ TKeyframeHandleList &outKeyframes) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ CheckKeyframesSorted(theItem, m_Objects);
+ outKeyframes = theItem->m_Keyframes;
+}
+
+size_t CSimpleAnimationCore::GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return theItem->m_Keyframes.size();
+}
+
+bool CSimpleAnimationCore::IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const
+{
+ Qt3DSDMAnimationHandle theAnimation = GetAnimationForKeyframe(inKeyframe);
+ if (theAnimation.Valid()) {
+ const SAnimationTrack *theItem = GetAnimationNF(theAnimation, m_Objects);
+ return theItem->m_Keyframes.size() && theItem->m_Keyframes[0] == inKeyframe;
+ }
+ return false;
+}
+
+void CSimpleAnimationCore::OffsetAnimations(Qt3DSDMSlideHandle /*inSlide*/,
+ Qt3DSDMInstanceHandle /*inInstance*/, long /*inOffset*/)
+{
+ throw std::runtime_error("unimplemented");
+}
+
+void CSimpleAnimationCore::SetIsArtistEdited(Qt3DSDMAnimationHandle inAnimation, bool inEdited)
+{
+ if (m_Objects.find(inAnimation) == m_Objects.end()) {
+ Q_ASSERT(false);
+ return;
+ }
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ if (theItem->m_ArtistEdited != inEdited)
+ theItem->m_ArtistEdited = inEdited;
+}
+
+bool CSimpleAnimationCore::IsArtistEdited(Qt3DSDMAnimationHandle inAnimation) const
+{
+ if (m_Objects.find(inAnimation) == m_Objects.end()) {
+ return false;
+ }
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return theItem->m_ArtistEdited;
+}
+
+inline bool KeyframeTimeLessThan(int inKeyframe, float inSeconds, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return KeyframeTime(theKeyframe->m_Keyframe) < inSeconds;
+}
+
+inline bool KeyframeValueTimeLessThan(const TKeyframe &inLeft, const TKeyframe &inRight)
+{
+ return KeyframeTime(inLeft) < KeyframeTime(inRight);
+}
+
+TKeyframe IntToKeyframe(int inKeyframe, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return theKeyframe->m_Keyframe;
+}
+
+inline float KeyframeValue(int inKeyframe, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return KeyframeValueValue(theKeyframe->m_Keyframe);
+}
+
+inline float EvaluateLinear(float inS1, float inS2, float inV1, float inV2, float inSeconds)
+{
+ float amount = (inSeconds - inS1) / (inS2 - inS1);
+ return inV1 + amount * (inV2 - inV1);
+}
+
+inline float EvaluateLinearKeyframe(SLinearKeyframe &inK1, SLinearKeyframe &inK2, float inSeconds)
+{
+ return EvaluateLinear(inK1.m_KeyframeSeconds, inK2.m_KeyframeSeconds, inK1.m_KeyframeValue,
+ inK2.m_KeyframeValue, inSeconds);
+}
+
+inline float DoBezierEvaluation(float inSeconds, const SBezierKeyframe &inK1,
+ const SBezierKeyframe &inK2)
+{
+ return Q3DStudio::EvaluateBezierKeyframe(
+ inSeconds, inK1.m_KeyframeSeconds, inK1.m_KeyframeValue, inK1.m_OutTangentTime,
+ inK1.m_OutTangentValue, inK2.m_InTangentTime, inK2.m_InTangentValue, inK2.m_KeyframeSeconds,
+ inK2.m_KeyframeValue);
+}
+
+// Animation Evaluation.
+float CSimpleAnimationCore::EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation,
+ float inSeconds) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ if (theItem->m_Keyframes.empty())
+ return 0.0f;
+ CheckKeyframesSorted(theItem, m_Objects);
+ // Default to linear for now.
+ SLinearKeyframe theKeyframe = { 0 };
+ theKeyframe.m_KeyframeSeconds = inSeconds;
+ TKeyframe theSearchKey(theKeyframe);
+ function<TKeyframe(int)> theIntToKeyframe(
+ std::bind(IntToKeyframe, std::placeholders::_1, std::ref(m_Objects)));
+
+ TKeyframeHandleList::const_iterator theBound =
+ lower_bound(theItem->m_Keyframes.begin(), theItem->m_Keyframes.end(), theSearchKey,
+ [theIntToKeyframe](const Qt3DSDMKeyframeHandle &inLeft,
+ const TKeyframe &inRight)
+ {return KeyframeTime(theIntToKeyframe(inLeft)) < KeyframeTime(inRight);});
+
+ if (theBound == theItem->m_Keyframes.end())
+ return KeyframeValue(theItem->m_Keyframes.back(), m_Objects);
+ if (theBound == theItem->m_Keyframes.begin())
+ return KeyframeValue(*theItem->m_Keyframes.begin(), m_Objects);
+
+ TKeyframeHandleList::const_iterator theStartIter = theBound;
+ --theStartIter;
+
+ // Both iterators must be valid at this point...
+ Qt3DSDMKeyframeHandle theStart = *theStartIter;
+ Qt3DSDMKeyframeHandle theFinish = *theBound;
+ switch (theItem->m_AnimationType) {
+ default:
+ throw AnimationEvaluationError(L"");
+ case EAnimationTypeLinear: {
+ SLinearKeyframe k1 = get<SLinearKeyframe>(theIntToKeyframe(theStart));
+ SLinearKeyframe k2 = get<SLinearKeyframe>(theIntToKeyframe(theFinish));
+ return EvaluateLinearKeyframe(k1, k2, inSeconds);
+ }
+ case EAnimationTypeBezier: {
+ SBezierKeyframe k1 = get<SBezierKeyframe>(theIntToKeyframe(theStart));
+ SBezierKeyframe k2 = get<SBezierKeyframe>(theIntToKeyframe(theFinish));
+ return DoBezierEvaluation(inSeconds, k1, k2);
+ }
+ case EAnimationTypeEaseInOut: {
+ SEaseInEaseOutKeyframe k1 = get<SEaseInEaseOutKeyframe>(theIntToKeyframe(theStart));
+ SEaseInEaseOutKeyframe k2 = get<SEaseInEaseOutKeyframe>(theIntToKeyframe(theFinish));
+ return DoBezierEvaluation(
+ inSeconds, CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, k1, &k2.m_KeyframeValue),
+ CreateBezierKeyframeFromEaseInEaseOutKeyframe(&k1.m_KeyframeValue, k2, NULL));
+ }
+ }
+}
+
+bool CSimpleAnimationCore::KeyframeValid(Qt3DSDMKeyframeHandle inKeyframe) const
+{
+ return HandleObjectValid<SKeyframe>(inKeyframe, m_Objects);
+}
+
+bool CSimpleAnimationCore::AnimationValid(Qt3DSDMAnimationHandle inAnimation) const
+{
+ return HandleObjectValid<SAnimationTrack>(inAnimation, m_Objects);
+}
+
+Qt3DSDMAnimationHandle CSimpleAnimationCore::CreateAnimationWithHandle(
+ int inHandle, Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
+ Qt3DSDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic)
+{
+ if (HandleValid(inHandle))
+ throw HandleExists(L"");
+ m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SAnimationTrack(
+ inHandle, inSlide, inInstance, inProperty, inIndex,
+ inAnimationType, inFirstKeyframeDynamic, true)));
+ return inHandle;
+}
+
+void CSimpleAnimationCore::AddAnimationToLookupCache(Qt3DSDMAnimationHandle inAnimation) const
+{
+ THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation);
+ if (theAnim != m_Objects.end())
+ AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second));
+}
+void CSimpleAnimationCore::RemoveAnimationFromLookupCache(Qt3DSDMAnimationHandle inAnimation) const
+{
+ THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation);
+ if (theAnim != m_Objects.end())
+ RemoveAnimationFromLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second));
+}
+
+// Ensure there is only one of these in the multimap.
+void CSimpleAnimationCore::AddAnimationToLookupCache(
+ std::shared_ptr<SAnimationTrack> inAnimation) const
+{
+ Qt3DSDMSlideHandle theSlide = inAnimation->m_Slide;
+ Qt3DSDMInstanceHandle theInstance = inAnimation->m_Instance;
+ pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange =
+ m_AnimationMatchesCache.equal_range(
+ make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()));
+ for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second;
+ ++theIter) {
+ if (theIter->second == inAnimation)
+ return;
+ }
+ m_AnimationMatchesCache.insert(
+ make_pair(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()), inAnimation));
+}
+
+// Remove this from the multimap
+void CSimpleAnimationCore::RemoveAnimationFromLookupCache(
+ std::shared_ptr<SAnimationTrack> inAnimation) const
+{
+ TStateInstanceAnimationMap &theMap(m_AnimationMatchesCache);
+ Qt3DSDMSlideHandle theSlide = inAnimation->m_Slide;
+ Qt3DSDMInstanceHandle theInstance = inAnimation->m_Instance;
+ pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange =
+ theMap.equal_range(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()));
+ for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second;
+ ++theIter) {
+ if (theIter->second == inAnimation) {
+ theMap.erase(theIter);
+ break;
+ }
+ }
+}
+
+//================================================================================
+// UICDMAnimation.h function implementations
+//================================================================================
+
+void CopyKeyframe(Qt3DSDMAnimationHandle inAnimation, Qt3DSDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore)
+{
+ TKeyframe theData = inSourceAnimationCore.GetKeyframeData(inKeyframe);
+ inDestAnimationCore.InsertKeyframe(inAnimation, theData);
+}
+
+void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore,
+ Qt3DSDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes)
+{
+ do_all(inKeyframes,
+ std::bind(CopyKeyframe, inDestAnimation, std::placeholders::_1,
+ std::cref(inSourceAnimationCore), std::ref(inDestAnimationCore)));
+}
+
+Qt3DSDMAnimationHandle CopyAnimation(TAnimationCorePtr inAnimationCore,
+ Qt3DSDMAnimationHandle inAnimation, Qt3DSDMSlideHandle inNewSlide,
+ Qt3DSDMInstanceHandle inNewInstance,
+ Qt3DSDMPropertyHandle inNewProperty, size_t inNewIndex)
+{
+ TKeyframeHandleList theKeyframes;
+ inAnimationCore->GetKeyframes(inAnimation, theKeyframes);
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ Qt3DSDMAnimationHandle theAnimation =
+ inAnimationCore->CreateAnimation(inNewSlide, inNewInstance, inNewProperty, inNewIndex,
+ theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe);
+ CopyKeyframes(*inAnimationCore, *inAnimationCore, theAnimation, theKeyframes);
+ return theAnimation;
+}
+
+SBezierKeyframe GetBezierKeyframeData(Qt3DSDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inAnimationCore)
+{
+ return get<SBezierKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe));
+}
+
+SEaseInEaseOutKeyframe GetEaseInEaseOutKeyframeData(Qt3DSDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inAnimationCore)
+{
+ return get<SEaseInEaseOutKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe));
+}
+
+TKeyframeHandleList::iterator SafeIncrementIterator(TKeyframeHandleList::iterator inIter,
+ const TKeyframeHandleList::iterator &inEnd)
+{
+ return inIter == inEnd ? inEnd : inIter + 1;
+}
+
+void GetKeyframesAsBezier(Qt3DSDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore,
+ TBezierKeyframeList &outKeyframes)
+{
+ SAnimationInfo theInfo(inAnimationCore.GetAnimationInfo(inAnimation));
+ TKeyframeHandleList theKeyframes;
+ inAnimationCore.GetKeyframes(inAnimation, theKeyframes);
+ outKeyframes.resize(theKeyframes.size());
+ switch (theInfo.m_AnimationType) {
+ default:
+ throw invalid_argument("AnimationType");
+ case EAnimationTypeBezier:
+ transform(theKeyframes.begin(), theKeyframes.end(), outKeyframes.begin(),
+ std::bind(GetBezierKeyframeData, std::placeholders::_1,
+ std::cref(inAnimationCore)));
+ break;
+ case EAnimationTypeEaseInOut: {
+
+ TKeyframeHandleList::iterator theEndKeyframe = theKeyframes.end();
+
+ typedef std::function<SEaseInEaseOutKeyframe(Qt3DSDMKeyframeHandle)> TConvertFunc;
+ TConvertFunc theDataConverter(
+ std::bind(GetEaseInEaseOutKeyframeData, std::placeholders::_1,
+ std::cref(inAnimationCore)));
+
+ TKeyframeHandleList::iterator thePreviousKeyframe = theKeyframes.begin();
+
+ TKeyframeHandleList::iterator theCurrentKeyframe =
+ SafeIncrementIterator(thePreviousKeyframe, theEndKeyframe);
+
+ TKeyframeHandleList::iterator theNextKeyframe =
+ SafeIncrementIterator(theCurrentKeyframe, theEndKeyframe);
+
+ TBezierKeyframeList::iterator theResult(outKeyframes.begin());
+
+ if (thePreviousKeyframe != theEndKeyframe) {
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+ if (theCurrentKeyframe != theEndKeyframe) {
+ theNextValue = theDataConverter(*theCurrentKeyframe).m_KeyframeValue;
+ theNextValuePtr = &theNextValue;
+ }
+ *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe(
+ NULL, theDataConverter(*thePreviousKeyframe), theNextValuePtr);
+ theResult = theResult + 1;
+ }
+ for (; theCurrentKeyframe != theEndKeyframe;
+ ++thePreviousKeyframe,
+ theCurrentKeyframe = SafeIncrementIterator(theCurrentKeyframe, theEndKeyframe),
+ theNextKeyframe = SafeIncrementIterator(theNextKeyframe, theEndKeyframe),
+ ++theResult) {
+ float theLastValue(theDataConverter(*thePreviousKeyframe).m_KeyframeValue);
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+ if (theNextKeyframe != theEndKeyframe) {
+ theNextValue = theDataConverter(*theNextKeyframe).m_KeyframeValue;
+ theNextValuePtr = &theNextValue;
+ }
+ *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe(
+ &theLastValue, theDataConverter(*theCurrentKeyframe), theNextValuePtr);
+ }
+ } break;
+ }
+}
+}