diff options
author | Juan José Casafranca <juan.casafranca@kdab.com> | 2017-09-10 14:52:46 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-10-06 12:10:05 +0000 |
commit | f0153ae8b12cc68ed6e38a1d93b83bb235b5e501 (patch) | |
tree | 311ec5c364d87ffc36b567986af3ff9823b3bbf1 | |
parent | c9bc1d866d69092f4fafe626687fe0f5746c829a (diff) |
Fix animation local time calculation when changing playbackRate
Animation local time was computed in absolute mode, as a scale of the
global time that has passed since the start of the animation. Now is
computed relative to the last local time, as the last local time + a
scale of the elapsed global time.
Change-Id: I5c29002602a5184174618ac7755ec94f5c7a328f
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/animation/backend/animationutils.cpp | 49 | ||||
-rw-r--r-- | src/animation/backend/animationutils_p.h | 20 | ||||
-rw-r--r-- | src/animation/backend/blendedclipanimator.cpp | 27 | ||||
-rw-r--r-- | src/animation/backend/blendedclipanimator_p.h | 13 | ||||
-rw-r--r-- | src/animation/backend/clipanimator.cpp | 23 | ||||
-rw-r--r-- | src/animation/backend/clipanimator_p.h | 12 | ||||
-rw-r--r-- | src/animation/backend/evaluateblendclipanimatorjob.cpp | 30 | ||||
-rw-r--r-- | src/animation/backend/evaluateblendclipanimatorjob_p.h | 3 | ||||
-rw-r--r-- | src/animation/backend/evaluateclipanimatorjob.cpp | 14 | ||||
-rw-r--r-- | src/animation/backend/evaluateclipanimatorjob_p.h | 3 | ||||
-rw-r--r-- | tests/auto/animation/animationutils/tst_animationutils.cpp | 435 | ||||
-rw-r--r-- | tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp | 7 | ||||
-rw-r--r-- | tests/manual/animation-keyframe-blendtree/main.qml | 26 | ||||
-rw-r--r-- | tests/manual/animation-keyframe-simple/main.qml | 22 |
14 files changed, 323 insertions, 361 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index 3e255308b..fb5b19a5d 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -93,22 +93,26 @@ ClipEvaluationData evaluationDataForClip(AnimationClip *clip, { // global time values expected in seconds ClipEvaluationData result; - result.localTime = localTimeFromGlobalTime(animatorData.globalTime, animatorData.startTime, - animatorData.playbackRate, clip->duration(), - animatorData.loopCount, result.currentLoop); + result.currentLoop = animatorData.currentLoop; + result.localTime = localTimeFromElapsedTime(animatorData.currentTime, animatorData.elapsedTime, + animatorData.playbackRate, clip->duration(), + animatorData.loopCount, result.currentLoop); result.isFinalFrame = isFinalFrame(result.localTime, clip->duration(), result.currentLoop, animatorData.loopCount); return result; } -double localTimeFromGlobalTime(double t_global, - double t_start_global, - double playbackRate, - double duration, - int loopCount, - int ¤tLoop) +double localTimeFromElapsedTime(double t_current_local, + double t_elapsed_global, + double playbackRate, + double duration, + int loopCount, + int ¤tLoop) { - double t_local = playbackRate * (t_global - t_start_global); + // Calculate the new local time. + // playhead + rate * dt + // where playhead is completed loops * duration + current loop local time + double t_local = currentLoop * duration + t_current_local + playbackRate * t_elapsed_global; double loopNumber = 0; if (loopCount == 1) { t_local = qBound(0.0, t_local, duration); @@ -123,28 +127,30 @@ double localTimeFromGlobalTime(double t_global, t_local = std::fmod(t_local, duration); // Ensure we clamp to end of final loop - if (loopNumber == loopCount) { + if (int(loopNumber) == loopCount) { loopNumber = loopCount - 1; t_local = duration; } } - qCDebug(Jobs) << "t_global - t_start =" << t_global - t_start_global - << "current loop =" << loopNumber + qCDebug(Jobs) << "current loop =" << loopNumber << "t =" << t_local << "duration =" << duration; - currentLoop = loopNumber; + currentLoop = int(loopNumber); return t_local; } -double phaseFromGlobalTime(double t_global, double t_start_global, - double playbackRate, double duration, - int loopCount, int ¤tLoop) +double phaseFromElapsedTime(double t_current_local, + double t_elapsed_global, + double playbackRate, + double duration, + int loopCount, + int ¤tLoop) { - const double t_local = localTimeFromGlobalTime(t_global, t_start_global, playbackRate, - duration, loopCount, currentLoop); + const double t_local = localTimeFromElapsedTime(t_current_local, t_elapsed_global, playbackRate, + duration, loopCount, currentLoop); return t_local / duration; } @@ -455,6 +461,11 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; const int index = channelNamesAndTypes.indexOf(nameAndType); if (index != -1) { + // Do we have any animation data for this channel? If not, don't bother + // adding a mapping for it. + if (channelComponentIndices[index].isEmpty()) + continue; + // We got one! mappingData.channelIndices = channelComponentIndices[index]; mappingDataVec.push_back(mappingData); diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index fb9e44680..d8127d8af 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -106,9 +106,10 @@ inline QDebug operator<<(QDebug dbg, const MappingData &mapping) struct AnimatorEvaluationData { - double globalTime; - double startTime; + double elapsedTime; + double currentTime; int loopCount; + int currentLoop; double playbackRate; }; @@ -157,14 +158,15 @@ struct AnimationCallbackAndValue }; template<typename Animator> -AnimatorEvaluationData evaluationDataForAnimator(Animator animator, Clock* clock, qint64 globalTime) +AnimatorEvaluationData evaluationDataForAnimator(Animator animator, Clock* clock, qint64 nsSincePreviousFrame) { AnimatorEvaluationData data; data.loopCount = animator->loops(); + data.currentLoop = animator->currentLoop(); data.playbackRate = clock != nullptr ? clock->playbackRate() : 1.0; // Convert global time from nsec to sec - data.startTime = double(animator->startTime()) / 1.0e9; - data.globalTime = double(globalTime) / 1.0e9; + data.elapsedTime = double(nsSincePreviousFrame) / 1.0e9; + data.currentTime = animator->lastLocalTime(); return data; } @@ -227,12 +229,12 @@ Q_AUTOTEST_EXPORT QVector<ComponentIndices> assignChannelComponentIndices(const QVector<ChannelNameAndType> &namesAndTypes); Q_AUTOTEST_EXPORT -double localTimeFromGlobalTime(double t_global, double t_start_global, - double playbackRate, double duration, - int loopCount, int ¤tLoop); +double localTimeFromElapsedTime(double t_current_local, double t_elapsed_global, + double playbackRate, double duration, + int loopCount, int ¤tLoop); Q_AUTOTEST_EXPORT -double phaseFromGlobalTime(double t_global, double t_start_global, +double phaseFromElapsedTime(double t_current_local, double t_elapsed_global, double playbackRate, double duration, int loopCount, int ¤tLoop); diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp index ec0a5027a..1487d6c3e 100644 --- a/src/animation/backend/blendedclipanimator.cpp +++ b/src/animation/backend/blendedclipanimator.cpp @@ -48,7 +48,8 @@ namespace Animation { BlendedClipAnimator::BlendedClipAnimator() : BackendNode(ReadWrite) , m_running(false) - , m_startGlobalTime(0) + , m_lastGlobalTimeNS(0) + , m_lastLocalTime(0.0) , m_currentLoop(0) , m_loops(1) { @@ -66,6 +67,26 @@ void BlendedClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeB setDirty(Handler::BlendedClipAnimatorDirty); } +double BlendedClipAnimator::lastLocalTime() const +{ + return m_lastLocalTime; +} + +void BlendedClipAnimator::setLastLocalTime(double lastLocalTime) +{ + m_lastLocalTime = lastLocalTime; +} + +void BlendedClipAnimator::setLastGlobalTimeNS(const qint64 &lastGlobalTimeNS) +{ + m_lastGlobalTimeNS = lastGlobalTimeNS; +} + +qint64 BlendedClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS) +{ + return currentGlobalTimeNS - m_lastGlobalTimeNS; +} + void BlendedClipAnimator::cleanup() { setEnabled(false); @@ -74,7 +95,8 @@ void BlendedClipAnimator::cleanup() m_mapperId = Qt3DCore::QNodeId(); m_clockId = Qt3DCore::QNodeId(); m_running = false; - m_startGlobalTime = 0; + m_lastGlobalTimeNS = 0; + m_lastLocalTime = 0.0; m_currentLoop = 0; m_loops = 1; } @@ -124,6 +146,7 @@ void BlendedClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> } } + Qt3DCore::QNodeId BlendedClipAnimator::blendTreeRootId() const { return m_blendTreeRootId; diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h index d9f89b5f9..dd99c4274 100644 --- a/src/animation/backend/blendedclipanimator_p.h +++ b/src/animation/backend/blendedclipanimator_p.h @@ -79,8 +79,7 @@ public: void setClockId(Qt3DCore::QNodeId clockId); void setRunning(bool running); - void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; } - qint64 startTime() const { return m_startGlobalTime; } + void setStartTime(qint64 globalTime) { m_lastGlobalTimeNS = globalTime; } void setLoops(int loops) { m_loops = loops; } int loops() const { return m_loops; } @@ -96,6 +95,12 @@ public: void animationClipMarkedDirty() { setDirty(Handler::BlendedClipAnimatorDirty); } + qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS); + void setLastGlobalTimeNS(const qint64 &lastGlobalTimeNS); + + double lastLocalTime() const; + void setLastLocalTime(double lastLocalTime); + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; Qt3DCore::QNodeId m_blendTreeRootId; @@ -103,7 +108,9 @@ private: Qt3DCore::QNodeId m_clockId; bool m_running; - qint64 m_startGlobalTime; + qint64 m_lastGlobalTimeNS; + double m_lastLocalTime; + int m_currentLoop; int m_loops; diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index 568e2dbb0..21c08b80a 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -56,7 +56,8 @@ ClipAnimator::ClipAnimator() , m_clockId() , m_running(false) , m_loops(1) - , m_startGlobalTime(0) + , m_lastGlobalTimeNS(0) + , m_lastLocalTime(0.0) , m_mappingData() , m_currentLoop(0) { @@ -162,6 +163,26 @@ void ClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callb } } +qint64 ClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS) +{ + return currentGlobalTimeNS - m_lastGlobalTimeNS; +} + +void ClipAnimator::setLastGlobalTimeNS(qint64 lastGlobalTimeNS) +{ + m_lastGlobalTimeNS = lastGlobalTimeNS; +} + +double ClipAnimator::lastLocalTime() const +{ + return m_lastLocalTime; +} + +void ClipAnimator::setLastLocalTime(double lastLocalTime) +{ + m_lastLocalTime = lastLocalTime; +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index 8a08969ba..0f7380d66 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -86,8 +86,7 @@ public: void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; } QVector<MappingData> mappingData() const { return m_mappingData; } - void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; } - qint64 startTime() const { return m_startGlobalTime; } + void setStartTime(qint64 globalTime) { m_lastGlobalTimeNS = globalTime; } int currentLoop() const { return m_currentLoop; } void setCurrentLoop(int currentLoop) { m_currentLoop = currentLoop; } @@ -100,6 +99,12 @@ public: void setFormatIndices(const ComponentIndices &formatIndices) { m_formatIndices = formatIndices; } ComponentIndices formatIndices() const { return m_formatIndices; } + qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS); + void setLastGlobalTimeNS(qint64 lastGlobalTimeNS); + + double lastLocalTime() const; + void setLastLocalTime(double lastLocalTime); + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; @@ -110,7 +115,8 @@ private: int m_loops; // Working state - qint64 m_startGlobalTime; + qint64 m_lastGlobalTimeNS; + double m_lastLocalTime; QVector<MappingData> m_mappingData; int m_currentLoop; diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp index be05f7ec0..3cde7b32f 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob.cpp +++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp @@ -51,6 +51,8 @@ namespace Animation { EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob() : Qt3DCore::QAspectJob() + , m_currentGlobalTime(0.0) + , m_lastGlobalTime(0.0) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0); } @@ -62,7 +64,15 @@ void EvaluateBlendClipAnimatorJob::run() // TODO: We should be able to cache this for each blend animator and only // update when a node indicates its dependencies have changed as a result // of blend factors changing + BlendedClipAnimator *blendedClipAnimator = m_handler->blendedClipAnimatorManager()->data(m_blendClipAnimatorHandle); + Q_ASSERT(blendedClipAnimator); + if (!blendedClipAnimator->isRunning()) + return; + + qint64 globalTimeNS = m_handler->simulationTime(); + qint64 nsSincePreviousFrame = blendedClipAnimator->nsSincePreviousFrame(globalTimeNS); + Qt3DCore::QNodeId blendTreeRootId = blendedClipAnimator->blendTreeRootId(); const QVector<Qt3DCore::QNodeId> valueNodeIdsToEvaluate = gatherValueNodesToEvaluate(m_handler, blendTreeRootId); @@ -75,15 +85,12 @@ void EvaluateBlendClipAnimatorJob::run() Clock *clock = m_handler->clockManager()->lookupResource(blendedClipAnimator->clockId()); // Calculate the phase given the blend tree duration and global time - const qint64 globalTime = m_handler->simulationTime(); - const AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, clock, globalTime); - int currentLoop = 0; - const double phase = phaseFromGlobalTime(animatorData.globalTime, - animatorData.startTime, - animatorData.playbackRate, - duration, - animatorData.loopCount, - currentLoop); + AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, clock, nsSincePreviousFrame); + const double phase = phaseFromElapsedTime(animatorData.currentTime, animatorData.elapsedTime, + animatorData.playbackRate, + duration, + animatorData.loopCount, + animatorData.currentLoop); // Iterate over the value nodes of the blend tree, evaluate the // contained animation clips at the current phase and store the results @@ -107,7 +114,10 @@ void EvaluateBlendClipAnimatorJob::run() ClipResults blendedResults = evaluateBlendTree(m_handler, blendedClipAnimator, blendTreeRootId); const double localTime = phase * duration; - const bool finalFrame = isFinalFrame(localTime, duration, currentLoop, animatorData.loopCount); + blendedClipAnimator->setLastGlobalTimeNS(globalTimeNS); + blendedClipAnimator->setLastLocalTime(localTime); + blendedClipAnimator->setCurrentLoop(animatorData.currentLoop); + const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount); // Prepare the property change events const QVector<MappingData> mappingData = blendedClipAnimator->mappingData(); diff --git a/src/animation/backend/evaluateblendclipanimatorjob_p.h b/src/animation/backend/evaluateblendclipanimatorjob_p.h index a7822c8f9..ff578e517 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob_p.h +++ b/src/animation/backend/evaluateblendclipanimatorjob_p.h @@ -78,6 +78,9 @@ protected: private: HBlendedClipAnimator m_blendClipAnimatorHandle; Handler *m_handler; + + qint64 m_currentGlobalTime; + qint64 m_lastGlobalTime; }; typedef QSharedPointer<EvaluateBlendClipAnimatorJob> EvaluateBlendClipAnimatorJobPtr; diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index d9600c375..972762033 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -48,6 +48,8 @@ namespace Animation { EvaluateClipAnimatorJob::EvaluateClipAnimatorJob() : Qt3DCore::QAspectJob() + , m_currentGlobalTime(0.0) + , m_lastGlobalTime(0.0) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0); } @@ -56,11 +58,13 @@ void EvaluateClipAnimatorJob::run() { Q_ASSERT(m_handler); - const qint64 globalTime = m_handler->simulationTime(); - //qDebug() << Q_FUNC_INFO << "t_global =" << globalTime; - ClipAnimator *clipAnimator = m_handler->clipAnimatorManager()->data(m_clipAnimatorHandle); Q_ASSERT(clipAnimator); + if (!clipAnimator->isRunning()) + return; + + qint64 globalTimeNS = m_handler->simulationTime(); + qint64 nsSincePreviousFrame = clipAnimator->nsSincePreviousFrame(globalTimeNS); Clock *clock = m_handler->clockManager()->lookupResource(clipAnimator->clockId()); @@ -68,7 +72,7 @@ void EvaluateClipAnimatorJob::run() AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); Q_ASSERT(clip); // Prepare for evaluation (convert global time to local time ....) - const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, globalTime); + const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, nsSincePreviousFrame); const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData); const ClipResults rawClipResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); @@ -80,6 +84,8 @@ void EvaluateClipAnimatorJob::run() clipAnimator->setRunning(false); clipAnimator->setCurrentLoop(preEvaluationDataForClip.currentLoop); + clipAnimator->setLastGlobalTimeNS(globalTimeNS); + clipAnimator->setLastLocalTime(preEvaluationDataForClip.localTime); // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend) const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(), diff --git a/src/animation/backend/evaluateclipanimatorjob_p.h b/src/animation/backend/evaluateclipanimatorjob_p.h index 866032dd1..911341788 100644 --- a/src/animation/backend/evaluateclipanimatorjob_p.h +++ b/src/animation/backend/evaluateclipanimatorjob_p.h @@ -82,6 +82,9 @@ protected: private: HClipAnimator m_clipAnimatorHandle; Handler *m_handler; + + qint64 m_currentGlobalTime; + qint64 m_lastGlobalTime; }; } // namespace Animation diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index c3253b9ce..5ec8c7d60 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -549,336 +549,137 @@ private Q_SLOTS: delete handler; } - void checkLocalTimeFromGlobalTime_data() + void checkLocalTimeFromElapsedTime_data() { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("elapsedTime"); + QTest::addColumn<double>("currentTime"); QTest::addColumn<double>("playbackRate"); QTest::addColumn<double>("duration"); QTest::addColumn<int>("loopCount"); + QTest::addColumn<int>("currentLoop"); QTest::addColumn<double>("expectedLocalTime"); QTest::addColumn<int>("expectedCurrentLoop"); - double globalTime; - double globalStartTime; + double elapsedTime; + double currentTime; double playbackRate; double duration; int loopCount; + int currentLoop; double expectedLocalTime; int expectedCurrentLoop; - globalTime = 0.0; - globalStartTime = 0.0; + elapsedTime = 0.0; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.5; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.0; - globalStartTime = 0.0; + elapsedTime = 1.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 1.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedLocalTime = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedLocalTime = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 2; - expectedLocalTime = 0.5; + currentLoop = 0; + expectedLocalTime = 0.1; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 3.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedLocalTime = 1.5; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; + duration = 1.0; loopCount = 2; - expectedLocalTime = 2.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + currentLoop = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 1; // We clamp at end of final loop + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; + elapsedTime = 0.5; + currentTime = 0.6; + playbackRate = 0.1; duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.5; + loopCount = 2; + currentLoop = 1; + expectedLocalTime = 0.65; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; } - void checkLocalTimeFromGlobalTime() + void checkLocalTimeFromElapsedTime() { // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); + QFETCH(double, elapsedTime); + QFETCH(double, currentTime); QFETCH(double, playbackRate); QFETCH(double, duration); QFETCH(int, loopCount); + QFETCH(int, currentLoop); QFETCH(double, expectedLocalTime); QFETCH(int, expectedCurrentLoop); // WHEN - int actualCurrentLoop = 0; - double actualLocalTime = localTimeFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); + int actualCurrentLoop = currentLoop; + double actualLocalTime = localTimeFromElapsedTime(currentTime, + elapsedTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); // THEN QCOMPARE(actualCurrentLoop, expectedCurrentLoop); QCOMPARE(actualLocalTime, expectedLocalTime); } - void checkPhaseFromGlobalTime_data() - { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); - QTest::addColumn<double>("playbackRate"); - QTest::addColumn<double>("duration"); - QTest::addColumn<int>("loopCount"); - QTest::addColumn<double>("expectedPhase"); - QTest::addColumn<int>("expectedCurrentLoop"); - - double globalTime; - double globalStartTime; - double playbackRate; - double duration; - int loopCount; - double expectedPhase; - int expectedCurrentLoop; - - globalTime = 0.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 3.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 0.75; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 1.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - } - - void checkPhaseFromGlobalTime() - { - // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); - QFETCH(double, playbackRate); - QFETCH(double, duration); - QFETCH(int, loopCount); - QFETCH(double, expectedPhase); - QFETCH(int, expectedCurrentLoop); - - // WHEN - int actualCurrentLoop = 0; - double actualPhase = phaseFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); - - // THEN - QCOMPARE(actualCurrentLoop, expectedCurrentLoop); - QCOMPARE(actualPhase, expectedPhase); - } - void checkPreparePropertyChanges_data() { QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); @@ -1880,11 +1681,13 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 0; - animatorData = evaluationDataForAnimator(animator, clock, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 0; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, @@ -1901,18 +1704,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration()+1)*1e09; // +1 to ensure beyond end + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = duration") + QTest::newRow("clip1.json, elapsedTime = duration + 1") << handler << clip << animatorData << clipData; } @@ -1922,18 +1727,43 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 0; // Infinite loops auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 2.0 * clip->duration() * 1.0e9; - animatorData = evaluationDataForAnimator(animator, clock, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 2.0 * clip->duration() * 1.0e9; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = false; - QTest::newRow("clip1.json, globalTime = 2 * duration, loops = infinite") + QTest::newRow("clip1.json, elapsedTime = 2 * duration, loops = infinite") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 2; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, elapsedTime = 2 * duration + 1, loops = 2") << handler << clip << animatorData << clipData; } @@ -1943,18 +1773,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 2; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(1); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = 2 * duration + 1, loops = 2") + QTest::newRow("clip1.json, elapsedTime = duration + 1, loops = 2, current_loop = 1") << handler << clip << animatorData << clipData; } } @@ -1983,12 +1815,12 @@ private Q_SLOTS: { QTest::addColumn<Handler *>("handler"); QTest::addColumn<ClipAnimator *>("animator"); - QTest::addColumn<qint64>("globalTimeNS"); + QTest::addColumn<qint64>("elapsedTime"); QTest::addColumn<AnimatorEvaluationData>("expectedAnimatorData"); Handler *handler; ClipAnimator *animator; - qint64 globalTimeNS; + qint64 elapsedTimeNS; AnimatorEvaluationData expectedAnimatorData; { @@ -1996,15 +1828,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2012,15 +1843,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 5; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 5") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 5") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2028,15 +1858,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 5000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 5.0; - QTest::newRow("globalStartTime = 0, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 5, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2044,15 +1873,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 3000000000; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 2000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 3.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 2.0; - QTest::newRow("globalStartTime = 3, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 3, elapsedTime = 2, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } } @@ -2061,17 +1889,16 @@ private Q_SLOTS: // GIVEN QFETCH(Handler *, handler); QFETCH(ClipAnimator *, animator); - QFETCH(qint64, globalTimeNS); + QFETCH(qint64, elapsedTime); QFETCH(AnimatorEvaluationData, expectedAnimatorData); // WHEN - AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); + AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, elapsedTime); // THEN QCOMPARE(actualAnimatorData.loopCount, expectedAnimatorData.loopCount); QVERIFY(fuzzyCompare(actualAnimatorData.playbackRate, expectedAnimatorData.playbackRate) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.startTime, expectedAnimatorData.startTime) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.globalTime, expectedAnimatorData.globalTime) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.elapsedTime, expectedAnimatorData.elapsedTime) == true); // Cleanup delete handler; diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index 3265de167..c0e1581f9 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -63,7 +63,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); @@ -82,6 +83,7 @@ private Q_SLOTS: backendBlendedClipAnimator.setMapperId(Qt3DCore::QNodeId::createId()); backendBlendedClipAnimator.setRunning(true); backendBlendedClipAnimator.setStartTime(28); + backendBlendedClipAnimator.setLastLocalTime(0.28); backendBlendedClipAnimator.cleanup(); // THEN @@ -89,7 +91,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } diff --git a/tests/manual/animation-keyframe-blendtree/main.qml b/tests/manual/animation-keyframe-blendtree/main.qml index 23aba4b79..3d7fa47e5 100644 --- a/tests/manual/animation-keyframe-blendtree/main.qml +++ b/tests/manual/animation-keyframe-blendtree/main.qml @@ -75,16 +75,36 @@ DefaultSceneEntity { shininess: 50 }, ObjectPicker { - onClicked: blendedAnimator.running = true + onClicked: { + if (blendedAnimator.running == false) { + blendedAnimator.running = true; + } else { + switch (pick.button) { + case PickEvent.RightButton: + animatorClock.playbackRate *= 2.0; + break; + case PickEvent.LeftButton: + animatorClock.playbackRate /= 2.0; + break; + default: + break; + } + } + } }, BlendedClipAnimator { id: blendedAnimator - loops: 2 + loops: 3 + + clock: Clock { + id: animatorClock + playbackRate: 0.5 + } onRunningChanged: console.log("running = " + running) blendTree: LerpClipBlend { - blendFactor: 0.2 + blendFactor: 0.8 startClip: ClipBlendValue { clip: AnimationClipLoader { source: "sliding-cube.json" } } diff --git a/tests/manual/animation-keyframe-simple/main.qml b/tests/manual/animation-keyframe-simple/main.qml index 79fb75fbd..9246f2467 100644 --- a/tests/manual/animation-keyframe-simple/main.qml +++ b/tests/manual/animation-keyframe-simple/main.qml @@ -75,13 +75,33 @@ DefaultSceneEntity { shininess: 50 }, ObjectPicker { - onClicked: animator.running = true + onClicked: { + if (animator.running == false) { + animator.running = true; + } else { + switch (pick.button) { + case PickEvent.RightButton: + animationClock.playbackRate *= 2.0; + break; + case PickEvent.LeftButton: + animationClock.playbackRate /= 2.0; + break; + default: + break; + } + } + } }, ClipAnimator { id: animator loops: 3 onRunningChanged: console.log("running = " + running) + clock: Clock { + id: animationClock + playbackRate: 1 + } + clip: AnimationClipLoader { source: "cubeanimation.json" onDurationChanged: console.log("duration = " + duration) |