1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquicktimelineanimation_p.h"
5
6#include "qquicktimeline_p.h"
7
8#include <private/qobject_p.h>
9#include <private/qquickanimation_p_p.h>
10
11#include <QTimer>
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \qmltype TimelineAnimation
17 \inherits NumberAnimation
18 \instantiates QQuickTimelineAnimation
19 \inqmlmodule QtQuick.Timeline
20 \ingroup qtqmltypes
21
22 \brief A number animation attached to a timeline.
23
24 Specifies how the current frame property of a timeline is animated. This
25 animates the properties of the objects targeted by the timeline.
26*/
27
28/*!
29 \qmlproperty bool TimelineAnimation::pingPong
30
31 Whether the animation is played backwards after it finishes. This is an easy
32 way to create circular animations.
33*/
34
35/*!
36 \qmlsignal TimelineAnimation::finished
37
38 This signal is emitted when the timeline animation finishes.
39*/
40
41QQuickTimelineAnimation::QQuickTimelineAnimation(QObject *parent) : QQuickNumberAnimation(parent)
42{
43 setProperty(QLatin1String("currentFrame"));
44 connect(sender: this, signal: &QQuickAbstractAnimation::started, context: this, slot: &QQuickTimelineAnimation::handleStarted);
45 connect(sender: this, signal: &QQuickAbstractAnimation::stopped, context: this, slot: &QQuickTimelineAnimation::handleStopped);
46}
47
48void QQuickTimelineAnimation::setPingPong(bool b)
49{
50 if (b == m_pinpong)
51 return;
52
53 m_pinpong = b;
54 emit pingPongChanged();
55}
56
57bool QQuickTimelineAnimation::pingPong() const
58{
59 return m_pinpong;
60}
61
62void QQuickTimelineAnimation::handleStarted()
63{
64 auto timeline = qobject_cast<QQuickTimeline*>(object: parent());
65
66 if (!timeline)
67 return;
68
69 for (QQuickTimelineAnimation *other : timeline->getAnimations()) {
70 if (other != this)
71 other->stop();
72 }
73
74 auto *privateObject = static_cast<QQuickPropertyAnimationPrivate*>(QObjectPrivate::get(o: this));
75
76 if (m_pinpong && m_originalStart) {
77 m_originalLoop = privateObject->loopCount;
78 m_currentLoop = 0;
79 privateObject->loopCount = 1;
80 privateObject->animationInstance->setLoopCount(1);
81 m_originalStart = false;
82 m_reversed = false;
83 }
84}
85
86static void swapStartEnd(QQuickPropertyAnimationPrivate *privateObject)
87{
88 std::swap(a&: privateObject->to, b&: privateObject->from);
89}
90
91void QQuickTimelineAnimation::handleStopped()
92{
93 if (!m_pinpong) {
94 emit finished();
95 return;
96 }
97
98 auto *privateObject = static_cast<QQuickPropertyAnimationPrivate*>(QObjectPrivate::get(o: this));
99
100 if (m_reversed)
101 m_currentLoop++;
102
103 if (!(privateObject->animationInstance->currentTime() < privateObject->duration)
104 && (m_currentLoop < m_originalLoop
105 || m_originalLoop == -1)) {
106 swapStartEnd(privateObject);
107
108 m_reversed = !m_reversed;
109 QQuickTimelineAnimation::start();
110
111 } else {
112 if (m_reversed)
113 swapStartEnd(privateObject);
114
115 m_originalStart = true;
116 m_reversed = false;
117 privateObject->loopCount = m_originalLoop;
118 emit finished();
119 }
120}
121
122QT_END_NAMESPACE
123

source code of qtquicktimeline/src/timeline/qquicktimelineanimation.cpp