1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick 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 "qquickanimator_p_p.h"
41 #include "qquickanimatorjob_p.h"
42 
43 #include <private/qquickitem_p.h>
44 
45 QT_BEGIN_NAMESPACE
46 
47 /*!
48     \qmltype Animator
49     \instantiates QQuickAnimator
50     \inqmlmodule QtQuick
51     \since 5.2
52     \ingroup qtquick-transitions-animations
53     \inherits Animation
54     \brief Is the base of all QML animators.
55 
56     Animator types are a special type of animation which operate
57     directly on Qt Quick's scene graph, rather than the QML objects and their
58     properties like regular Animation types do. This has the benefit that
59     Animator based animations can animate on the \l
60     {Threaded Render Loop ("threaded")}{scene graph's rendering thread} even when the
61     UI thread is blocked.
62 
63     The value of the QML property will be updated after the animation has
64     finished. The property is not updated while the animation is running.
65 
66     The Animator types can be used just like any other Animation type.
67 
68     \snippet qml/animators.qml mixed
69 
70     If all sub-animations of ParallelAnimation and SequentialAnimation
71     are Animator types, the ParallelAnimation and SequentialAnimation will
72     also be treated as an Animator and be run on the scene graph's rendering
73     thread when possible.
74 
75     The Animator types can be used for animations during transitions, but
76     they do not support the \l {Transition::reversible}{reversible}
77     property.
78 
79     The Animator type cannot be used directly in a QML file. It exists
80     to provide a set of common properties and methods, available across all the
81     other animator types that inherit from it. Attempting to use the Animator
82     type directly will result in an error.
83  */
84 
QQuickAnimator(QQuickAnimatorPrivate & dd,QObject * parent)85 QQuickAnimator::QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent)
86     : QQuickAbstractAnimation(dd, parent)
87 {
88 }
89 
QQuickAnimator(QObject * parent)90 QQuickAnimator::QQuickAnimator(QObject *parent)
91     : QQuickAbstractAnimation(*new QQuickAnimatorPrivate, parent)
92 {
93 }
94 
95 /*!
96    \qmlproperty QtQuick::Item QtQuick::Animator::target
97 
98    This property holds the target item of the animator.
99 
100    \note Animator targets must be Item based types.
101  */
102 
setTargetItem(QQuickItem * target)103 void QQuickAnimator::setTargetItem(QQuickItem *target)
104 {
105     Q_D(QQuickAnimator);
106     if (target == d->target)
107         return;
108     d->target = target;
109     Q_EMIT targetItemChanged(d->target);
110 }
111 
targetItem() const112 QQuickItem *QQuickAnimator::targetItem() const
113 {
114     Q_D(const QQuickAnimator);
115     return d->target;
116 }
117 
118 /*!
119     \qmlproperty int QtQuick::Animator::duration
120     This property holds the duration of the animation in milliseconds.
121 
122     The default value is 250.
123 */
setDuration(int duration)124 void QQuickAnimator::setDuration(int duration)
125 {
126     Q_D(QQuickAnimator);
127     if (duration == d->duration)
128         return;
129     d->duration = duration;
130     Q_EMIT durationChanged(duration);
131 }
132 
duration() const133 int QQuickAnimator::duration() const
134 {
135     Q_D(const QQuickAnimator);
136     return d->duration;
137 }
138 
139 /*!
140     \qmlpropertygroup QtQuick::Animator::easing
141     \qmlproperty enumeration QtQuick::Animator::easing.type
142     \qmlproperty real QtQuick::Animator::easing.amplitude
143     \qmlproperty real QtQuick::Animator::easing.overshoot
144     \qmlproperty real QtQuick::Animator::easing.period
145     \qmlproperty list<real> QtQuick::Animator::easing.bezierCurve
146     \include qquickanimation.cpp propertyanimation.easing
147 */
148 
setEasing(const QEasingCurve & easing)149 void QQuickAnimator::setEasing(const QEasingCurve &easing)
150 {
151     Q_D(QQuickAnimator);
152     if (easing == d->easing)
153         return;
154     d->easing = easing;
155     Q_EMIT easingChanged(d->easing);
156 }
157 
easing() const158 QEasingCurve QQuickAnimator::easing() const
159 {
160     Q_D(const QQuickAnimator);
161     return d->easing;
162 }
163 
164 /*!
165     \qmlproperty real QtQuick::Animator::to
166     This property holds the end value for the animation.
167 
168     If the Animator is defined within a \l Transition or \l Behavior,
169     this value defaults to the value defined in the end state of the
170     \l Transition, or the value of the property change that triggered the
171     \l Behavior.
172  */
173 
setTo(qreal to)174 void QQuickAnimator::setTo(qreal to)
175 {
176     Q_D(QQuickAnimator);
177     if (to == d->to)
178         return;
179     d->isToDefined = true;
180     d->to = to;
181     Q_EMIT toChanged(d->to);
182 }
183 
to() const184 qreal QQuickAnimator::to() const
185 {
186     Q_D(const QQuickAnimator);
187     return d->to;
188 }
189 
190 /*!
191     \qmlproperty real QtQuick::Animator::from
192     This property holds the starting value for the animation.
193 
194     If the Animator is defined within a \l Transition or \l Behavior,
195     this value defaults to the value defined in the starting state of the
196     \l Transition, or the current value of the property at the moment the
197     \l Behavior is triggered.
198 
199     \sa {Animation and Transitions in Qt Quick}
200 */
201 
setFrom(qreal from)202 void QQuickAnimator::setFrom(qreal from)
203 {
204     Q_D(QQuickAnimator);
205     if (from == d->from)
206         return;
207     d->isFromDefined = true;
208     d->from = from;
209     Q_EMIT fromChanged(d->from);
210 }
211 
from() const212 qreal QQuickAnimator::from() const
213 {
214     Q_D(const QQuickAnimator);
215     return d->from;
216 }
217 
apply(QQuickAnimatorJob * job,const QString & propertyName,QQuickStateActions & actions,QQmlProperties & modified,QObject * defaultTarget)218 void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
219                                      const QString &propertyName,
220                                      QQuickStateActions &actions,
221                                      QQmlProperties &modified,
222                                      QObject *defaultTarget)
223 {
224 
225     if (actions.size()) {
226         for (int i=0; i<actions.size(); ++i) {
227             QQuickStateAction &action = actions[i];
228             if (action.property.name() != propertyName)
229                 continue;
230             modified << action.property;
231 
232             job->setTarget(qobject_cast<QQuickItem *>(action.property.object()));
233 
234             if (isFromDefined)
235                 job->setFrom(from);
236             else if (action.fromValue.isValid())
237                 job->setFrom(action.fromValue.toReal());
238             else
239                 job->setFrom(action.property.read().toReal());
240 
241             if (isToDefined)
242                 job->setTo(to);
243             else if (action.toValue.isValid())
244                 job->setTo(action.toValue.toReal());
245             else
246                 job->setTo(action.property.read().toReal());
247 
248             // This magic line is in sync with what PropertyAnimation does
249             // and prevents the animation to end up in the "completeList"
250             // which forces action.toValue to be written directly to
251             // the item when a transition is cancelled.
252             action.fromValue = action.toValue;
253        }
254     }
255 
256     if (modified.isEmpty()) {
257         job->setTarget(target);
258         job->setFrom(from);
259         job->setTo(to);
260     }
261 
262     if (!job->target()) {
263         if (defaultProperty.object())
264             job->setTarget(qobject_cast<QQuickItem *>(defaultProperty.object()));
265         else
266             job->setTarget(qobject_cast<QQuickItem *>(defaultTarget));
267     }
268 
269     job->setDuration(duration);
270     job->setLoopCount(loopCount);
271     job->setEasingCurve(easing);
272 }
273 
transition(QQuickStateActions & actions,QQmlProperties & modified,TransitionDirection direction,QObject * defaultTarget)274 QAbstractAnimationJob *QQuickAnimator::transition(QQuickStateActions &actions,
275                                                   QQmlProperties &modified,
276                                                   TransitionDirection direction,
277                                                   QObject *defaultTarget)
278 {
279     Q_D(QQuickAnimator);
280 
281     if (d->defaultProperty.isValid() && propertyName() != d->defaultProperty.name()) {
282         qDebug() << Q_FUNC_INFO << "property name conflict...";
283         return nullptr;
284     }
285 
286     // The animation system cannot handle backwards uncontrolled animations.
287     if (direction == Backward)
288         return nullptr;
289 
290     QQuickAnimatorJob *job = createJob();
291     if (!job)
292         return nullptr;
293 
294     d->apply(job, propertyName(), actions, modified, defaultTarget);
295 
296     if (!job->target()) {
297         delete job;
298         return nullptr;
299     }
300 
301     return job;
302 }
303 
304 /*!
305     \qmltype XAnimator
306     \instantiates QQuickXAnimator
307     \inqmlmodule QtQuick
308     \since 5.2
309     \ingroup qtquick-transitions-animations
310     \inherits Animator
311     \brief The XAnimator type animates the x position of an Item.
312 
313     \l{Animator} types are different from normal Animation types. When
314     using an Animator, the animation can be run in the render thread
315     and the property value will jump to the end when the animation is
316     complete.
317 
318     The value of Item::x is updated after the animation has finished.
319 
320     The following snippet shows how to use a XAnimator together
321     with a Rectangle item.
322 
323     \snippet qml/animators.qml x target
324 
325     It is also possible to use the \c on keyword to tie the
326     XAnimator directly to an Item instance.
327 
328     \snippet qml/animators.qml x on
329 
330 
331  */
332 
QQuickXAnimator(QObject * parent)333 QQuickXAnimator::QQuickXAnimator(QObject *parent) : QQuickAnimator(parent) {}
334 
createJob() const335 QQuickAnimatorJob *QQuickXAnimator::createJob() const { return new QQuickXAnimatorJob(); }
336 
337 /*!
338     \qmltype YAnimator
339     \instantiates QQuickYAnimator
340     \inqmlmodule QtQuick
341     \since 5.2
342     \ingroup qtquick-transitions-animations
343     \inherits Animator
344     \brief The YAnimator type animates the y position of an Item.
345 
346     \l{Animator} types are different from normal Animation types. When
347     using an Animator, the animation can be run in the render thread
348     and the property value will jump to the end when the animation is
349     complete.
350 
351     The value of Item::y is updated after the animation has finished.
352 
353     The following snippet shows how to use a YAnimator together
354     with a Rectangle item.
355 
356     \snippet qml/animators.qml y target
357 
358     It is also possible to use the \c on keyword to tie the
359     YAnimator directly to an Item instance.
360 
361     \snippet qml/animators.qml y on
362 
363 
364  */
365 
QQuickYAnimator(QObject * parent)366 QQuickYAnimator::QQuickYAnimator(QObject *parent) : QQuickAnimator(parent) {}
367 
createJob() const368 QQuickAnimatorJob *QQuickYAnimator::createJob() const { return new QQuickYAnimatorJob(); }
369 
370 /*!
371     \qmltype ScaleAnimator
372     \instantiates QQuickScaleAnimator
373     \inqmlmodule QtQuick
374     \since 5.2
375     \ingroup qtquick-transitions-animations
376     \inherits Animator
377     \brief The ScaleAnimator type animates the scale factor of an Item.
378 
379     \l{Animator} types are different from normal Animation types. When
380     using an Animator, the animation can be run in the render thread
381     and the property value will jump to the end when the animation is
382     complete.
383 
384     The value of Item::scale is updated after the animation has finished.
385 
386     The following snippet shows how to use a ScaleAnimator together
387     with a Rectangle item.
388 
389     \snippet qml/animators.qml scale target
390 
391     It is also possible to use the \c on keyword to tie the
392     ScaleAnimator directly to an Item instance.
393 
394     \snippet qml/animators.qml scale on
395 
396     \sa Item::transformOrigin, RotationAnimator
397  */
398 
QQuickScaleAnimator(QObject * parent)399 QQuickScaleAnimator::QQuickScaleAnimator(QObject *parent) : QQuickAnimator(parent) {}
400 
createJob() const401 QQuickAnimatorJob *QQuickScaleAnimator::createJob() const { return new QQuickScaleAnimatorJob(); }
402 
403 /*!
404     \qmltype OpacityAnimator
405     \instantiates QQuickOpacityAnimator
406     \inqmlmodule QtQuick
407     \since 5.2
408     \ingroup qtquick-transitions-animations
409     \inherits Animator
410     \brief The OpacityAnimator type animates the opacity of an Item.
411 
412     \l{Animator} types are different from normal Animation types. When
413     using an Animator, the animation can be run in the render thread
414     and the property value will jump to the end when the animation is
415     complete.
416 
417     The value of Item::opacity is updated after the animation has finished.
418 
419     The following snippet shows how to use a OpacityAnimator together
420     with a Rectangle item.
421 
422     \snippet qml/animators.qml opacity target
423 
424     It is also possible to use the \c on keyword to tie the
425     OpacityAnimator directly to an Item instance.
426 
427     \snippet qml/animators.qml opacity on
428 
429  */
430 
QQuickOpacityAnimator(QObject * parent)431 QQuickOpacityAnimator::QQuickOpacityAnimator(QObject *parent) : QQuickAnimator(parent) {}
432 
createJob() const433 QQuickAnimatorJob *QQuickOpacityAnimator::createJob() const { return new QQuickOpacityAnimatorJob(); }
434 
435 /*!
436     \qmltype RotationAnimator
437     \instantiates QQuickRotationAnimator
438     \inqmlmodule QtQuick
439     \since 5.2
440     \ingroup qtquick-transitions-animations
441     \inherits Animator
442     \brief The RotationAnimator type animates the rotation of an Item.
443 
444     \l{Animator} types are different from normal Animation types. When
445     using an Animator, the animation can be run in the render thread
446     and the property value will jump to the end when the animation is
447     complete.
448 
449     The value of Item::rotation is updated after the animation has finished.
450 
451     The following snippet shows how to use a RotationAnimator together
452     with a Rectangle item.
453 
454     \snippet qml/animators.qml rotation target
455 
456     It is also possible to use the \c on keyword to tie the
457     RotationAnimator directly to the \c rotation property of an Item
458     instance.
459 
460     \snippet qml/animators.qml rotation on
461 
462     \sa Item::transformOrigin, ScaleAnimator
463  */
464 
QQuickRotationAnimator(QObject * parent)465 QQuickRotationAnimator::QQuickRotationAnimator(QObject *parent)
466     : QQuickAnimator(*new QQuickRotationAnimatorPrivate, parent)
467 {
468 }
469 
createJob() const470 QQuickAnimatorJob *QQuickRotationAnimator::createJob() const {
471     Q_D(const QQuickRotationAnimator);
472     QQuickRotationAnimatorJob *job = new QQuickRotationAnimatorJob();
473     job->setDirection(d->direction);
474     return job;
475 }
476 
477 /*!
478     \qmlproperty enumeration QtQuick::RotationAnimator::direction
479     This property holds the direction of the rotation.
480 
481     Possible values are:
482 
483     \list
484     \li RotationAnimator.Numerical (default) - Rotate by linearly interpolating between the two numbers.
485            A rotation from 10 to 350 will rotate 340 degrees clockwise.
486     \li RotationAnimator.Clockwise - Rotate clockwise between the two values
487     \li RotationAnimator.Counterclockwise - Rotate counterclockwise between the two values
488     \li RotationAnimator.Shortest - Rotate in the direction that produces the shortest animation path.
489            A rotation from 10 to 350 will rotate 20 degrees counterclockwise.
490     \endlist
491 */
setDirection(RotationDirection dir)492 void QQuickRotationAnimator::setDirection(RotationDirection dir)
493 {
494     Q_D(QQuickRotationAnimator);
495     if (d->direction == dir)
496         return;
497     d->direction = dir;
498     Q_EMIT directionChanged(d->direction);
499 }
500 
direction() const501 QQuickRotationAnimator::RotationDirection QQuickRotationAnimator::direction() const
502 {
503     Q_D(const QQuickRotationAnimator);
504     return d->direction;
505 }
506 
507 #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl)
508 /*!
509     \qmltype UniformAnimator
510     \instantiates QQuickUniformAnimator
511     \inqmlmodule QtQuick
512     \since 5.2
513     \ingroup qtquick-transitions-animations
514     \inherits Animator
515     \brief The UniformAnimator type animates a uniform of a ShaderEffect.
516 
517     \l{Animator} types are different from normal Animation types. When
518     using an Animator, the animation can be run in the render thread
519     and the property value will jump to the end when the animation is
520     complete.
521 
522     The value of the QML property defining the uniform is updated after
523     the animation has finished.
524 
525     The following snippet shows how to use a UniformAnimator together
526     with a ShaderEffect item.
527 
528     \snippet qml/animators.qml shader target
529 
530     It is also possible to use the \c on keyword to tie the
531     UniformAnimator directly to a uniform of a ShaderEffect
532     instance.
533 
534     \snippet qml/animators.qml shader on
535 
536     \sa ShaderEffect, ShaderEffectSource
537  */
538 
QQuickUniformAnimator(QObject * parent)539 QQuickUniformAnimator::QQuickUniformAnimator(QObject *parent)
540     : QQuickAnimator(*new QQuickUniformAnimatorPrivate, parent)
541 {
542 }
543 
544 /*!
545    \qmlproperty string QtQuick::UniformAnimator::uniform
546    This property holds the name of the uniform to animate.
547 
548    The value of the uniform must correspond to both a property
549    on the target ShaderEffect and must be a uniform of type
550    \c float in the fragment or vertex shader.
551  */
setUniform(const QString & uniform)552 void QQuickUniformAnimator::setUniform(const QString &uniform)
553 {
554     Q_D(QQuickUniformAnimator);
555     if (d->uniform == uniform)
556         return;
557     d->uniform = uniform;
558     Q_EMIT uniformChanged(d->uniform);
559 }
560 
uniform() const561 QString QQuickUniformAnimator::uniform() const
562 {
563     Q_D(const QQuickUniformAnimator);
564     return d->uniform;
565 }
566 
propertyName() const567 QString QQuickUniformAnimator::propertyName() const
568 {
569     Q_D(const QQuickUniformAnimator);
570     if (!d->uniform.isEmpty())
571         return d->uniform;
572     return d->defaultProperty.name();
573 }
574 
createJob() const575 QQuickAnimatorJob *QQuickUniformAnimator::createJob() const
576 {
577     QString u = propertyName();
578     if (u.isEmpty())
579         return nullptr;
580 
581     QQuickUniformAnimatorJob *job = new QQuickUniformAnimatorJob();
582     job->setUniform(u.toLatin1());
583     return job;
584 }
585 #endif
586 
587 QT_END_NAMESPACE
588 
589 #include "moc_qquickanimator_p.cpp"
590