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

source code of qtdeclarative/src/quick/util/qquickanimator.cpp