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 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | namespace Qt3DAnimation { |
17 | namespace Animation { |
18 | |
19 | |
20 | EvaluateClipAnimatorJob::EvaluateClipAnimatorJob() |
21 | : AbstractEvaluateClipAnimatorJob() |
22 | , m_handler(nullptr) |
23 | { |
24 | SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0) |
25 | } |
26 | |
27 | void 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 | |
92 | QT_END_NAMESPACE |
93 | |