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