summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dm/systems/Qt3DSDMAnimation.h93
-rw-r--r--src/dm/systems/StudioAnimationSystem.cpp185
-rw-r--r--src/dm/systems/StudioAnimationSystem.h14
-rw-r--r--src/dm/systems/cores/AnimationCoreProducer.cpp13
-rw-r--r--src/dm/systems/cores/AnimationCoreProducer.h4
-rw-r--r--src/dm/systems/cores/SimpleAnimationCore.cpp13
-rw-r--r--src/dm/systems/cores/SimpleAnimationCore.h32
-rw-r--r--src/system/Qt3DSBezierEval.h16
8 files changed, 237 insertions, 133 deletions
diff --git a/src/dm/systems/Qt3DSDMAnimation.h b/src/dm/systems/Qt3DSDMAnimation.h
index 9009efb..4cc8630 100644
--- a/src/dm/systems/Qt3DSDMAnimation.h
+++ b/src/dm/systems/Qt3DSDMAnimation.h
@@ -39,6 +39,11 @@ struct SLinearKeyframe
{
float m_KeyframeSeconds;
float m_KeyframeValue;
+
+ SLinearKeyframe() = default;
+ SLinearKeyframe(float seconds, float value)
+ : m_KeyframeSeconds(seconds)
+ , m_KeyframeValue(value) {}
};
struct SBezierKeyframe : public SLinearKeyframe
@@ -47,6 +52,15 @@ struct SBezierKeyframe : public SLinearKeyframe
float m_InTangentValue; // value offset
float m_OutTangentTime; // time offset in seconds
float m_OutTangentValue; // value offset
+
+ SBezierKeyframe() = default;
+ SBezierKeyframe(float seconds, float value, float tangentInTime, float tangentInValue,
+ float tangentOutTime, float tangentOutValue)
+ : SLinearKeyframe(seconds, value)
+ , m_InTangentTime(tangentInTime)
+ , m_InTangentValue(tangentInValue)
+ , m_OutTangentTime(tangentOutTime)
+ , m_OutTangentValue(tangentOutValue) {}
};
typedef std::vector<SBezierKeyframe> TBezierKeyframeList;
@@ -62,6 +76,12 @@ struct SEaseInEaseOutKeyframe : public SLinearKeyframe
{
float m_EaseIn;
float m_EaseOut;
+
+ SEaseInEaseOutKeyframe() = default;
+ SEaseInEaseOutKeyframe(float seconds, float value, float easeIn, float easeOut)
+ : SLinearKeyframe(seconds, value)
+ , m_EaseIn(easeIn)
+ , m_EaseOut(easeOut) {}
};
} // namespace qt3dsdm
@@ -92,8 +112,8 @@ namespace qt3dsdm {
enum EAnimationType {
EAnimationTypeNone = 0,
EAnimationTypeLinear,
- EAnimationTypeBezier,
EAnimationTypeEaseInOut,
+ EAnimationTypeBezier,
};
template <typename TDataType>
@@ -246,7 +266,6 @@ public:
virtual void GetAnimations(TAnimationInfoList &outAnimations,
Qt3DSDMSlideHandle inMaster = Qt3DSDMSlideHandle(),
Qt3DSDMSlideHandle inSlide = Qt3DSDMSlideHandle()) const = 0;
-
virtual void GetSpecificInstanceAnimations(Qt3DSDMSlideHandle inSlide,
Qt3DSDMInstanceHandle inInstance,
TAnimationHandleList &outAnimations) = 0;
@@ -269,6 +288,7 @@ public:
TKeyframeHandleList &outKeyframes) const = 0;
virtual size_t GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const = 0;
virtual bool IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const = 0;
+ virtual bool IsLastKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const = 0;
virtual void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
long inOffset) = 0;
@@ -293,22 +313,17 @@ typedef std::shared_ptr<IAnimationCore> TAnimationCorePtr;
struct SGetOrSetKeyframeInfo
{
- float m_Value = 0.0;
- float m_EaseIn = -1.f;
- float m_EaseOut = -1.f;
+ qt3dsdm::TKeyframe m_keyframeData;
bool m_AnimationTrackIsDynamic = false;
- SGetOrSetKeyframeInfo(float inValue, float inEaseIn = -1.f, float inEaseOut = -1.f,
- bool inDynamic = false)
- : m_Value(inValue)
- , m_EaseIn(inEaseIn)
- , m_EaseOut(inEaseOut)
+ SGetOrSetKeyframeInfo(qt3dsdm::TKeyframe &keyframeData, bool inDynamic = false)
+ : m_keyframeData(keyframeData)
, m_AnimationTrackIsDynamic(inDynamic)
{
}
SGetOrSetKeyframeInfo() = default;
-
};
+
/**
* Interface from studio into the animation system that speaks
* a language near to that of studio. Public interface.
@@ -789,6 +804,33 @@ inline void GetEaseInOutValues(const TKeyframe &inValue, float &outEaseIn, float
outEaseOut = inValue.visit<float>(theEaseOutGetter);
}
+struct BezierValuesGetter
+{
+ QVector<float> operator()(const SLinearKeyframe &) const { return {}; }
+ QVector<float> operator()(const SEaseInEaseOutKeyframe &) const { return {}; }
+ QVector<float> operator()(const SBezierKeyframe &inValue) const
+ {
+ return {inValue.m_InTangentTime, inValue.m_InTangentValue,
+ inValue.m_OutTangentTime, inValue.m_OutTangentValue};
+ }
+ QVector<float> operator()()
+ {
+ QT3DS_ASSERT(false);
+ return {};
+ }
+};
+inline void getBezierValues(const TKeyframe &keyframe, float &tangentInTime, float &tangentInValue,
+ float &tangentOutTime, float &tangentOutValue)
+{
+ const QVector<float> values = keyframe.visit<QVector<float>>(BezierValuesGetter());
+ if (!values.empty()) {
+ tangentInTime = values[0];
+ tangentInValue = values[1];
+ tangentOutTime = values[2];
+ tangentOutValue = values[3];
+ }
+}
+
struct SEaseInSetter
{
float m_Value;
@@ -834,6 +876,35 @@ inline TKeyframe SetEaseInOutValues(TKeyframe &inKeyframe, float inEaseIn, float
return inKeyframe;
}
+struct BezierOffsetter
+{
+ float dt; // time offset in seconds
+
+ TKeyframe operator()(SLinearKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SEaseInEaseOutKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SBezierKeyframe &inKeyframe) const
+ {
+ inKeyframe.m_InTangentTime += dt;
+ inKeyframe.m_OutTangentTime += dt;
+
+ return inKeyframe;
+ }
+ TKeyframe operator()()
+ {
+ QT3DS_ASSERT(false);
+ return TKeyframe();
+ }
+};
+
+// dt: time offset in seconds
+inline TKeyframe offsetBezier(TKeyframe &inKeyframe, float dt)
+{
+ BezierOffsetter offsetter{dt};
+ inKeyframe.visit<TKeyframe>(offsetter);
+
+ return inKeyframe;
+}
+
void GetKeyframesAsBezier(Qt3DSDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore,
TBezierKeyframeList &outKeyframes);
}
diff --git a/src/dm/systems/StudioAnimationSystem.cpp b/src/dm/systems/StudioAnimationSystem.cpp
index be33bb1..4ecae00 100644
--- a/src/dm/systems/StudioAnimationSystem.cpp
+++ b/src/dm/systems/StudioAnimationSystem.cpp
@@ -158,45 +158,84 @@ bool CStudioAnimationSystem::GetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle
bool KeyframeNear(const TKeyframe &inKeyframe, float inSeconds)
{
- return fabs(KeyframeTime(inKeyframe) - inSeconds) < .01;
+ return fabs(KeyframeTime(inKeyframe) - inSeconds) < .01f;
}
-Qt3DSDMKeyframeHandle CreateKeyframeExplicit(Qt3DSDMAnimationHandle inAnimation, float inValue,
- float inSeconds, TAnimationCorePtr inAnimationCore,
- float inEaseIn, float inEaseOut)
+
+Qt3DSDMKeyframeHandle CStudioAnimationSystem::CreateKeyframeExplicit(
+ Qt3DSDMAnimationHandle inAnimation, float inValue, float inSeconds,
+ TKeyframe keyframeData)
{
TKeyframeHandleList theKeyframes;
- float theValue = inValue;
- inAnimationCore->GetKeyframes(inAnimation, theKeyframes);
+ m_AnimationCore->GetKeyframes(inAnimation, theKeyframes);
function<TKeyframe(Qt3DSDMKeyframeHandle)> theConverter(
- std::bind(&IAnimationCore::GetKeyframeData, inAnimationCore, std::placeholders::_1));
+ std::bind(&IAnimationCore::GetKeyframeData, m_AnimationCore, std::placeholders::_1));
TKeyframeHandleList::iterator theFind =
std::find_if(theKeyframes.begin(), theKeyframes.end(),
[theConverter, inSeconds](const Qt3DSDMKeyframeHandle &handle)
{ return KeyframeNear(theConverter(handle), inSeconds); });
- float theEaseIn = inEaseIn;
- float theEaseOut = inEaseOut;
- Qt3DSDMKeyframeHandle theKeyframe;
- if (theFind != theKeyframes.end()) {
- theKeyframe = *theFind;
+ if (keyframeData.getType()) { // not empty (paste keyframe case)
+ // offset control points time for bezier keyframes
+ offsetBezier(keyframeData, inSeconds - GetKeyframeSeconds(keyframeData));
+
+ keyframeData = SetKeyframeSeconds(keyframeData, inSeconds);
+ } else { // empty (insert new keyframe/change value case
+ EAnimationType animType = m_AnimationCore->GetAnimationInfo(inAnimation).m_AnimationType;
+ switch (animType) {
+ case EAnimationTypeLinear:
+ keyframeData = CreateLinearKeyframe(inSeconds, inValue);
+ break;
- inAnimationCore->SetKeyframeData(
- theKeyframe, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut));
+ case EAnimationTypeEaseInOut: {
+ float easeIn = m_SmoothInterpolation ? 100 : 0;
+ float easeOut = m_SmoothInterpolation ? 100 : 0;
+ keyframeData = CreateEaseInEaseOutKeyframe(inSeconds, inValue, easeIn, easeOut);
+ } break;
+
+ case EAnimationTypeBezier: {
+ float timeIn, valueIn, timeOut, valueOut;
+ // if keyframe exists, offset control points values
+ if (theFind != theKeyframes.end()) {
+ TKeyframe kfData = m_AnimationCore->GetKeyframeData(*theFind);
+ getBezierValues(kfData, timeIn, valueIn, timeOut, valueOut);
+ float dValue = inValue - KeyframeValueValue(kfData);
+ valueIn += dValue;
+ valueOut += dValue;
+ } else {
+ valueIn = inValue;
+ valueOut = inValue;
+ timeIn = inSeconds - .5f;
+ timeOut = inSeconds + .5f;
+ }
+ keyframeData = CreateBezierKeyframe(inSeconds, inValue, timeIn, valueIn,
+ timeOut, valueOut);
+ } break;
+
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+ }
+ Qt3DSDMKeyframeHandle keyframeHandle;
+ if (theFind != theKeyframes.end()) {
+ keyframeHandle = *theFind;
+ m_AnimationCore->SetKeyframeData(keyframeHandle, keyframeData);
} else {
- theKeyframe = inAnimationCore->InsertKeyframe(
- inAnimation, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut));
+ keyframeHandle = m_AnimationCore->InsertKeyframe(inAnimation, keyframeData);
}
- return theKeyframe;
+
+ return keyframeHandle;
}
-Qt3DSDMKeyframeHandle CreateKeyframe(Qt3DSDMAnimationHandle inAnimation, const SValue &inValue,
- float inSeconds, TAnimationCorePtr inAnimationCore,
- float inEaseIn, float inEaseOut)
+Qt3DSDMKeyframeHandle CStudioAnimationSystem::CreateKeyframe(Qt3DSDMAnimationHandle inAnimation,
+ const SValue &inValue, float inSeconds,
+ TAnimationCorePtr inAnimationCore)
{
SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+
return CreateKeyframeExplicit(inAnimation, GetAnimationValue(theInfo.m_Index, inValue),
- inSeconds, inAnimationCore, inEaseIn, inEaseOut);
+ inSeconds);
}
void MaybeAddAnimation(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
@@ -219,17 +258,17 @@ void GetPresentAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inIn
const TAnimationFloatPairList &inAnimationPairs,
TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations)
{
- function<void(Qt3DSDMAnimationHandle)> theOperation(
- std::bind(MaybeAddAnimation, inSlide, inInstance, inProperty,
- std::placeholders::_1, inAnimationCore,
- std::ref(outAnimations)));
-
for (auto animation : inAnimationPairs) {
MaybeAddAnimation(inSlide, inInstance, inProperty, animation.first, inAnimationCore,
std::ref(outAnimations));
}
if (outAnimations.empty()) {
+ function<void(Qt3DSDMAnimationHandle)> theOperation(
+ std::bind(MaybeAddAnimation, inSlide, inInstance, inProperty,
+ std::placeholders::_1, inAnimationCore,
+ std::ref(outAnimations)));
+
TAnimationHandleList theAnimationHandles;
inAnimationCore->GetAnimations(theAnimationHandles);
do_all(theAnimationHandles, theOperation);
@@ -240,11 +279,12 @@ void GetPresentAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inIn
}
void CreateAnimationAndAdd(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
- Qt3DSDMPropertyHandle inProperty, size_t inIndex,
- TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations)
+ Qt3DSDMPropertyHandle inProperty, qt3dsdm::EAnimationType animType,
+ size_t inIndex, TAnimationCorePtr inAnimationCore,
+ TAnimationHandleList &outAnimations)
{
outAnimations.push_back(inAnimationCore->CreateAnimation(
- inSlide, inInstance, inProperty, inIndex, EAnimationTypeEaseInOut, false));
+ inSlide, inInstance, inProperty, inIndex, animType, false));
}
bool AnimationValueDiffers(Qt3DSDMAnimationHandle inAnimation, const SValue &inValue,
@@ -266,61 +306,38 @@ bool AnimationExistsInPresentAnimations(const TAnimationFloatPair &inAnimation,
std::placeholders::_1));
}
-void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
- Qt3DSDMPropertyHandle inProperty, const SValue &inValue, float inTimeInSecs,
- bool inDoDiffValue, TAnimationCorePtr inAnimationCore,
- TAnimationFloatPairList &inAnimationFloatPairs, float inEaseIn,
- float inEaseOut)
+void CStudioAnimationSystem::DoKeyframeProperty(Qt3DSDMSlideHandle inSlide,
+ Qt3DSDMInstanceHandle inInstance, Qt3DSDMPropertyHandle inProperty,
+ const SValue &inValue, bool inDoDiffValue)
{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ float inTimeInSecs = m_SlideCore->GetSlideTime(m_SlideGraphCore
+ ->GetGraphActiveSlide(theGraphSlidePair.first));
+
size_t arity = GetVariantAnimatableArity(inValue);
TAnimationHandleList thePresentAnimations;
- GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(inAnimationFloatPairs),
- inAnimationCore, thePresentAnimations);
- if (thePresentAnimations.empty())
+ GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(m_AnimationFloatPairs),
+ m_AnimationCore, thePresentAnimations);
+ if (thePresentAnimations.empty()) {
+ // default newly created keyframes to EaseInOut
do_times(arity, std::bind(CreateAnimationAndAdd, inSlide, inInstance, inProperty,
- std::placeholders::_1,
- inAnimationCore, std::ref(thePresentAnimations)));
+ EAnimationTypeEaseInOut, std::placeholders::_1,
+ m_AnimationCore, std::ref(thePresentAnimations)));
+ }
if (!inDoDiffValue
|| find_if(thePresentAnimations.begin(), thePresentAnimations.end(),
std::bind(AnimationValueDiffers,
- std::placeholders::_1, inValue, inTimeInSecs, inAnimationCore))
+ std::placeholders::_1, inValue, inTimeInSecs, m_AnimationCore))
!= thePresentAnimations.end()) {
do_all(thePresentAnimations,
- std::bind(CreateKeyframe, std::placeholders::_1,
- std::cref(inValue), inTimeInSecs, inAnimationCore,
- inEaseIn, inEaseOut));
- erase_if(inAnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations,
+ std::bind(&CStudioAnimationSystem::CreateKeyframe, this, std::placeholders::_1,
+ std::cref(inValue), inTimeInSecs, m_AnimationCore));
+ erase_if(m_AnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations,
std::placeholders::_1,
std::ref(thePresentAnimations)));
}
}
-void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
- Qt3DSDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue,
- TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore,
- TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs,
- float inEaseIn, float inEaseOut)
-{
- TGraphSlidePair theGraphSlidePair = inSlideGraphCore->GetAssociatedGraph(inInstance);
- float theCurrentTime =
- inSlideCore->GetSlideTime(inSlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first));
- DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, theCurrentTime, inDoDiffValue,
- inAnimationCore, inAnimationFloatPairs, inEaseIn, inEaseOut);
-}
-
-void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
- Qt3DSDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue,
- TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore,
- TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs,
- bool inSmoothInterpolation)
-{
- float theEaseIn = 0.0f, theEaseOut = 0.0f;
- if (inSmoothInterpolation)
- theEaseIn = theEaseOut = 100.f;
- DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, inDoDiffValue, inAnimationCore,
- inSlideGraphCore, inSlideCore, inAnimationFloatPairs, theEaseIn, theEaseOut);
-}
-
TAnimationFloatPair CreateAnimationFloatPair(Qt3DSDMAnimationHandle inAnimation,
const SValue &inValue,
TAnimationCorePtr inAnimationCore)
@@ -346,14 +363,9 @@ bool CStudioAnimationSystem::SetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle
{
size_t arity = GetVariantAnimatableArity(inValue);
if (arity > 0) {
- if (m_AutoKeyframe && IsPropertyAnimated(inInstance, inProperty)) // prerequisite for
- // autoset-keyframes is
- // that the property is
- // already animated.
- {
- DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, true, m_AnimationCore,
- m_SlideGraphCore, m_SlideCore, m_AnimationFloatPairs,
- m_SmoothInterpolation);
+ // prerequisite for autoset-keyframes is that the property is already animated.
+ if (m_AutoKeyframe && IsPropertyAnimated(inInstance, inProperty)) {
+ DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, true);
return true;
}
@@ -366,7 +378,6 @@ bool CStudioAnimationSystem::SetAnimatedInstancePropertyValue(Qt3DSDMSlideHandle
std::ref(m_AnimationFloatPairs),
std::cref(inValue), m_AnimationCore));
-
if (m_Consumer && m_refreshCallback) {
// Only create a single refresh per transaction stack
if (((CTransactionConsumer *)m_Consumer.get())->m_TransactionList.size() == 0) {
@@ -470,8 +481,7 @@ void CStudioAnimationSystem::Animate(Qt3DSDMInstanceHandle inInstance,
if (!theFound)
DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(),
- true, m_AnimationCore, m_SlideGraphCore, m_SlideCore,
- m_AnimationFloatPairs, m_SmoothInterpolation);
+ true);
}
}
@@ -510,8 +520,7 @@ void CStudioAnimationSystem::KeyframeProperty(Qt3DSDMInstanceHandle inInstance,
GetApplicableGraphAndSlide(inInstance, inProperty, theValue.toOldSkool());
if (theApplicableSlide.Valid())
DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(),
- inDoDiffValue, m_AnimationCore, m_SlideGraphCore, m_SlideCore,
- m_AnimationFloatPairs, m_SmoothInterpolation);
+ inDoDiffValue);
}
void CStudioAnimationSystem::SetOrCreateKeyframe(Qt3DSDMInstanceHandle inInstance,
Qt3DSDMPropertyHandle inProperty,
@@ -525,22 +534,22 @@ void CStudioAnimationSystem::SetOrCreateKeyframe(Qt3DSDMInstanceHandle inInstanc
if (arity) {
theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
if (theApplicableSlide.Valid()) {
-
TAnimationHandleList thePresentAnimations;
GetPresentAnimations(theApplicableSlide, inInstance, inProperty,
std::cref(m_AnimationFloatPairs), m_AnimationCore,
thePresentAnimations);
size_t numIterations = std::min(inNumInfos, arity);
if (thePresentAnimations.empty()) {
+ qt3dsdm::EAnimationType animType = inKeyframeInfo[0].m_keyframeData.getType();
for (size_t idx = 0, end = numIterations; idx < end; ++idx) {
- CreateAnimationAndAdd(theApplicableSlide, inInstance, inProperty, idx,
+ CreateAnimationAndAdd(theApplicableSlide, inInstance, inProperty, animType, idx,
m_AnimationCore, thePresentAnimations);
}
}
for (size_t idx = 0, end = numIterations; idx < end; ++idx) {
- CreateKeyframeExplicit(thePresentAnimations[idx], inKeyframeInfo[idx].m_Value,
- inTimeInSeconds, m_AnimationCore,
- inKeyframeInfo[idx].m_EaseIn, inKeyframeInfo[idx].m_EaseOut);
+ CreateKeyframeExplicit(thePresentAnimations[idx],
+ KeyframeValueValue(inKeyframeInfo[idx].m_keyframeData),
+ inTimeInSeconds, inKeyframeInfo[idx].m_keyframeData);
if (inKeyframeInfo[idx].m_AnimationTrackIsDynamic)
m_AnimationCore->SetFirstKeyframeDynamic(thePresentAnimations[idx], true);
}
diff --git a/src/dm/systems/StudioAnimationSystem.h b/src/dm/systems/StudioAnimationSystem.h
index e6fdf75..5331490 100644
--- a/src/dm/systems/StudioAnimationSystem.h
+++ b/src/dm/systems/StudioAnimationSystem.h
@@ -126,8 +126,18 @@ private:
const SValue &inValue);
void OverrideChannelIfAnimated(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
- Qt3DSDMPropertyHandle inProperty, size_t inIndex, float inSeconds,
- bool &ioAnimated, SValue &outValue) const;
+ Qt3DSDMPropertyHandle inProperty, size_t inIndex,
+ float inSeconds, bool &ioAnimated, SValue &outValue) const;
+
+ void DoKeyframeProperty(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
+ Qt3DSDMPropertyHandle inProperty, const SValue &inValue,
+ bool inDoDiffValue);
+
+ Qt3DSDMKeyframeHandle CreateKeyframe(Qt3DSDMAnimationHandle inAnimation, const SValue &inValue,
+ float inSeconds, TAnimationCorePtr inAnimationCore);
+ Qt3DSDMKeyframeHandle CreateKeyframeExplicit(Qt3DSDMAnimationHandle inAnimation, float inValue,
+ float inSeconds, TKeyframe kfData = {});
+
};
}
diff --git a/src/dm/systems/cores/AnimationCoreProducer.cpp b/src/dm/systems/cores/AnimationCoreProducer.cpp
index 14d1824..d42ac1e 100644
--- a/src/dm/systems/cores/AnimationCoreProducer.cpp
+++ b/src/dm/systems/cores/AnimationCoreProducer.cpp
@@ -342,7 +342,7 @@ void CAnimationCoreProducer::OffsetAnimations(Qt3DSDMSlideHandle inSlide,
Qt3DSDMInstanceHandle inInstance,
long inMillisecondOffset)
{
- float theOffsetSeconds = static_cast<float>(inMillisecondOffset) / 1000.f;
+ float dt = static_cast<float>(inMillisecondOffset) / 1000.f; // time offset in seconds
for (THandleObjectMap::const_iterator iter = m_Data->m_Objects.begin(),
end = m_Data->m_Objects.end();
iter != end; ++iter) {
@@ -351,14 +351,13 @@ void CAnimationCoreProducer::OffsetAnimations(Qt3DSDMSlideHandle inSlide,
for (size_t keyframeIdx = 0, keyframeEnd = theTrack->m_Keyframes.size();
keyframeIdx < keyframeEnd; ++keyframeIdx) {
Qt3DSDMKeyframeHandle theKeyframeHandle(theTrack->m_Keyframes[keyframeIdx]);
- TKeyframe theCurrentKeyframe = m_Data->GetKeyframeData(theKeyframeHandle);
+ TKeyframe kfData = m_Data->GetKeyframeData(theKeyframeHandle);
- float seconds = qt3dsdm::GetKeyframeSeconds(theCurrentKeyframe);
+ // offset control points for bezier keyframes
+ offsetBezier(kfData, dt);
- theCurrentKeyframe =
- qt3dsdm::SetKeyframeSeconds(theCurrentKeyframe, seconds + theOffsetSeconds);
-
- SetKeyframeData(theKeyframeHandle, theCurrentKeyframe);
+ kfData = SetKeyframeSeconds(kfData, GetKeyframeSeconds(kfData) + dt);
+ SetKeyframeData(theKeyframeHandle, kfData);
}
}
}
diff --git a/src/dm/systems/cores/AnimationCoreProducer.h b/src/dm/systems/cores/AnimationCoreProducer.h
index 17603d6..0eb6fbd 100644
--- a/src/dm/systems/cores/AnimationCoreProducer.h
+++ b/src/dm/systems/cores/AnimationCoreProducer.h
@@ -97,6 +97,10 @@ public:
{
return m_Data->IsFirstKeyframe(inKeyframe);
}
+ bool IsLastKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override
+ {
+ return m_Data->IsLastKeyframe(inKeyframe);
+ }
void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
long inMillisecondOffset) override;
diff --git a/src/dm/systems/cores/SimpleAnimationCore.cpp b/src/dm/systems/cores/SimpleAnimationCore.cpp
index 00d6df4..24e9694 100644
--- a/src/dm/systems/cores/SimpleAnimationCore.cpp
+++ b/src/dm/systems/cores/SimpleAnimationCore.cpp
@@ -303,6 +303,17 @@ bool CSimpleAnimationCore::IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) con
return false;
}
+bool CSimpleAnimationCore::IsLastKeyframe(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[theItem->m_Keyframes.size() - 1]
+ == inKeyframe;
+ }
+ return false;
+}
+
void CSimpleAnimationCore::OffsetAnimations(Qt3DSDMSlideHandle /*inSlide*/,
Qt3DSDMInstanceHandle /*inInstance*/, long /*inOffset*/)
{
@@ -382,7 +393,7 @@ float CSimpleAnimationCore::EvaluateAnimation(Qt3DSDMAnimationHandle inAnimation
return 0.0f;
CheckKeyframesSorted(theItem, m_Objects);
// Default to linear for now.
- SLinearKeyframe theKeyframe = { 0 };
+ SLinearKeyframe theKeyframe;
theKeyframe.m_KeyframeSeconds = inSeconds;
TKeyframe theSearchKey(theKeyframe);
function<TKeyframe(int)> theIntToKeyframe(
diff --git a/src/dm/systems/cores/SimpleAnimationCore.h b/src/dm/systems/cores/SimpleAnimationCore.h
index cb4c415..d1b5245 100644
--- a/src/dm/systems/cores/SimpleAnimationCore.h
+++ b/src/dm/systems/cores/SimpleAnimationCore.h
@@ -48,27 +48,17 @@ struct pair_hash {
namespace qt3dsdm {
struct SAnimationTrack : public CHandleObject
{
- int m_Slide;
- int m_Instance;
- int m_Property;
- EAnimationType m_AnimationType;
- size_t m_Index;
+ int m_Slide = 0;
+ int m_Instance = 0;
+ int m_Property = 0;
+ EAnimationType m_AnimationType = EAnimationTypeLinear;
+ size_t m_Index = 0;
TKeyframeHandleList m_Keyframes;
- bool m_KeyframesDirty;
- bool m_FirstKeyframeDynamic;
- bool m_ArtistEdited;
-
- SAnimationTrack()
- : m_Slide(0)
- , m_Instance(0)
- , m_Property(0)
- , m_AnimationType(EAnimationTypeLinear)
- , m_Index(0)
- , m_KeyframesDirty(false)
- , m_FirstKeyframeDynamic(false)
- , m_ArtistEdited(true)
- {
- }
+ bool m_KeyframesDirty = false;
+ bool m_FirstKeyframeDynamic = false;
+ bool m_ArtistEdited = true;
+
+ SAnimationTrack() = default;
SAnimationTrack(int inHandle, Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
Qt3DSDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType,
@@ -79,7 +69,6 @@ struct SAnimationTrack : public CHandleObject
, m_Property(inProperty)
, m_AnimationType(inAnimationType)
, m_Index(inIndex)
- , m_KeyframesDirty(false)
, m_FirstKeyframeDynamic(inFirstKeyframeDynamic)
, m_ArtistEdited(inArtistEdited)
{
@@ -159,6 +148,7 @@ public: // Use
void GetKeyframes(Qt3DSDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override;
size_t GetKeyframeCount(Qt3DSDMAnimationHandle inAnimation) const override;
bool IsFirstKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override;
+ bool IsLastKeyframe(Qt3DSDMKeyframeHandle inKeyframe) const override;
// Only implemented in the producer for now.
void OffsetAnimations(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inInstance,
long inOffset) override;
diff --git a/src/system/Qt3DSBezierEval.h b/src/system/Qt3DSBezierEval.h
index c4d733a..46f8a3d 100644
--- a/src/system/Qt3DSBezierEval.h
+++ b/src/system/Qt3DSBezierEval.h
@@ -147,7 +147,16 @@ inline FLOAT EvaluateInverseBezierCurve(const FLOAT inP0, const FLOAT inP1, cons
}
} else {
INT32 theNumRoots = CCubicRoots::SolveCubic(theConstants, theSolution);
- theResult = static_cast<FLOAT>(theSolution[theNumRoots / 3]);
+ INT32 solutionIndex = theNumRoots / 3;
+ theResult = static_cast<FLOAT>(theSolution[solutionIndex]);
+
+ // if the result is not within bounds, correct solutionIndex to pick the right solution
+ // TODO: in rare situations the 3 solutions for the cubic equation are all invalid. It's
+ // worth investigating.
+ if (theResult <= 0)
+ theResult = static_cast<FLOAT>(theSolution[solutionIndex - 1]);
+ else if (theResult >= 1)
+ theResult = static_cast<FLOAT>(theSolution[solutionIndex + 1]);
}
return theResult;
@@ -157,7 +166,6 @@ inline FLOAT EvaluateBezierKeyframe(FLOAT inTime, FLOAT inTime1, FLOAT inValue1,
FLOAT inC1Value, FLOAT inC2Time, FLOAT inC2Value, FLOAT inTime2,
FLOAT inValue2)
{
-
// The special case of C1Time=0 and C2Time=0 is used to indicate Studio-native animation.
// Studio uses a simplified version of the bezier animation where the time control points
// are equally spaced between the starting and ending times. This avoids calling the expensive
@@ -171,12 +179,14 @@ inline FLOAT EvaluateBezierKeyframe(FLOAT inTime, FLOAT inTime1, FLOAT inValue1,
} else {
// Compute the "s" parameter on the Bezier given the time
theParameter = EvaluateInverseBezierCurve(inTime1, inC1Time, inC2Time, inTime2, inTime);
+
if (theParameter <= 0.0f)
return inValue1;
+
if (theParameter >= 1.0f)
return inValue2;
}
return EvaluateBezierCurve(inValue1, inC1Value, inC2Value, inValue2, theParameter);
}
-}
+} // namespace Qt3DStudio