1/****************************************************************************
2**
3** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "clipanimator_p.h"
38#include <Qt3DAnimation/qclipanimator.h>
39#include <Qt3DAnimation/private/qclipanimator_p.h>
40#include <Qt3DAnimation/private/animationclip_p.h>
41#include <Qt3DAnimation/private/managers_p.h>
42#include <Qt3DAnimation/private/animationlogging_p.h>
43#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h>
44#include <Qt3DCore/qpropertyupdatedchange.h>
45#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
46
47QT_BEGIN_NAMESPACE
48
49namespace Qt3DAnimation {
50namespace Animation {
51
52ClipAnimator::ClipAnimator()
53 : BackendNode(ReadWrite)
54 , m_clipId()
55 , m_mapperId()
56 , m_clockId()
57 , m_running(false)
58 , m_loops(1)
59 , m_lastGlobalTimeNS(0)
60 , m_lastLocalTime(0.0)
61 , m_mappingData()
62 , m_currentLoop(0)
63 , m_normalizedLocalTime(-1.0f)
64 , m_lastNormalizedLocalTime(-1.0f)
65{
66}
67
68void ClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
69{
70 const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QClipAnimatorData>>(change);
71 const auto &data = typedChange->data;
72 m_clipId = data.clipId;
73 m_mapperId = data.mapperId;
74 m_clockId = data.clockId;
75 m_running = data.running;
76 m_loops = data.loops;
77 m_normalizedLocalTime = data.normalizedTime;
78 setDirty(Handler::ClipAnimatorDirty);
79}
80
81void ClipAnimator::setClipId(Qt3DCore::QNodeId clipId)
82{
83 m_clipId = clipId;
84 setDirty(Handler::ClipAnimatorDirty);
85
86 // register at the clip to make sure we are marked dirty when the clip finished loading
87 AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipId);
88 if (clip)
89 clip->addDependingClipAnimator(peerId());
90}
91
92void ClipAnimator::setMapperId(Qt3DCore::QNodeId mapperId)
93{
94 m_mapperId = mapperId;
95 setDirty(Handler::ClipAnimatorDirty);
96}
97
98void ClipAnimator::setClockId(Qt3DCore::QNodeId clockId)
99{
100 m_clockId = clockId;
101 setDirty(Handler::ClipAnimatorDirty);
102}
103
104void ClipAnimator::setRunning(bool running)
105{
106 m_running = running;
107 if (!running)
108 m_currentLoop = 0;
109 setDirty(Handler::ClipAnimatorDirty);
110}
111
112void ClipAnimator::setNormalizedLocalTime(float normalizedTime)
113{
114 m_normalizedLocalTime = normalizedTime;
115 if (isValidNormalizedTime(normalizedTime))
116 setDirty(Handler::ClipAnimatorDirty);
117}
118
119void ClipAnimator::cleanup()
120{
121 setEnabled(false);
122 m_handler = nullptr;
123 m_clipId = Qt3DCore::QNodeId();
124 m_mapperId = Qt3DCore::QNodeId();
125 m_clockId = Qt3DCore::QNodeId();
126 m_running = false;
127 m_loops = 1;
128 m_clipFormat = ClipFormat();
129 m_normalizedLocalTime = m_lastNormalizedLocalTime = -1.0f;
130}
131
132void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
133{
134 switch (e->type()) {
135 case Qt3DCore::PropertyUpdated: {
136 const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
137 if (change->propertyName() == QByteArrayLiteral("clip"))
138 setClipId(change->value().value<Qt3DCore::QNodeId>());
139 else if (change->propertyName() == QByteArrayLiteral("channelMapper"))
140 setMapperId(change->value().value<Qt3DCore::QNodeId>());
141 else if (change->propertyName() == QByteArrayLiteral("clock"))
142 setClockId(change->value().value<Qt3DCore::QNodeId>());
143 else if (change->propertyName() == QByteArrayLiteral("running"))
144 setRunning(change->value().toBool());
145 else if (change->propertyName() == QByteArrayLiteral("loops"))
146 m_loops = change->value().toInt();
147 else if (change->propertyName() == QByteArrayLiteral("normalizedTime"))
148 setNormalizedLocalTime(change->value().toFloat());
149 break;
150 }
151
152 default:
153 break;
154 }
155 QBackendNode::sceneChangeEvent(e);
156}
157
158void ClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes)
159{
160 for (const Qt3DCore::QSceneChangePtr &change : changes)
161 notifyObservers(change);
162}
163
164void ClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks)
165{
166 for (const AnimationCallbackAndValue &callback : callbacks) {
167 if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) {
168 callback.callback->valueChanged(callback.value);
169 } else {
170 auto e = QAnimationCallbackTriggerPtr::create(peerId());
171 e->setCallback(callback.callback);
172 e->setValue(callback.value);
173 e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
174 notifyObservers(e);
175 }
176 }
177}
178
179qint64 ClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS)
180{
181 return currentGlobalTimeNS - m_lastGlobalTimeNS;
182}
183
184void ClipAnimator::setLastGlobalTimeNS(qint64 lastGlobalTimeNS)
185{
186 m_lastGlobalTimeNS = lastGlobalTimeNS;
187}
188
189double ClipAnimator::lastLocalTime() const
190{
191 return m_lastLocalTime;
192}
193
194void ClipAnimator::setLastLocalTime(double lastLocalTime)
195{
196 m_lastLocalTime = lastLocalTime;
197}
198
199void ClipAnimator::setLastNormalizedLocalTime(float normalizedTime)
200{
201 m_lastNormalizedLocalTime = normalizedTime;
202}
203
204} // namespace Animation
205} // namespace Qt3DAnimation
206
207QT_END_NAMESPACE
208