1// Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "evaluateclipanimatorjob_p.h"
5#include <Qt3DCore/private/qaspectjob_p.h>
6#include <Qt3DCore/private/qaspectmanager_p.h>
7#include <Qt3DAnimation/qclipanimator.h>
8#include <Qt3DAnimation/private/handler_p.h>
9#include <Qt3DAnimation/private/managers_p.h>
10#include <Qt3DAnimation/private/animationlogging_p.h>
11#include <Qt3DAnimation/private/animationutils_p.h>
12#include <Qt3DAnimation/private/job_common_p.h>
13
14QT_BEGIN_NAMESPACE
15
16namespace Qt3DAnimation {
17namespace Animation {
18
19
20EvaluateClipAnimatorJob::EvaluateClipAnimatorJob()
21 : AbstractEvaluateClipAnimatorJob()
22 , m_handler(nullptr)
23{
24 SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0)
25}
26
27void EvaluateClipAnimatorJob::run()
28{
29 Q_ASSERT(m_handler);
30
31 ClipAnimator *clipAnimator = m_handler->clipAnimatorManager()->data(handle: m_clipAnimatorHandle);
32 Q_ASSERT(clipAnimator);
33 const bool running = clipAnimator->isRunning();
34 const bool seeking = clipAnimator->isSeeking();
35 if (!running && !seeking) {
36 m_handler->setClipAnimatorRunning(handle: m_clipAnimatorHandle, running: false);
37 return;
38 }
39
40 const qint64 globalTimeNS = m_handler->simulationTime();
41
42 Clock *clock = m_handler->clockManager()->lookupResource(id: clipAnimator->clockId());
43
44 // Evaluate the fcurves
45 AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(id: clipAnimator->clipId());
46 Q_ASSERT(clip);
47
48 const qint64 nsSincePreviousFrame = seeking ? toNsecs(seconds: clip->duration() * clipAnimator->normalizedLocalTime())
49 : clipAnimator->nsSincePreviousFrame(currentGlobalTimeNS: globalTimeNS);
50
51 // Prepare for evaluation (convert global time to local time ....)
52 const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(animator: clipAnimator,
53 clock,
54 nsSincePreviousFrame);
55
56 const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorData: animatorEvaluationData);
57 const ClipResults rawClipResults = evaluateClipAtPhase(clip, phase: preEvaluationDataForClip.normalizedLocalTime);
58
59 // Reformat the clip results into the layout used by this animator/blend tree
60 const ClipFormat clipFormat = clipAnimator->clipFormat();
61 ClipResults formattedClipResults = formatClipResults(rawClipResults, format: clipFormat.sourceClipIndices);
62
63 if (preEvaluationDataForClip.isFinalFrame)
64 clipAnimator->setRunning(false);
65
66 clipAnimator->setCurrentLoop(preEvaluationDataForClip.currentLoop);
67 clipAnimator->setLastGlobalTimeNS(globalTimeNS);
68 clipAnimator->setLastLocalTime(preEvaluationDataForClip.localTime);
69 clipAnimator->setLastNormalizedLocalTime(preEvaluationDataForClip.normalizedLocalTime);
70
71 // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend)
72 auto record = prepareAnimationRecord(animatorId: clipAnimator->peerId(),
73 mappingDataVec: clipAnimator->mappingData(),
74 channelResults: formattedClipResults,
75 finalFrame: preEvaluationDataForClip.isFinalFrame,
76 normalizedLocalTime: preEvaluationDataForClip.normalizedLocalTime);
77
78 // Trigger callbacks either on this thread or by notifying the gui thread.
79 auto callbacks = prepareCallbacks(mappingDataVec: clipAnimator->mappingData(), channelResults: formattedClipResults);
80
81 // Update the normalized time on the backend node so that
82 // frontend <-> backend sync will not mark things dirty
83 // unless the frontend normalized time really is different
84 clipAnimator->setNormalizedLocalTime(normalizedLocalTime: record.normalizedTime, allowMarkDirty: false);
85
86 setPostFrameData(record, callbacks);
87}
88
89} // namespace Animation
90} // namespace Qt3DAnimation
91
92QT_END_NAMESPACE
93

source code of qt3d/src/animation/backend/evaluateclipanimatorjob.cpp