4#include "private/qsequentialanimationgroupjob_p.h"
5#include "private/qpauseanimationjob_p.h"
6#include "private/qanimationjobutil_p.h"
10QSequentialAnimationGroupJob::QSequentialAnimationGroupJob()
11 : QAnimationGroupJob()
12 , m_currentAnimation(
nullptr)
17QSequentialAnimationGroupJob::~QSequentialAnimationGroupJob()
21bool QSequentialAnimationGroupJob::atEnd()
const
30 const int animTotalCurrentTime = m_currentAnimation->currentTime();
31 return (m_currentLoop == m_loopCount - 1
32 && m_direction == Forward
33 && !m_children.next(m_currentAnimation)
34 && animTotalCurrentTime == animationActualTotalDuration(m_currentAnimation));
37int QSequentialAnimationGroupJob::animationActualTotalDuration(
38 const QAbstractAnimationJob *anim)
const
40 int ret = anim->totalDuration();
42 int done = uncontrolledAnimationFinishTime(anim);
44 if (done >= 0 && (anim->loopCount() - 1 == anim->currentLoop() || anim->state() == Stopped))
50QSequentialAnimationGroupJob::AnimationIndex QSequentialAnimationGroupJob::indexForCurrentTime()
const
52 Q_ASSERT(!m_children.isEmpty());
57 for (
const QAbstractAnimationJob *anim : m_children) {
58 duration = animationActualTotalDuration(anim);
65 if (duration == -1 || m_currentTime < (ret.timeOffset + duration)
66 || (m_currentTime == (ret.timeOffset + duration) && m_direction == QAbstractAnimationJob::Backward)) {
71 if (anim == m_currentAnimation) {
72 ret.afterCurrent =
true;
76 ret.timeOffset += duration;
82 ret.timeOffset -= duration;
83 ret.animation = m_children.last();
87void QSequentialAnimationGroupJob::restart()
90 if (m_direction == Forward) {
92 if (m_currentAnimation == m_children.first())
93 activateCurrentAnimation();
95 setCurrentAnimation(m_children.first());
98 m_previousLoop = m_loopCount - 1;
99 if (m_currentAnimation == m_children.last())
100 activateCurrentAnimation();
102 setCurrentAnimation(m_children.last());
106void QSequentialAnimationGroupJob::advanceForwards(
const AnimationIndex &newAnimationIndex)
108 if (m_previousLoop < m_currentLoop) {
110 for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = m_children.next(anim)) {
111 RETURN_IF_DELETED(setCurrentAnimation(anim,
true));
112 RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim)));
115 if (m_children.count() == 1) {
117 RETURN_IF_DELETED(activateCurrentAnimation());
119 RETURN_IF_DELETED(setCurrentAnimation(m_children.first(),
true));
124 for (QAbstractAnimationJob *anim = m_currentAnimation;
125 anim && anim != newAnimationIndex.animation; anim = m_children.next(anim)) {
126 RETURN_IF_DELETED(setCurrentAnimation(anim,
true));
127 RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim)));
132void QSequentialAnimationGroupJob::rewindForwards(
const AnimationIndex &newAnimationIndex)
134 if (m_previousLoop > m_currentLoop) {
136 for (QAbstractAnimationJob *anim = m_currentAnimation; anim;
137 anim = m_children.prev(anim)) {
138 RETURN_IF_DELETED(setCurrentAnimation(anim,
true));
139 RETURN_IF_DELETED(anim->setCurrentTime(0));
142 if (m_children.count() == 1) {
144 RETURN_IF_DELETED(activateCurrentAnimation());
146 RETURN_IF_DELETED(setCurrentAnimation(m_children.last(),
true));
151 for (QAbstractAnimationJob *anim = m_currentAnimation;
152 anim && anim != newAnimationIndex.animation; anim = m_children.prev(anim)) {
153 RETURN_IF_DELETED(setCurrentAnimation(anim,
true));
154 RETURN_IF_DELETED(anim->setCurrentTime(0));
159int QSequentialAnimationGroupJob::duration()
const
163 for (
const QAbstractAnimationJob *anim : m_children) {
164 const int currentDuration = anim->totalDuration();
165 if (currentDuration == -1)
168 ret += currentDuration;
174void QSequentialAnimationGroupJob::clear()
177 QAnimationGroupJob::clear();
180 Q_ASSERT(m_currentAnimation ==
nullptr);
183void QSequentialAnimationGroupJob::updateCurrentTime(
int currentTime)
185 if (!m_currentAnimation)
188 const QSequentialAnimationGroupJob::AnimationIndex newAnimationIndex = indexForCurrentTime();
191 if (m_previousLoop < m_currentLoop
192 || (m_previousLoop == m_currentLoop && m_currentAnimation != newAnimationIndex.animation && newAnimationIndex.afterCurrent)) {
194 RETURN_IF_DELETED(advanceForwards(newAnimationIndex));
196 }
else if (m_previousLoop > m_currentLoop
197 || (m_previousLoop == m_currentLoop && m_currentAnimation != newAnimationIndex.animation && !newAnimationIndex.afterCurrent)) {
199 RETURN_IF_DELETED(rewindForwards(newAnimationIndex));
202 RETURN_IF_DELETED(setCurrentAnimation(newAnimationIndex.animation));
204 const int newCurrentTime = currentTime - newAnimationIndex.timeOffset;
206 if (m_currentAnimation) {
207 RETURN_IF_DELETED(m_currentAnimation->setCurrentTime(newCurrentTime));
210 m_currentTime += m_currentAnimation->currentTime() - newCurrentTime;
211 RETURN_IF_DELETED(stop());
216 Q_ASSERT(m_children.isEmpty());
218 RETURN_IF_DELETED(stop());
221 m_previousLoop = m_currentLoop;
224void QSequentialAnimationGroupJob::updateState(QAbstractAnimationJob::State newState,
225 QAbstractAnimationJob::State oldState)
227 QAnimationGroupJob::updateState(newState, oldState);
229 if (!m_currentAnimation)
234 m_currentAnimation->stop();
237 if (oldState == m_currentAnimation->state() && oldState == Running)
238 m_currentAnimation->pause();
243 if (oldState == m_currentAnimation->state() && oldState == Paused)
244 m_currentAnimation->start();
251void QSequentialAnimationGroupJob::updateDirection(QAbstractAnimationJob::Direction direction)
254 if (!isStopped() && m_currentAnimation)
255 m_currentAnimation->setDirection(direction);
258void QSequentialAnimationGroupJob::setCurrentAnimation(
259 const QAbstractAnimationJob *anim,
bool intermediate)
262 Q_ASSERT(m_children.isEmpty());
263 m_currentAnimation =
nullptr;
267 if (anim == m_currentAnimation)
271 if (m_currentAnimation)
272 m_currentAnimation->stop();
275 Q_ASSERT(m_children.contains(anim));
279 m_currentAnimation =
const_cast<QAbstractAnimationJob *>(anim);
281 activateCurrentAnimation(intermediate);
284void QSequentialAnimationGroupJob::activateCurrentAnimation(
bool intermediate)
286 if (!m_currentAnimation || isStopped())
289 m_currentAnimation->stop();
292 m_currentAnimation->setDirection(m_direction);
295 if (m_currentAnimation->totalDuration() == -1)
296 resetUncontrolledAnimationFinishTime(m_currentAnimation);
298 RETURN_IF_DELETED(m_currentAnimation->start());
299 if (!intermediate && isPaused())
300 m_currentAnimation->pause();
303void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimationJob *animation)
306 Q_ASSERT(animation == m_currentAnimation);
308 setUncontrolledAnimationFinishTime(m_currentAnimation, m_currentAnimation->currentTime());
310 int totalTime = currentTime();
311 if (m_direction == Forward) {
313 if (
auto *anim = m_children.next(m_currentAnimation))
314 RETURN_IF_DELETED(setCurrentAnimation(anim));
316 for (QAbstractAnimationJob *a = m_children.next(animation); a; a = m_children.next(a)) {
317 int dur = a->duration();
328 if (
auto *anim = m_children.prev(m_currentAnimation))
329 RETURN_IF_DELETED(setCurrentAnimation(anim));
331 for (QAbstractAnimationJob *a = m_children.prev(animation); a; a = m_children.prev(a)) {
332 int dur = a->duration();
342 setUncontrolledAnimationFinishTime(
this, totalTime);
347void QSequentialAnimationGroupJob::animationInserted(QAbstractAnimationJob *anim)
349 if (m_currentAnimation ==
nullptr)
350 RETURN_IF_DELETED(setCurrentAnimation(m_children.first()));
352 if (m_currentAnimation == m_children.next(anim)
353 && m_currentAnimation->currentTime() == 0 && m_currentAnimation->currentLoop() == 0) {
355 RETURN_IF_DELETED(setCurrentAnimation(anim));
365void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim, QAbstractAnimationJob *prev, QAbstractAnimationJob *next)
367 QAnimationGroupJob::animationRemoved(anim, prev, next);
369 Q_ASSERT(m_currentAnimation);
371 bool removingCurrent = anim == m_currentAnimation;
372 if (removingCurrent) {
374 RETURN_IF_DELETED(setCurrentAnimation(next));
376 RETURN_IF_DELETED(setCurrentAnimation(prev));
378 RETURN_IF_DELETED(setCurrentAnimation(
nullptr));
383 for (QAbstractAnimationJob *job : m_children) {
384 if (job == m_currentAnimation)
386 m_currentTime += animationActualTotalDuration(job);
390 if (!removingCurrent) {
393 m_currentTime += m_currentAnimation->currentTime();
397 m_totalCurrentTime = m_currentTime + m_loopCount * duration();
400void QSequentialAnimationGroupJob::debugAnimation(QDebug d)
const
402 d <<
"SequentialAnimationGroupJob(" << Qt::hex << (
const void *)
this << Qt::dec <<
")" <<
"currentAnimation:" << (
void *)m_currentAnimation;