1/****************************************************************************
2**
3** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qabstractclipanimator.h"
41#include "qabstractclipanimator_p.h"
42#include <Qt3DAnimation/qchannelmapper.h>
43#include <Qt3DAnimation/qclock.h>
44#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h>
45
46QT_BEGIN_NAMESPACE
47
48namespace Qt3DAnimation {
49
50QAbstractClipAnimatorPrivate::QAbstractClipAnimatorPrivate()
51 : Qt3DCore::QComponentPrivate()
52 , m_mapper(nullptr)
53 , m_clock(nullptr)
54 , m_running(false)
55 , m_loops(1)
56 , m_normalizedTime(0.0f)
57{
58}
59
60bool QAbstractClipAnimatorPrivate::canPlay() const
61{
62 return true;
63}
64
65/*!
66 \qmltype AbstractClipAnimator
67 \instantiates Qt3DAnimation::QAbstractClipAnimator
68 \inqmlmodule Qt3D.Animation
69 \since 5.9
70
71 \brief AbstractClipAnimator is the base class for types providing animation playback
72 capabilities.
73
74 Subclasses of AbstractClipAnimator can be aggregated by an Entity to
75 provide animation capabilities. The animator components provide an
76 interface for controlling the animation (e.g. start, stop). Each animator
77 type requires some form of animation data such as an AbstractAnimationClip
78 as well as a ChannelMapper which describes how the channels in the
79 animation clip should be mapped onto the properties of the objects you wish
80 to animate.
81
82 The following subclasses are available:
83
84 \list
85 \li Qt3D.Animation.ClipAnimator
86 \li Qt3D.Animation.BlendedClipAnimator
87 \endlist
88*/
89
90/*!
91 \class Qt3DAnimation::QAbstractClipAnimator
92 \inherits Qt3DCore::QComponent
93
94 \inmodule Qt3DAnimation
95 \since 5.9
96
97 \brief QAbstractClipAnimator is the base class for types providing animation playback
98 capabilities.
99
100 Subclasses of QAbstractClipAnimator can be aggregated by a QEntity to
101 provide animation capabilities. The animator components provide an
102 interface for controlling the animation (e.g. start, stop). Each animator
103 type requires some form of animation data such as a QAbstractAnimationClip
104 as well as a QChannelMapper which describes how the channels in the
105 animation clip should be mapped onto the properties of the objects you wish
106 to animate.
107
108 The following subclasses are available:
109
110 \list
111 \li Qt3DAnimation::QClipAnimator
112 \li Qt3DAnimation::QBlendedClipAnimator
113 \endlist
114*/
115
116QAbstractClipAnimator::QAbstractClipAnimator(Qt3DCore::QNode *parent)
117 : Qt3DCore::QComponent(*new QAbstractClipAnimatorPrivate, parent)
118{
119}
120
121QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent)
122 : Qt3DCore::QComponent(dd, parent)
123{
124}
125
126/*! \internal */
127void QAbstractClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
128{
129 if (change->type() == Qt3DCore::CallbackTriggered) {
130 QAnimationCallbackTriggerPtr callbackTrigger = qSharedPointerCast<Qt3DAnimation::QAnimationCallbackTrigger>(change);
131 if (callbackTrigger->callback())
132 callbackTrigger->callback()->valueChanged(callbackTrigger->value());
133 } else {
134 QComponent::sceneChangeEvent(change);
135 }
136}
137
138QAbstractClipAnimator::~QAbstractClipAnimator()
139{
140}
141
142/*!
143 \property Qt3DAnimation::QAbstractClipAnimator::running
144
145 This property holds a boolean indicating whether the animation is currently running.
146*/
147
148/*!
149 Returns a boolean indicating whether the animation is currently running.
150*/
151bool QAbstractClipAnimator::isRunning() const
152{
153 Q_D(const QAbstractClipAnimator);
154 return d->m_running;
155}
156
157/*!
158 \property Qt3DAnimation::QAbstractClipAnimator::channelMapper
159
160 This property holds the ChannelMapper that controls how the channels in
161 the animation clip map onto the properties of the target objects.
162*/
163
164QChannelMapper *QAbstractClipAnimator::channelMapper() const
165{
166 Q_D(const QAbstractClipAnimator);
167 return d->m_mapper;
168}
169
170/*!
171 \qmlproperty int Qt3DAnimation::AbstractClipAnimator::loops
172
173 This property holds the number of times the animation should play.
174
175 By default, loops is 1: the animation will play through once and then stop.
176
177 If set to QAbstractClipAnimator::Infinite, the animation will continuously
178 repeat until it is explicitly stopped.
179*/
180/*!
181 \enum QAbstractClipAnimator::Loops
182
183 Holds the number of times the animation should play.
184
185 \value Infinite
186 This will repeat the loop continuously until it is explicitly
187 stopped.
188
189*/
190/*!
191 \property Qt3DAnimation::QAbstractClipAnimator::loops
192
193 Holds the number of times the animation should play.
194
195 The value is 1 by default: the animation will be played once and then stop.
196
197 If set to QAbstractClipAnimator::Infinite, the animation will continuously
198 repeat until it is explicitly stopped.
199*/
200
201/*!
202 Returns the number of times the animation should play.
203
204 The value is 1 by default: the animation will play through once and then stop.
205
206 If set to QAbstractClipAnimator::Infinite, the animation will continuously
207 repeat until it is explicitly stopped.
208*/
209int QAbstractClipAnimator::loopCount() const
210{
211 Q_D(const QAbstractClipAnimator);
212 return d->m_loops;
213}
214/*!
215 \property Qt3DAnimation::QAbstractClipAnimator::clock
216
217 The clock controls the speed with which an animation is played.
218*/
219QClock *QAbstractClipAnimator::clock() const
220{
221 Q_D(const QAbstractClipAnimator);
222 return d->m_clock;
223}
224
225/*!
226 \property Qt3DAnimation::QAbstractClipAnimator::normalizedTime
227
228 This property holds the clips normalized time.
229*/
230float QAbstractClipAnimator::normalizedTime() const
231{
232 Q_D(const QAbstractClipAnimator);
233 return d->m_normalizedTime;
234}
235
236void QAbstractClipAnimator::setRunning(bool running)
237{
238 Q_D(QAbstractClipAnimator);
239 if (d->m_running == running)
240 return;
241
242 if (running && !d->canPlay())
243 return;
244
245 d->m_running = running;
246 emit runningChanged(running);
247}
248
249void QAbstractClipAnimator::setChannelMapper(QChannelMapper *mapping)
250{
251 Q_D(QAbstractClipAnimator);
252 if (d->m_mapper == mapping)
253 return;
254
255 if (d->m_mapper)
256 d->unregisterDestructionHelper(d->m_mapper);
257
258 if (mapping && !mapping->parent())
259 mapping->setParent(this);
260 d->m_mapper = mapping;
261
262 // Ensures proper bookkeeping
263 if (d->m_mapper)
264 d->registerDestructionHelper(d->m_mapper, &QAbstractClipAnimator::setChannelMapper, d->m_mapper);
265 emit channelMapperChanged(mapping);
266}
267
268void QAbstractClipAnimator::setLoopCount(int loops)
269{
270 Q_D(QAbstractClipAnimator);
271 if (d->m_loops == loops)
272 return;
273
274 d->m_loops = loops;
275 emit loopCountChanged(loops);
276}
277
278void QAbstractClipAnimator::setClock(QClock *clock)
279{
280 Q_D(QAbstractClipAnimator);
281 if (d->m_clock == clock)
282 return;
283
284 if (d->m_clock)
285 d->unregisterDestructionHelper(d->m_clock);
286
287 if (clock && !clock->parent())
288 clock->setParent(this);
289 d->m_clock = clock;
290
291 if (d->m_clock)
292 d->registerDestructionHelper(d->m_clock, &QAbstractClipAnimator::setClock, d->m_clock);
293 emit clockChanged(clock);
294}
295
296void QAbstractClipAnimator::setNormalizedTime(float timeFraction)
297{
298 Q_D(QAbstractClipAnimator);
299 const bool validTime = !(timeFraction < 0.0f) && !(timeFraction > 1.0f);
300 if (!validTime) {
301 qWarning("Time value %f is not valid, needs to be in the range 0.0 to 1.0", timeFraction);
302 return;
303 }
304
305 if (qFuzzyCompare(d->m_normalizedTime, timeFraction))
306 return;
307
308 d->m_normalizedTime = timeFraction;
309 emit normalizedTimeChanged(timeFraction);
310}
311
312/*!
313 Starts the animation.
314*/
315void QAbstractClipAnimator::start()
316{
317 setRunning(true);
318}
319
320/*!
321 Stops the animation.
322*/
323void QAbstractClipAnimator::stop()
324{
325 setRunning(false);
326}
327
328} // namespace Qt3DAnimation
329
330QT_END_NAMESPACE
331