diff options
author | Thierry Bastian <thierry.bastian@nokia.com> | 2009-08-12 12:19:15 (GMT) |
---|---|---|
committer | Thierry Bastian <thierry.bastian@nokia.com> | 2009-08-12 12:21:23 (GMT) |
commit | 657de489549bab1f9d2ba759739dd55f65a8532e (patch) | |
tree | ad1878a9bd11bfe0b7b7f03eddf44cfca5bf7dc7 | |
parent | 4cf8deb5da96b00a3b89c5c328aab3d47e1dfbb3 (diff) | |
download | Qt-657de489549bab1f9d2ba759739dd55f65a8532e.zip Qt-657de489549bab1f9d2ba759739dd55f65a8532e.tar.gz Qt-657de489549bab1f9d2ba759739dd55f65a8532e.tar.bz2 |
Make QPropertyAnimation symetric wrt direction
It is now possible to set a start value and no end value and starting
the animation will pick the default end value from the current value
of the property that's being animated.
-rw-r--r-- | src/corelib/animation/qvariantanimation.cpp | 77 | ||||
-rw-r--r-- | src/corelib/animation/qvariantanimation_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp | 42 |
3 files changed, 81 insertions, 39 deletions
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 61321c8..04e0980 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -178,8 +178,7 @@ template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress)); } -QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), hasStartValue(false), - interpolator(&defaultInterpolator), +QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolator(&defaultInterpolator), changedSignalMask(1 << QVariantAnimation::staticMetaObject.indexOfSignal("valueChanged(QVariant)")) { //we keep the mask so that we emit valueChanged only when needed (for performance reasons) @@ -222,34 +221,52 @@ void QVariantAnimationPrivate::updateInterpolator() void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/) { // can't interpolate if we have only 1 key value - if (keyValues.count() <= 1) + if ((keyValues.count() + (defaultStartValue.isValid() ? 1 : 0)) <=1) return; const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration))); if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) { //let's update currentInterval - QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), + QVariantAnimation::KeyValues::const_iterator it = qLowerBound(keyValues.constBegin(), keyValues.constEnd(), qMakePair(progress, QVariant()), animationValueLessThan); - QVariantAnimation::KeyValues::const_iterator itEnd = itStart; - - // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0). - // This is because the easing function can return a value slightly outside the range [0, 1] - if (itStart != keyValues.constEnd()) { - // this can't happen because we always prepend the default start value there - if (itStart == keyValues.constBegin()) { - ++itEnd; + if (it == keyValues.constEnd()) { + if (direction == QVariantAnimation::Backward && defaultStartValue.isValid()) { + --it; + if (it->first == 1) { + //we have an end value (item with progress = 1) + currentInterval.start = *(it-1); + currentInterval.end = *it; + } else if (direction == QVariantAnimation::Backward && defaultStartValue.isValid()) { + //the default start value should be used as the default end value + currentInterval.start = *it; + currentInterval.end = qMakePair(qreal(1), defaultStartValue); + } else { + ///This should not happen + } + } + } else if (it == keyValues.constBegin()) { + if (it->first == progress || it->first == 0) { + //the item pointed to by it is the start element in the range + //we also test if the current element is for progress 0 (ie the real start) because + //some easing curves might get the progress below 0. + currentInterval.start = *it; + currentInterval.end = *(it+1); + } else if (direction == QVariantAnimation::Forward && defaultStartValue.isValid()) { + currentInterval.start = qMakePair(qreal(0), defaultStartValue); + currentInterval.end = *it; } else { - --itStart; + ///this should not happen } - - // update all the values of the currentInterval - currentInterval.start = *itStart; - currentInterval.end = *itEnd; - updateInterpolator(); + } else { + currentInterval.start = *(it-1); + currentInterval.end = *it; } + + // update all the values of the currentInterval + updateInterpolator(); } setCurrentValueForProgress(progress); } @@ -298,8 +315,6 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) } else { if (value.isValid()) result->second = value; // replaces the previous value - else if (step == 0 && !hasStartValue && defaultStartValue.isValid()) - result->second = defaultStartValue; // resets to the default start value else keyValues.erase(result); // removes the previous value } @@ -310,8 +325,7 @@ void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value) void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value) { defaultStartValue = value; - if (!hasStartValue) - setValueAt(0, value); + recalculateCurrentInterval(/*force=*/true); } /*! @@ -526,11 +540,7 @@ void QVariantAnimation::setEndValue(const QVariant &value) */ QVariant QVariantAnimation::keyValueAt(qreal step) const { - Q_D(const QVariantAnimation); - if (step == 0 && !d->hasStartValue) - return QVariant(); //special case where we don't have an explicit startValue - - return d->valueAt(step); + return d_func()->valueAt(step); } /*! @@ -552,10 +562,7 @@ QVariant QVariantAnimation::keyValueAt(qreal step) const */ void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value) { - Q_D(QVariantAnimation); - if (step == 0) - d->hasStartValue = value.isValid(); - d->setValueAt(step, value); + d_func()->setValueAt(step, value); } /*! @@ -565,12 +572,7 @@ void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value) */ QVariantAnimation::KeyValues QVariantAnimation::keyValues() const { - Q_D(const QVariantAnimation); - QVariantAnimation::KeyValues ret = d->keyValues; - //in case we added the default start value, we remove it - if (!d->hasStartValue && !ret.isEmpty() && ret.at(0).first == 0) - ret.remove(0); - return ret; + return d_func()->keyValues; } /*! @@ -584,7 +586,6 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues) Q_D(QVariantAnimation); d->keyValues = keyValues; qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan); - d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0; d->recalculateCurrentInterval(/*force=*/true); } diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index dbfd956..9c9d25b 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -84,7 +84,6 @@ public: QVariantAnimation::KeyValues keyValues; QVariant currentValue; QVariant defaultStartValue; - bool hasStartValue; //this is used to keep track of the KeyValue interval in which we currently are struct diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp index 6f49d8e..5af6f39 100644 --- a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp @@ -102,6 +102,7 @@ private slots: void easingcurve_data(); void easingcurve(); void startWithoutStartValue(); + void startBackwardWithoutEndValue(); void playForwardBackward(); void interpolated(); void setStartEndValues_data(); @@ -582,6 +583,47 @@ void tst_QPropertyAnimation::startWithoutStartValue() QVERIFY(current <= 110); } +void tst_QPropertyAnimation::startBackwardWithoutEndValue() +{ + QObject o; + o.setProperty("ole", 42); + QCOMPARE(o.property("ole").toInt(), 42); + + QPropertyAnimation anim(&o, "ole"); + anim.setStartValue(100); + anim.setDirection(QAbstractAnimation::Backward); + + //we start without an end value + anim.start(); + QCOMPARE(anim.state(), QAbstractAnimation::Running); + QCOMPARE(o.property("ole").toInt(), 42); //the initial value + + QTest::qWait(100); + int current = anim.currentValue().toInt(); + //it is somewhere in the animation + QVERIFY(current > 42); + QVERIFY(current < 100); + + QTest::qWait(200); + QCOMPARE(anim.state(), QVariantAnimation::Stopped); + current = anim.currentValue().toInt(); + QCOMPARE(current, 100); + QCOMPARE(o.property("ole").toInt(), current); + + anim.setStartValue(110); + anim.start(); + current = anim.currentValue().toInt(); + // the default start value will reevaluate the current property + // and set it to the end value of the last iteration + QCOMPARE(current, 100); + QTest::qWait(100); + current = anim.currentValue().toInt(); + //it is somewhere in the animation + QVERIFY(current >= 100); + QVERIFY(current <= 110); +} + + void tst_QPropertyAnimation::playForwardBackward() { QObject o; |