/*! \internal This manages advancing the execution of a group running forwards (time has gone forward), which is the same behaviour for rewinding the execution of a group running backwards (time has gone backward). */ void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex) { if (lastLoop < currentLoop) { // we need to fast forward to the end for (int i = currentAnimationIndex; i < animations.size(); ++i) { QAbstractAnimation *anim = animations.at(i); setCurrentAnimation(i, true); anim->setCurrentTime(animationActualTotalDuration(i)); } // this will make sure the current animation is reset to the beginning if (animations.size() == 1) // we need to force activation because setCurrentAnimation will have no effect activateCurrentAnimation(); else setCurrentAnimation(0, true); } // and now we need to fast forward from the current position to for (int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) { //### WRONG, QAbstractAnimation *anim = animations.at(i); setCurrentAnimation(i, true); anim->setCurrentTime(animationActualTotalDuration(i)); } // setting the new current animation will happen later }
/*! \internal This manages rewinding the execution of a group running forwards (time has gone forward), which is the same behaviour for advancing the execution of a group running backwards (time has gone backward). */ void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex) { if (lastLoop > currentLoop) { // we need to fast rewind to the beginning for (int i = currentAnimationIndex; i >= 0 ; --i) { QAbstractAnimation *anim = animations.at(i); setCurrentAnimation(i, true); anim->setCurrentTime(0); } // this will make sure the current animation is reset to the end if (animations.size() == 1) // we need to force activation because setCurrentAnimation will have no effect activateCurrentAnimation(); else setCurrentAnimation(animations.count() - 1, true); } // and now we need to fast rewind from the current position to for (int i = currentAnimationIndex; i > newAnimationIndex.index; --i) { QAbstractAnimation *anim = animations.at(i); setCurrentAnimation(i, true); anim->setCurrentTime(0); } // setting the new current animation will happen later }
void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished() { Q_Q(QParallelAnimationGroup); QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender()); Q_ASSERT(animation); int uncontrolledRunningCount = 0; if (animation->duration() == -1 || animation->loopCount() < 0) { QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin(); while (it != uncontrolledFinishTime.end()) { if (it.key() == animation) { *it = animation->currentTime(); } if (it.value() == -1) ++uncontrolledRunningCount; ++it; } } if (uncontrolledRunningCount > 0) return; int maxDuration = 0; for (int i = 0; i < animations.size(); ++i) maxDuration = qMax(maxDuration, animations.at(i)->totalDuration()); if (currentTime >= maxDuration) q->stop(); }
/*! \reimp */ void QParallelAnimationGroup::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { Q_D(QParallelAnimationGroup); QAnimationGroup::updateState(newState, oldState); switch (newState) { case Stopped: for (int i = 0; i < d->animations.size(); ++i) d->animations.at(i)->stop(); d->disconnectUncontrolledAnimations(); break; case Paused: for (int i = 0; i < d->animations.size(); ++i) if (d->animations.at(i)->state() == Running) d->animations.at(i)->pause(); break; case Running: d->connectUncontrolledAnimations(); for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); if (oldState == Stopped) animation->stop(); animation->setDirection(d->direction); if (d->shouldAnimationStart(animation, oldState == Stopped)) animation->start(); } break; } }
void QUnifiedTimer::updateAnimationsTime() { //setCurrentTime can get this called again while we're the for loop. At least with pauseAnimations if(insideTick) return; qint64 totalElapsed = time.elapsed(); // ignore consistentTiming in case the pause timer is active int delta = (consistentTiming && !isPauseTimerActive) ? timingInterval : totalElapsed - lastTick; if (slowMode) { if (slowdownFactor > 0) delta = qRound(delta / slowdownFactor); else delta = 0; } lastTick = totalElapsed; //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) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } insideTick = false; currentAnimationIdx = 0; } }
int QSequentialAnimationGroupPrivate::animationActualTotalDuration(int index) const { QAbstractAnimation *anim = animations.at(index); int ret = anim->totalDuration(); if (ret == -1 && actualDuration.size() > index) ret = actualDuration.at(index); //we can try the actual duration there return ret; }
void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() { for (int i = 0; i < animations.size(); ++i) { QAbstractAnimation *animation = animations.at(i); if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; connectUncontrolledAnimation(animation); } } }
/*! \reimp */ void QParallelAnimationGroup::updateCurrentTime(int currentTime) { Q_D(QParallelAnimationGroup); if (d->animations.isEmpty()) return; if (d->currentLoop > d->lastLoop) { // simulate completion of the loop int dura = duration(); if (dura > 0) { for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); if (animation->state() != QAbstractAnimation::Stopped) d->animations.at(i)->setCurrentTime(dura); // will stop } } } else if (d->currentLoop < d->lastLoop) { // simulate completion of the loop seeking backwards for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); //we need to make sure the animation is in the right state //and then rewind it d->applyGroupState(animation); animation->setCurrentTime(0); animation->stop(); } } #ifdef QANIMATION_DEBUG qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d", __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state()); #endif // finally move into the actual time of the current loop for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); const int dura = animation->totalDuration(); //if the loopcount is bigger we should always start all animations if (d->currentLoop > d->lastLoop //if we're at the end of the animation, we need to start it if it wasn't already started in this loop //this happens in Backward direction where not all animations are started at the same time || d->shouldAnimationStart(animation, d->lastCurrentTime > dura /*startIfAtEnd*/)) { d->applyGroupState(animation); } if (animation->state() == state()) { animation->setCurrentTime(currentTime); if (dura > 0 && currentTime > dura) animation->stop(); } } d->lastLoop = d->currentLoop; d->lastCurrentTime = currentTime; }
void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() { Q_Q(QParallelAnimationGroup); for (int i = 0; i < animations.size(); ++i) { QAbstractAnimation *animation = animations.at(i); if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); } } }
/*! Returns the animation at \a index and removes it from the animation group. \note The ownership of the animation is transferred to the caller. \sa removeAnimation(), addAnimation(), insertAnimation(), indexOfAnimation() */ QAbstractAnimation *QAnimationGroup::takeAnimation(int index) { Q_D(QAnimationGroup); if (index < 0 || index >= d->animations.size()) { qWarning("QAnimationGroup::takeAnimation: no animation at index %d", index); return 0; } QAbstractAnimation *animation = d->animations.at(index); QAbstractAnimationPrivate::get(animation)->group = 0; // ### removing from list before doing setParent to avoid inifinite recursion // in ChildRemoved event d->animations.removeAt(index); animation->setParent(0); d->animationRemoved(index, animation); return animation; }
/*! \reimp */ int QSequentialAnimationGroup::duration() const { Q_D(const QSequentialAnimationGroup); int ret = 0; for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); const int currentDuration = animation->totalDuration(); if (currentDuration == -1) return -1; // Undetermined length ret += currentDuration; } return ret; }
int QAnimationTimer::closestPauseAnimationTimeToFinish() { int closestTimeToFinish = INT_MAX; for (int i = 0; i < runningPauseAnimations.size(); ++i) { QAbstractAnimation *animation = runningPauseAnimations.at(i); int timeToFinish; if (animation->direction() == QAbstractAnimation::Forward) timeToFinish = animation->duration() - animation->currentLoopTime(); else timeToFinish = animation->currentLoopTime(); if (timeToFinish < closestTimeToFinish) closestTimeToFinish = timeToFinish; } return closestTimeToFinish; }
/*! \reimp */ void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction) { Q_D(QParallelAnimationGroup); //we need to update the direction of the current animation if (state() != Stopped) { for (int i = 0; i < d->animations.size(); ++i) { QAbstractAnimation *animation = d->animations.at(i); animation->setDirection(direction); } } else { if (direction == Forward) { d->lastLoop = 0; d->lastCurrentTime = 0; } else { // Looping backwards with loopCount == -1 does not really work well... d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1); d->lastCurrentTime = duration(); } } }
void QUnifiedTimer::updateAnimationsTime() { // ignore consistentTiming in case the pause timer is active int delta = (consistentTiming && !isPauseTimerActive) ? timingInterval : time.elapsed() - lastTick; if (slowMode) delta /= 5; lastTick = time.elapsed(); //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) { for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } currentAnimationIdx = 0; } }
void QAnimationTimer::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) { QAbstractAnimation *animation = animations.at(currentAnimationIdx); int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta); animation->setCurrentTime(elapsed); } insideTick = false; currentAnimationIdx = 0; } }