void QQmlAnimationTimer::updateAnimationsTime(qint64 delta) { //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations if (insideTick) return; lastTick += delta; //we make sure we only call update time if the time has actually changed //it might happen in some cases that the time doesn't change because events are delayed //when the CPU load is high if (delta) { insideTick = true; for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) { QAbstractAnimationJob *animation = animations.at(currentAnimationIdx); int elapsed = animation->m_totalCurrentTime + (animation->direction() == QAbstractAnimationJob::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } if (animationTickDump()) { qDebug() << "***** Dumping Animation Tree ***** ( tick:" << lastTick << "delta:" << delta << ")"; for (int i = 0; i < animations.count(); ++i) qDebug() << animations.at(i); } insideTick = false; currentAnimationIdx = 0; } }
void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim, QAbstractAnimationJob *prev, QAbstractAnimationJob *next) { QAnimationGroupJob::animationRemoved(anim, prev, next); Q_ASSERT(m_currentAnimation); // currentAnimation should always be set bool removingCurrent = anim == m_currentAnimation; if (removingCurrent) { if (next) setCurrentAnimation(next); //let's try to take the next one else if (prev) setCurrentAnimation(prev); else// case all animations were removed setCurrentAnimation(0); } // duration of the previous animations up to the current animation m_currentTime = 0; for (QAbstractAnimationJob *job = firstChild(); job; job = job->nextSibling()) { if (job == m_currentAnimation) break; m_currentTime += animationActualTotalDuration(job); } if (!removingCurrent) { //the current animation is not the one being removed //so we add its current time to the current time of this group m_currentTime += m_currentAnimation->currentTime(); } //let's also update the total current time m_totalCurrentTime = m_currentTime + m_loopCount * duration(); }
void QAnimationGroupJob::resetUncontrolledAnimationsFinishTime() { for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { if (animation->duration() == -1 || animation->loopCount() < 0) { resetUncontrolledAnimationFinishTime(animation); } } }
void QContinuingAnimationGroupJob::updateDirection(QAbstractAnimationJob::Direction direction) { if (!isStopped()) { for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { animation->setDirection(direction); } } }
static void qquickanimator_invalidate_jobs(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { static_cast<QQuickAnimatorJob *>(job)->invalidate(); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) qquickanimator_invalidate_jobs(a); } }
void QContinuingAnimationGroupJob::updateCurrentTime(int /*currentTime*/) { Q_ASSERT(firstChild()); for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { if (animation->state() == state()) { RETURN_IF_DELETED(animation->setCurrentTime(m_currentTime)); } } }
static void qquickanimator_sync_before_start(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { static_cast<QQuickAnimatorJob *>(job)->preSync(); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) qquickanimator_sync_before_start(a); } }
// All this is being executed on the GUI thread while the animator controller // is locked. void QQuickAnimatorController::start_helper(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job); j->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange); j->initialize(this); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) start_helper(a); } }
void QAnimationGroupJob::clear() { QAbstractAnimationJob *child = firstChild(); QAbstractAnimationJob *nextSibling = 0; while (child != 0) { child->m_group = 0; nextSibling = child->nextSibling(); delete child; child = nextSibling; } m_firstChild = 0; m_lastChild = 0; }
static void qquick_syncback_helper(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { QQuickAnimatorJob *a = static_cast<QQuickAnimatorJob *>(job); // Sync back only those jobs that actually have been running if (a->controller() && a->hasBeenRunning()) a->writeBack(); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) qquick_syncback_helper(a); } }
int QSequentialAnimationGroupJob::duration() const { int ret = 0; for (QAbstractAnimationJob *anim = firstChild(); anim; anim = anim->nextSibling()) { const int currentDuration = anim->totalDuration(); if (currentDuration == -1) return -1; // Undetermined length ret += currentDuration; } return ret; }
int QQmlAnimationTimer::closestPauseAnimationTimeToFinish() { int closestTimeToFinish = INT_MAX; for (int i = 0; i < runningPauseAnimations.size(); ++i) { QAbstractAnimationJob *animation = runningPauseAnimations.at(i); int timeToFinish; if (animation->direction() == QAbstractAnimationJob::Forward) timeToFinish = animation->duration() - animation->currentLoopTime(); else timeToFinish = animation->currentLoopTime(); if (timeToFinish < closestTimeToFinish) closestTimeToFinish = timeToFinish; } return closestTimeToFinish; }
void QContinuingAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimationJob *animation) { Q_ASSERT(animation && (animation->duration() == -1)); int uncontrolledRunningCount = 0; for (QAbstractAnimationJob *child = firstChild(); child; child = child->nextSibling()) { if (child == animation) setUncontrolledAnimationFinishTime(animation, animation->currentTime()); else if (uncontrolledAnimationFinishTime(child) == -1) ++uncontrolledRunningCount; } if (uncontrolledRunningCount > 0) return; setUncontrolledAnimationFinishTime(this, currentTime()); stop(); }
void QSequentialAnimationGroupJob::advanceForwards(const AnimationIndex &newAnimationIndex) { if (m_previousLoop < m_currentLoop) { // we need to fast forward to the end for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->nextSibling()) { setCurrentAnimation(anim, true); RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim))); } // this will make sure the current animation is reset to the beginning if (firstChild() && !firstChild()->nextSibling()) //count == 1 // we need to force activation because setCurrentAnimation will have no effect activateCurrentAnimation(); else setCurrentAnimation(firstChild(), true); } // and now we need to fast forward from the current position to for (QAbstractAnimationJob *anim = m_currentAnimation; anim && anim != newAnimationIndex.animation; anim = anim->nextSibling()) { //### WRONG, setCurrentAnimation(anim, true); RETURN_IF_DELETED(anim->setCurrentTime(animationActualTotalDuration(anim))); } // setting the new current animation will happen later }
QSequentialAnimationGroupJob::AnimationIndex QSequentialAnimationGroupJob::indexForCurrentTime() const { Q_ASSERT(firstChild()); AnimationIndex ret; QAbstractAnimationJob *anim = 0; int duration = 0; for (anim = firstChild(); anim; anim = anim->nextSibling()) { duration = animationActualTotalDuration(anim); // 'animation' is the current animation if one of these reasons is true: // 1. it's duration is undefined // 2. it ends after msecs // 3. it is the last animation (this can happen in case there is at least 1 uncontrolled animation) // 4. it ends exactly in msecs and the direction is backwards if (duration == -1 || m_currentTime < (ret.timeOffset + duration) || (m_currentTime == (ret.timeOffset + duration) && m_direction == QAbstractAnimationJob::Backward)) { ret.animation = anim; return ret; } if (anim == m_currentAnimation) { ret.afterCurrent = true; } // 'animation' has a non-null defined duration and is not the one at time 'msecs'. ret.timeOffset += duration; } // this can only happen when one of those conditions is true: // 1. the duration of the group is undefined and we passed its actual duration // 2. there are only 0-duration animations in the group ret.timeOffset -= duration; ret.animation = lastChild(); return ret; }
void QSequentialAnimationGroupJob::rewindForwards(const AnimationIndex &newAnimationIndex) { if (m_previousLoop > m_currentLoop) { // we need to fast rewind to the beginning for (QAbstractAnimationJob *anim = m_currentAnimation; anim; anim = anim->previousSibling()) { RETURN_IF_DELETED(setCurrentAnimation(anim, true)); RETURN_IF_DELETED(anim->setCurrentTime(0)); } // this will make sure the current animation is reset to the end if (lastChild() && !lastChild()->previousSibling()) { //count == 1 // we need to force activation because setCurrentAnimation will have no effect RETURN_IF_DELETED(activateCurrentAnimation()); } else { RETURN_IF_DELETED(setCurrentAnimation(lastChild(), true)); } } // and now we need to fast rewind from the current position to for (QAbstractAnimationJob *anim = m_currentAnimation; anim && anim != newAnimationIndex.animation; anim = anim->previousSibling()) { RETURN_IF_DELETED(setCurrentAnimation(anim, true)); RETURN_IF_DELETED(anim->setCurrentTime(0)); } // setting the new current animation will happen later }
void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimationJob *animation) { Q_UNUSED(animation); Q_ASSERT(animation == m_currentAnimation); setUncontrolledAnimationFinishTime(m_currentAnimation, m_currentAnimation->currentTime()); int totalTime = currentTime(); if (m_direction == Forward) { // set the current animation to be the next one if (m_currentAnimation->nextSibling()) setCurrentAnimation(m_currentAnimation->nextSibling()); for (QAbstractAnimationJob *a = animation->nextSibling(); a; a = a->nextSibling()) { int dur = a->duration(); if (dur == -1) { totalTime = -1; break; } else { totalTime += dur; } } } else { // set the current animation to be the previous one if (m_currentAnimation->previousSibling()) setCurrentAnimation(m_currentAnimation->previousSibling()); for (QAbstractAnimationJob *a = animation->previousSibling(); a; a = a->previousSibling()) { int dur = a->duration(); if (dur == -1) { totalTime = -1; break; } else { totalTime += dur; } } } if (totalTime >= 0) setUncontrolledAnimationFinishTime(this, totalTime); if (atEnd()) stop(); }
void QAnimationGroupJob::topLevelAnimationLoopChanged() { for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) animation->topLevelAnimationLoopChanged(); }
void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) { QAnimationGroupJob::updateState(newState, oldState); switch (newState) { case Stopped: for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) animation->stop(); break; case Paused: for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) if (animation->isRunning()) animation->pause(); break; case Running: if (!firstChild()) { stop(); return; } for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { resetUncontrolledAnimationFinishTime(animation); animation->setDirection(m_direction); animation->start(); } break; } }