diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-03-30 06:06:18 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-03-30 06:06:18 (GMT) |
commit | 2df6a9a02a43d88d2ddb73c08c02ad29712a8fbc (patch) | |
tree | cea85c3e3334f80b19f420a275dbe1e5b4c6aefa /src/declarative/util | |
parent | ff983ee8257b79143911ca58ebedc49b1660a0c4 (diff) | |
parent | 2661be1bacdd83d1b3e6207c519c2699edfdc1d0 (diff) | |
download | Qt-2df6a9a02a43d88d2ddb73c08c02ad29712a8fbc.zip Qt-2df6a9a02a43d88d2ddb73c08c02ad29712a8fbc.tar.gz Qt-2df6a9a02a43d88d2ddb73c08c02ad29712a8fbc.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Diffstat (limited to 'src/declarative/util')
-rw-r--r-- | src/declarative/util/qdeclarativeanimation.cpp | 19 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativeanimation_p.h | 10 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativeanimation_p_p.h | 5 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativebehavior.cpp | 3 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativeeasefollow.cpp | 537 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativesmoothedanimation.cpp | 483 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativesmoothedanimation_p.h (renamed from src/declarative/util/qdeclarativeeasefollow_p.h) | 48 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativesmoothedanimation_p_p.h | 134 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativespringfollow.cpp | 2 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativetransition.cpp | 6 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativeutilmodule.cpp | 4 | ||||
-rw-r--r-- | src/declarative/util/util.pri | 5 |
12 files changed, 674 insertions, 582 deletions
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index bad142c..ba1444e 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -1078,15 +1078,26 @@ void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions, QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QObject *parent) : QDeclarativePropertyAnimation(parent) { - Q_D(QDeclarativePropertyAnimation); - d->interpolatorType = QMetaType::QReal; - d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); + init(); +} + +QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent) +: QDeclarativePropertyAnimation(dd, parent) +{ + init(); } QDeclarativeNumberAnimation::~QDeclarativeNumberAnimation() { } +void QDeclarativeNumberAnimation::init() +{ + Q_D(QDeclarativePropertyAnimation); + d->interpolatorType = QMetaType::QReal; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); +} + /*! \qmlproperty real NumberAnimation::from This property holds the starting value. @@ -2237,8 +2248,10 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions } d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); d->va->setFromSourcedValue(&data->fromSourced); + d->actions = &data->actions; } else { delete data; + d->actions = 0; } } diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index 816520e..f620786 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -251,8 +251,8 @@ public: QDeclarativePropertyAnimation(QObject *parent=0); virtual ~QDeclarativePropertyAnimation(); - int duration() const; - void setDuration(int); + virtual int duration() const; + virtual void setDuration(int); QVariant from() const; void setFrom(const QVariant &); @@ -326,6 +326,12 @@ public: qreal to() const; void setTo(qreal); + +protected: + QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent); + +private: + void init(); }; class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index 2a66c8a..8bcbeff 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -304,7 +304,7 @@ class QDeclarativePropertyAnimationPrivate : public QDeclarativeAbstractAnimatio public: QDeclarativePropertyAnimationPrivate() : QDeclarativeAbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false), - rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0) {} + rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0), actions(0) {} void init(); @@ -330,6 +330,9 @@ public: QDeclarativeBulkValueAnimator *va; + // for animations that dont use the QDeclarativeBulkValueAnimator + QDeclarativeStateActions *actions; + static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress); static void convertVariant(QVariant &variant, int type); }; diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp index 7181777..87d6836 100644 --- a/src/declarative/util/qdeclarativebehavior.cpp +++ b/src/declarative/util/qdeclarativebehavior.cpp @@ -163,7 +163,8 @@ void QDeclarativeBehavior::write(const QVariant &value) d->currentValue = d->property.read(); - d->animation->qtAnimation()->stop(); + if (d->animation->qtAnimation()->duration() != -1) + d->animation->qtAnimation()->stop(); QDeclarativeStateOperation::ActionList actions; QDeclarativeAction action; diff --git a/src/declarative/util/qdeclarativeeasefollow.cpp b/src/declarative/util/qdeclarativeeasefollow.cpp deleted file mode 100644 index ee181dd..0000000 --- a/src/declarative/util/qdeclarativeeasefollow.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativeeasefollow_p.h" - -#include "qdeclarativeanimation_p_p.h" - -#include <qdeclarativeproperty.h> - -#include <QtCore/qdebug.h> - -#include <math.h> - -QT_BEGIN_NAMESPACE - - - -class QDeclarativeEaseFollowPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeEaseFollow) -public: - QDeclarativeEaseFollowPrivate() - : source(0), velocity(200), duration(-1), maximumEasingTime(-1), - reversingMode(QDeclarativeEaseFollow::Eased), initialVelocity(0), - initialValue(0), invert(false), enabled(true), trackVelocity(0), clockOffset(0), - lastTick(0), clock(this) - {} - - qreal source; - qreal velocity; - qreal duration; - qreal maximumEasingTime; - QDeclarativeEaseFollow::ReversingMode reversingMode; - - qreal initialVelocity; - qreal initialValue; - bool invert; - bool enabled; - - qreal trackVelocity; - - QDeclarativeProperty target; - - int clockOffset; - int lastTick; - void tick(int); - void clockStart(); - void clockStop(); - QTickAnimationProxy<QDeclarativeEaseFollowPrivate, &QDeclarativeEaseFollowPrivate::tick> clock; - - void restart(); - - // Parameters for use in tick() - qreal a; // Acceleration - qreal d; // Deceleration - qreal tf; // Total time - qreal tp; // Time at which peak velocity occurs - qreal td; // Time at which decelleration begins - qreal vp; // Velocity at tp - qreal sp; // Displacement at tp - qreal sd; // Displacement at td - qreal vi; // "Normalized" initialvelocity - bool recalc(); -}; - -bool QDeclarativeEaseFollowPrivate::recalc() -{ - qreal s = source - initialValue; - vi = initialVelocity; - - s = (invert?-1.0:1.0) * s; - vi = (invert?-1.0:1.0) * vi; - - if (duration > 0 && velocity > 0) { - tf = s / velocity; - if (tf > (duration / 1000.)) tf = (duration / 1000.); - } else if (duration > 0) { - tf = duration / 1000.; - } else if (velocity > 0) { - tf = s / velocity; - } else { - return false; - } - - if (maximumEasingTime == 0) { - a = 0; - d = 0; - tp = 0; - td = tf; - vp = velocity; - sp = 0; - sd = s; - } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) { - - qreal met = maximumEasingTime / 1000.; - td = tf - met; - - qreal c1 = td; - qreal c2 = (tf - td) * vi - tf * velocity; - qreal c3 = -0.5 * (tf - td) * vi * vi; - - qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - // qreal vp2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - - vp = vp1; - a = vp / met; - d = a; - tp = (vp - vi) / a; - sp = vi * tp + 0.5 * a * tp * tp; - sd = sp + (td - tp) * vp; - } else { - - qreal c1 = 0.25 * tf * tf; - qreal c2 = 0.5 * vi * tf - s; - qreal c3 = -0.25 * vi * vi; - - qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - //qreal a2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); - - qreal tp1 = 0.5 * tf - 0.5 * vi / a1; - //qreal tp2 = 0.5 * tf - 0.5 * vi / a2; - qreal vp1 = a1 * tp1 + vi; - //qreal vp2 = a2 * tp2 + vi; - - qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1; - //qreal sp2 = 0.5 * a2 * tp2 * tp2 + vi * tp2; - - a = a1; - d = a1; - tp = tp1; - td = tp1; - vp = vp1; - sp = sp1; - sd = sp1; - } - - /* - qWarning() << "a:" << a << "tf:" << tf << "tp:" << tp << "vp:" - << vp << "sp:" << sp << "vi:" << vi << "invert:" << invert; - */ - return true; -} - -void QDeclarativeEaseFollowPrivate::clockStart() -{ - if (clock.state() == QAbstractAnimation::Running) { - clockOffset = lastTick; - return; - } else { - clockOffset = 0; - lastTick = 0; - clock.start(); - } -} - -void QDeclarativeEaseFollowPrivate::clockStop() -{ - clockOffset = 0; - lastTick = 0; - clock.stop(); -} - -void QDeclarativeEaseFollowPrivate::tick(int t) -{ - lastTick = t; - t -= clockOffset; - - qreal time_seconds = qreal(t) / 1000.; - - qreal out = 0; - if (time_seconds < tp) { - - trackVelocity = vi + time_seconds * a; - trackVelocity = (invert?-1.0:1.0) * trackVelocity; - - qreal value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds; - value = (invert?-1.0:1.0) * value; - target.write(initialValue + value); - out = initialValue + value; - } else if (time_seconds < td) { - - time_seconds -= tp; - trackVelocity = (invert?-1.0:1.0) * vp; - qreal value = sp + time_seconds * vp; - value = (invert?-1.0:1.0) * value; - - target.write(initialValue + value); - - out = initialValue + value; - } else if (time_seconds < tf) { - - time_seconds -= td; - - trackVelocity = vp - time_seconds * a; - trackVelocity = (invert?-1.0:1.0) * trackVelocity; - - qreal value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds; - value = (invert?-1.0:1.0) * value; - - target.write(initialValue + value); - - out = initialValue + value; - } else { - - clock.stop(); - - trackVelocity = 0; - target.write(source); - } - - //qWarning() << out << trackVelocity << t << a; -} - -/*! - \qmlclass EaseFollow QDeclarativeEaseFollow - \since 4.7 - \brief The EaseFollow element allows a property to smoothly track a value. - - The EaseFollow smoothly animates a property's value to a set target value - using an ease in/out quad easing curve. If the target value changes while - the animation is in progress, the easing curves used to animate to the old - and the new target values are spliced together to avoid any obvious visual - glitches. - - The property animation is configured by setting the velocity at which the - animation should occur, or the duration that the animation should take. - If both a velocity and a duration are specified, the one that results in - the quickest animation is chosen for each change in the target value. - - For example, animating from 0 to 800 will take 4 seconds if a velocity - of 200 is set, will take 8 seconds with a duration of 8000 set, and will - take 4 seconds with both a velocity of 200 and a duration of 8000 set. - Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, - will take 8 seconds with a duration of 8000 set, and will take 8 seconds - with both a velocity of 200 and a duration of 8000 set. - - The follow example shows one rectangle tracking the position of another. -\code -import Qt 4.6 - -Rectangle { - width: 800; height: 600; color: "blue" - - Rectangle { - color: "green" - width: 60; height: 60; - x: -5; y: -5; - EaseFollow on x { source: rect1.x - 5; velocity: 200 } - EaseFollow on y { source: rect1.y - 5; velocity: 200 } - } - - Rectangle { - id: rect1 - color: "red" - width: 50; height: 50; - } - - focus: true - Keys.onRightPressed: rect1.x = rect1.x + 100 - Keys.onLeftPressed: rect1.x = rect1.x - 100 - Keys.onUpPressed: rect1.y = rect1.y - 100 - Keys.onDownPressed: rect1.y = rect1.y + 100 -} -\endcode - - The default velocity of EaseFollow is 200 units/second. Note that if the range of the - value being animated is small, then the velocity will need to be adjusted - appropriately. For example, the opacity of an item ranges from 0 - 1.0. - To enable a smooth animation in this range the velocity will need to be - set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity - of 0.5 will take 2000 ms to complete. - - \sa SpringFollow -*/ - -QDeclarativeEaseFollow::QDeclarativeEaseFollow(QObject *parent) -: QObject(*(new QDeclarativeEaseFollowPrivate), parent) -{ -} - -QDeclarativeEaseFollow::~QDeclarativeEaseFollow() -{ -} - -/*! - \qmlproperty qreal EaseFollow::source - This property holds the source value which will be tracked. - - Bind to a property in order to track its changes. -*/ -qreal QDeclarativeEaseFollow::sourceValue() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->source; -} - -/*! - \qmlproperty enumeration EaseFollow::reversingMode - - Sets how the EaseFollow behaves if an animation direction is reversed. - - If reversing mode is \c Eased, the animation will smoothly decelerate, and - then reverse direction. If the reversing mode is \c Immediate, the - animation will immediately begin accelerating in the reverse direction, - begining with a velocity of 0. If the reversing mode is \c Sync, the - property is immediately set to the target value. -*/ -QDeclarativeEaseFollow::ReversingMode QDeclarativeEaseFollow::reversingMode() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->reversingMode; -} - -void QDeclarativeEaseFollow::setReversingMode(ReversingMode m) -{ - Q_D(QDeclarativeEaseFollow); - if (d->reversingMode == m) - return; - - d->reversingMode = m; - emit reversingModeChanged(); -} - -void QDeclarativeEaseFollowPrivate::restart() -{ - if (!enabled || velocity == 0) { - clockStop(); - return; - } - - initialValue = target.read().toReal(); - - if (source == initialValue) { - clockStop(); - return; - } - - bool hasReversed = trackVelocity != 0. && - ((trackVelocity > 0) == ((initialValue - source) > 0)); - - if (hasReversed) { - switch (reversingMode) { - default: - case QDeclarativeEaseFollow::Eased: - break; - case QDeclarativeEaseFollow::Sync: - target.write(source); - return; - case QDeclarativeEaseFollow::Immediate: - initialVelocity = 0; - clockStop(); - break; - } - } - - trackVelocity = initialVelocity; - - invert = (source < initialValue); - - if (!recalc()) { - target.write(source); - clockStop(); - return; - } - - clockStart(); -} - -void QDeclarativeEaseFollow::setSourceValue(qreal s) -{ - Q_D(QDeclarativeEaseFollow); - - if (d->clock.state() == QAbstractAnimation::Running && d->source == s) - return; - - d->source = s; - d->initialVelocity = d->trackVelocity; - d->restart(); - - emit sourceChanged(); -} - -/*! - \qmlproperty qreal EaseFollow::duration - - This property holds the animation duration used when tracking the source. - - Setting this to -1 (the default) disables the duration value. -*/ -qreal QDeclarativeEaseFollow::duration() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->duration; -} - -void QDeclarativeEaseFollow::setDuration(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - if (d->duration == v) - return; - - d->duration = v; - d->trackVelocity = 0; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit durationChanged(); -} - -qreal QDeclarativeEaseFollow::velocity() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->velocity; -} - -/*! - \qmlproperty qreal EaseFollow::velocity - - This property holds the average velocity allowed when tracking the source. - - The default velocity of EaseFollow is 200 units/second. - - Setting this to -1 disables the velocity value. -*/ -void QDeclarativeEaseFollow::setVelocity(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - if (d->velocity == v) - return; - - d->velocity = v; - d->trackVelocity = 0; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit velocityChanged(); -} - -/*! - \qmlproperty bool EaseFollow::enabled - This property holds whether the target will track the source. -*/ -bool QDeclarativeEaseFollow::enabled() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->enabled; -} - -void QDeclarativeEaseFollow::setEnabled(bool enabled) -{ - Q_D(QDeclarativeEaseFollow); - if (d->enabled == enabled) - return; - - d->enabled = enabled; - if (enabled) - d->restart(); - else - d->clockStop(); - - emit enabledChanged(); -} - -void QDeclarativeEaseFollow::setTarget(const QDeclarativeProperty &t) -{ - Q_D(QDeclarativeEaseFollow); - d->target = t; -} - -/*! -\qmlproperty qreal EaseFollow::maximumEasingTime - -This property specifies the maximum time an "eases" during the follow should take. -Setting this property causes the velocity to "level out" after at a time. Setting -a negative value reverts to the normal mode of easing over the entire animation -duration. - -The default value is -1. -*/ -qreal QDeclarativeEaseFollow::maximumEasingTime() const -{ - Q_D(const QDeclarativeEaseFollow); - return d->maximumEasingTime; -} - -void QDeclarativeEaseFollow::setMaximumEasingTime(qreal v) -{ - Q_D(QDeclarativeEaseFollow); - d->maximumEasingTime = v; - - if (d->clock.state() == QAbstractAnimation::Running) - d->restart(); - - emit maximumEasingTimeChanged(); -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp new file mode 100644 index 0000000..b3a9b9a --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp @@ -0,0 +1,483 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesmoothedanimation_p.h" +#include "qdeclarativesmoothedanimation_p_p.h" + +#include "qdeclarativeanimation_p_p.h" + +#include <qdeclarativeproperty.h> +#include "qdeclarativeproperty_p.h" + +#include "qdeclarativeglobal_p.h" + +#include <QtCore/qdebug.h> + +#include <math.h> + +#define DELAY_STOP_TIMER_INTERVAL 32 + +QT_BEGIN_NAMESPACE + +QSmoothedAnimation::QSmoothedAnimation(QObject *parent) + : QAbstractAnimation(parent), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1), + reversingMode(QDeclarativeSmoothedAnimation::Eased), initialVelocity(0), + trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0) +{ + delayedStopTimer.setInterval(DELAY_STOP_TIMER_INTERVAL); + delayedStopTimer.setSingleShot(true); + connect(&delayedStopTimer, SIGNAL(timeout()), this, SLOT(stop())); +} + +void QSmoothedAnimation::restart() +{ + if (state() != QAbstractAnimation::Running) + start(); + else + init(); +} + +void QSmoothedAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/) +{ + if (newState == QAbstractAnimation::Running) + init(); +} + +void QSmoothedAnimation::delayedStop() +{ + if (!delayedStopTimer.isActive()) + delayedStopTimer.start(); +} + +int QSmoothedAnimation::duration() const +{ + return -1; +} + +bool QSmoothedAnimation::recalc() +{ + s = to - initialValue; + vi = initialVelocity; + + s = (invert? -1.0: 1.0) * s; + + if (userDuration > 0 && velocity > 0) { + tf = s / velocity; + if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.); + } else if (userDuration > 0) { + tf = userDuration / 1000.; + } else if (velocity > 0) { + tf = s / velocity; + } else { + return false; + } + + finalDuration = ceil(tf * 1000.0); + + if (maximumEasingTime == 0) { + a = 0; + d = 0; + tp = 0; + td = tf; + vp = velocity; + sp = 0; + sd = s; + } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) { + qreal met = maximumEasingTime / 1000.; + td = tf - met; + + qreal c1 = td; + qreal c2 = (tf - td) * vi - tf * velocity; + qreal c3 = -0.5 * (tf - td) * vi * vi; + + qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); + + vp = vp1; + a = vp / met; + d = a; + tp = (vp - vi) / a; + sp = vi * tp + 0.5 * a * tp * tp; + sd = sp + (td - tp) * vp; + } else { + qreal c1 = 0.25 * tf * tf; + qreal c2 = 0.5 * vi * tf - s; + qreal c3 = -0.25 * vi * vi; + + qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1); + + qreal tp1 = 0.5 * tf - 0.5 * vi / a1; + qreal vp1 = a1 * tp1 + vi; + + qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1; + + a = a1; + d = a1; + tp = tp1; + td = tp1; + vp = vp1; + sp = sp1; + sd = sp1; + } + return true; +} + +qreal QSmoothedAnimation::easeFollow(qreal time_seconds) +{ + qreal value; + if (time_seconds < tp) { + trackVelocity = vi + time_seconds * a; + value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds; + } else if (time_seconds < td) { + time_seconds -= tp; + trackVelocity = vp; + value = sp + time_seconds * vp; + } else if (time_seconds < tf) { + time_seconds -= td; + trackVelocity = vp - time_seconds * a; + value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds; + } else { + trackVelocity = 0; + value = s; + delayedStop(); + } + + // to normalize 's' between [0..1], divide 'value' by 's' + return value; +} + +void QSmoothedAnimation::updateCurrentTime(int t) +{ + qreal time_seconds = qreal(t - lastTime) / 1000.; + + qreal value = easeFollow(time_seconds); + value *= (invert? -1.0: 1.0); + QDeclarativePropertyPrivate::write(target, initialValue + value, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); +} + +void QSmoothedAnimation::init() +{ + if (velocity == 0) { + stop(); + return; + } + + if (delayedStopTimer.isActive()) + delayedStopTimer.stop(); + + initialValue = target.read().toReal(); + lastTime = this->currentTime(); + + if (to == initialValue) { + stop(); + return; + } + + bool hasReversed = trackVelocity != 0. && + ((trackVelocity > 0) == ((initialValue - to) > 0)); + + if (hasReversed) { + switch (reversingMode) { + default: + case QDeclarativeSmoothedAnimation::Eased: + break; + case QDeclarativeSmoothedAnimation::Sync: + QDeclarativePropertyPrivate::write(target, to, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); + return; + case QDeclarativeSmoothedAnimation::Immediate: + initialVelocity = 0; + delayedStop(); + break; + } + } + + trackVelocity = initialVelocity; + + invert = (to < initialValue); + + if (!recalc()) { + QDeclarativePropertyPrivate::write(target, to, + QDeclarativePropertyPrivate::BypassInterceptor + | QDeclarativePropertyPrivate::DontRemoveBinding); + stop(); + return; + } +} + +/*! + \qmlclass SmoothedAnimation QDeclarativeSmoothedAnimation + \since 4.7 + \brief The SmoothedAnimation element allows a property to smoothly track a value. + + The SmoothedAnimation smoothly animates a property's value to a set target value + using an ease in/out quad easing curve. If the animation is restarted + with a different target value, the easing curves used to animate to the old + and the new target values are spliced together to avoid any obvious visual + glitches. + + The property animation is configured by setting the velocity at which the + animation should occur, or the duration that the animation should take. + If both a velocity and a duration are specified, the one that results in + the quickest animation is chosen for each change in the target value. + + For example, animating from 0 to 800 will take 4 seconds if a velocity + of 200 is set, will take 8 seconds with a duration of 8000 set, and will + take 4 seconds with both a velocity of 200 and a duration of 8000 set. + Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, + will take 8 seconds with a duration of 8000 set, and will take 8 seconds + with both a velocity of 200 and a duration of 8000 set. + + The follow example shows one rectangle tracking the position of another. +\code +import Qt 4.6 + +Rectangle { + width: 800; height: 600; color: "blue" + + Rectangle { + color: "green" + width: 60; height: 60; + x: rect1.x - 5; y: rect1.y - 5; + Behavior on x { SmoothedAnimation { velocity: 200 } } + Behavior on y { SmoothedAnimation { velocity: 200 } } + } + + Rectangle { + id: rect1 + color: "red" + width: 50; height: 50; + } + + focus: true + Keys.onRightPressed: rect1.x = rect1.x + 100 + Keys.onLeftPressed: rect1.x = rect1.x - 100 + Keys.onUpPressed: rect1.y = rect1.y - 100 + Keys.onDownPressed: rect1.y = rect1.y + 100 +} +\endcode + + The default velocity of SmoothedAnimation is 200 units/second. Note that if the range of the + value being animated is small, then the velocity will need to be adjusted + appropriately. For example, the opacity of an item ranges from 0 - 1.0. + To enable a smooth animation in this range the velocity will need to be + set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity + of 0.5 will take 2000 ms to complete. + + \sa SpringFollow +*/ + +QDeclarativeSmoothedAnimation::QDeclarativeSmoothedAnimation(QObject *parent) +: QDeclarativeNumberAnimation(*(new QDeclarativeSmoothedAnimationPrivate), parent) +{ +} + +QDeclarativeSmoothedAnimation::~QDeclarativeSmoothedAnimation() +{ +} + +QDeclarativeSmoothedAnimationPrivate::QDeclarativeSmoothedAnimationPrivate() + : wrapperGroup(new QParallelAnimationGroup), anim(new QSmoothedAnimation) +{ + Q_Q(QDeclarativeSmoothedAnimation); + QDeclarative_setParent_noEvent(wrapperGroup, q); + QDeclarative_setParent_noEvent(anim, q); +} + +QAbstractAnimation* QDeclarativeSmoothedAnimation::qtAnimation() +{ + Q_D(QDeclarativeSmoothedAnimation); + return d->wrapperGroup; +} + +void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) +{ + Q_D(QDeclarativeSmoothedAnimation); + QDeclarativeNumberAnimation::transition(actions, modified, direction); + + if (!d->actions) + return; + + QSet<QAbstractAnimation*> anims; + for (int i = 0; i < d->actions->size(); i++) { + QSmoothedAnimation *ease; + qreal trackVelocity; + bool needsRestart; + if (!d->activeAnimations.contains((*d->actions)[i].property)) { + ease = new QSmoothedAnimation(); + d->wrapperGroup->addAnimation(ease); + d->activeAnimations.insert((*d->actions)[i].property, ease); + trackVelocity = 0.0; + needsRestart = false; + } else { + ease = d->activeAnimations.value((*d->actions)[i].property); + trackVelocity = ease->trackVelocity; + needsRestart = true; + } + + ease->target = (*d->actions)[i].property; + ease->to = (*d->actions)[i].toValue.toReal(); + + // copying public members from main value holder animation + ease->maximumEasingTime = d->anim->maximumEasingTime; + ease->reversingMode = d->anim->reversingMode; + ease->velocity = d->anim->velocity; + ease->userDuration = d->anim->userDuration; + + ease->trackVelocity = trackVelocity; + ease->initialVelocity = trackVelocity; + + if (needsRestart) + ease->init(); + anims.insert(ease); + } + + for (int i = d->wrapperGroup->animationCount() - 1; i >= 0 ; --i) { + if (!anims.contains(d->wrapperGroup->animationAt(i))) { + QSmoothedAnimation *ease = static_cast<QSmoothedAnimation*>(d->wrapperGroup->animationAt(i)); + d->activeAnimations.remove(ease->target); + d->wrapperGroup->takeAnimation(i); + delete ease; + } + } +} + +/*! + \qmlproperty enumeration SmoothedAnimation::reversingMode + + Sets how the SmoothedAnimation behaves if an animation direction is reversed. + + If reversing mode is \c Eased, the animation will smoothly decelerate, and + then reverse direction. If the reversing mode is \c Immediate, the + animation will immediately begin accelerating in the reverse direction, + begining with a velocity of 0. If the reversing mode is \c Sync, the + property is immediately set to the target value. +*/ +QDeclarativeSmoothedAnimation::ReversingMode QDeclarativeSmoothedAnimation::reversingMode() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return (QDeclarativeSmoothedAnimation::ReversingMode) d->anim->reversingMode; +} + +void QDeclarativeSmoothedAnimation::setReversingMode(ReversingMode m) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (d->anim->reversingMode == m) + return; + + d->anim->reversingMode = m; + emit reversingModeChanged(); +} + +/*! + \qmlproperty int SmoothedAnimation::duration + + This property holds the animation duration, in msecs, used when tracking the source. + + Setting this to -1 (the default) disables the duration value. +*/ +int QDeclarativeSmoothedAnimation::duration() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->userDuration; +} + +void QDeclarativeSmoothedAnimation::setDuration(int duration) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (duration != -1) + QDeclarativeNumberAnimation::setDuration(duration); + d->anim->userDuration = duration; +} + +qreal QDeclarativeSmoothedAnimation::velocity() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->velocity; +} + +/*! + \qmlproperty qreal SmoothedAnimation::velocity + + This property holds the average velocity allowed when tracking the 'to' value. + + The default velocity of SmoothedAnimation is 200 units/second. + + Setting this to -1 disables the velocity value. +*/ +void QDeclarativeSmoothedAnimation::setVelocity(qreal v) +{ + Q_D(QDeclarativeSmoothedAnimation); + if (d->anim->velocity == v) + return; + + d->anim->velocity = v; + emit velocityChanged(); +} + +/*! +\qmlproperty qreal SmoothedAnimation::maximumEasingTime + +This property specifies the maximum time, in msecs, an "eases" during the follow should take. +Setting this property causes the velocity to "level out" after at a time. Setting +a negative value reverts to the normal mode of easing over the entire animation +duration. + +The default value is -1. +*/ +int QDeclarativeSmoothedAnimation::maximumEasingTime() const +{ + Q_D(const QDeclarativeSmoothedAnimation); + return d->anim->maximumEasingTime; +} + +void QDeclarativeSmoothedAnimation::setMaximumEasingTime(int v) +{ + Q_D(QDeclarativeSmoothedAnimation); + d->anim->maximumEasingTime = v; + emit maximumEasingTimeChanged(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeeasefollow_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h index 83d1eff..50ed00c 100644 --- a/src/declarative/util/qdeclarativeeasefollow_p.h +++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h @@ -39,11 +39,11 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEEASEFOLLOW_H -#define QDECLARATIVEEASEFOLLOW_H +#ifndef QDECLARATIVESMOOTHEDANIMATION_H +#define QDECLARATIVESMOOTHEDANIMATION_H #include <qdeclarative.h> -#include <qdeclarativepropertyvaluesource.h> +#include "qdeclarativeanimation_p.h" #include <QtCore/qobject.h> @@ -54,61 +54,51 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeProperty; -class QDeclarativeEaseFollowPrivate; -class Q_DECLARATIVE_EXPORT QDeclarativeEaseFollow : public QObject, - public QDeclarativePropertyValueSource +class QDeclarativeSmoothedAnimationPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation { Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeEaseFollow) - Q_INTERFACES(QDeclarativePropertyValueSource) + Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation) Q_ENUMS(ReversingMode) - Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue NOTIFY sourceChanged) Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged) - Q_PROPERTY(qreal duration READ duration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged) public: enum ReversingMode { Eased, Immediate, Sync }; - QDeclarativeEaseFollow(QObject *parent = 0); - ~QDeclarativeEaseFollow(); + QDeclarativeSmoothedAnimation(QObject *parent = 0); + ~QDeclarativeSmoothedAnimation(); ReversingMode reversingMode() const; void setReversingMode(ReversingMode); - qreal sourceValue() const; - void setSourceValue(qreal); + virtual int duration() const; + virtual void setDuration(int); qreal velocity() const; void setVelocity(qreal); - qreal duration() const; - void setDuration(qreal); + int maximumEasingTime() const; + void setMaximumEasingTime(int); - bool enabled() const; - void setEnabled(bool enabled); - - qreal maximumEasingTime() const; - void setMaximumEasingTime(qreal); - - virtual void setTarget(const QDeclarativeProperty &); +public: + virtual void transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction); + QAbstractAnimation* qtAnimation(); Q_SIGNALS: - void sourceChanged(); void velocityChanged(); - void durationChanged(); void reversingModeChanged(); - void enabledChanged(); void maximumEasingTimeChanged(); }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeEaseFollow); +QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation); QT_END_HEADER -#endif // QDECLARATIVEEASEFOLLOW_H +#endif // QDECLARATIVESMOOTHEDANIMATION_H diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h new file mode 100644 index 0000000..bdceeb3 --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESMOOTHEDANIMATION_P_H +#define QDECLARATIVESMOOTHEDANIMATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qdeclarativesmoothedanimation_p.h" +#include "qdeclarativeanimation_p.h" + +#include "qdeclarativeanimation_p_p.h" + +#include <qparallelanimationgroup.h> + +#include <private/qobject_p.h> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QSmoothedAnimation : public QAbstractAnimation +{ +public: + QSmoothedAnimation(QObject *parent=0); + + qreal to; + qreal velocity; + int userDuration; + + int maximumEasingTime; + QDeclarativeSmoothedAnimation::ReversingMode reversingMode; + + qreal initialVelocity; + qreal trackVelocity; + + QDeclarativeProperty target; + + int duration() const; + void restart(); + void init(); + +protected: + virtual void updateCurrentTime(int); + virtual void updateState(QAbstractAnimation::State, QAbstractAnimation::State); + +private: + qreal easeFollow(qreal); + qreal initialValue; + + bool invert; + + int finalDuration; + + // Parameters for use in updateCurrentTime() + qreal a; // Acceleration + qreal d; // Deceleration + qreal tf; // Total time + qreal tp; // Time at which peak velocity occurs + qreal td; // Time at which decelleration begins + qreal vp; // Velocity at tp + qreal sp; // Displacement at tp + qreal sd; // Displacement at td + qreal vi; // "Normalized" initialvelocity + qreal s; // Total s + + int lastTime; + + bool recalc(); + void delayedStop(); + + QTimer delayedStopTimer; +}; + +class QDeclarativeSmoothedAnimationPrivate : public QDeclarativePropertyAnimationPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeSmoothedAnimation) +public: + QDeclarativeSmoothedAnimationPrivate(); + + QParallelAnimationGroup *wrapperGroup; + QSmoothedAnimation *anim; + QHash<QDeclarativeProperty, QSmoothedAnimation*> activeAnimations; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVESMOOTHEDANIMATION_P_H diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringfollow.cpp index 76d7c98..063c3df 100644 --- a/src/declarative/util/qdeclarativespringfollow.cpp +++ b/src/declarative/util/qdeclarativespringfollow.cpp @@ -242,8 +242,6 @@ void QDeclarativeSpringFollowPrivate::stop() SpringFollow on y { source: rect1.y; velocity: 200 } } \endcode - - \sa EaseFollow */ QDeclarativeSpringFollow::QDeclarativeSpringFollow(QObject *parent) diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp index 4326a55..1e8be7f 100644 --- a/src/declarative/util/qdeclarativetransition.cpp +++ b/src/declarative/util/qdeclarativetransition.cpp @@ -116,9 +116,9 @@ void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QD void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { QParallelAnimationGroup::updateState(newState, oldState); - if (newState == Stopped && - ((direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) || - (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0))) + if (newState == Stopped && (duration() == -1 + || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) + || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0))) { trans->complete(); } diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 2a02ffe..7f2f64a 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -45,7 +45,7 @@ #include "qdeclarativebehavior_p.h" #include "qdeclarativebind_p.h" #include "qdeclarativeconnections_p.h" -#include "qdeclarativeeasefollow_p.h" +#include "qdeclarativesmoothedanimation_p.h" #include "qdeclarativefontloader_p.h" #include "qdeclarativelistaccessor_p.h" #include "qdeclarativelistmodel_p.h" @@ -111,7 +111,7 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeBind>("Qt",4,6,"Binding"); qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,6,"ColorAnimation"); qmlRegisterType<QDeclarativeConnections>("Qt",4,6,"Connections"); - qmlRegisterType<QDeclarativeEaseFollow>("Qt",4,6,"EaseFollow"); + qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,6,"SmoothedAnimation"); qmlRegisterType<QDeclarativeFontLoader>("Qt",4,6,"FontLoader"); qmlRegisterType<QDeclarativeListElement>("Qt",4,6,"ListElement"); qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,6,"NumberAnimation"); diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index f537806..4163596 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -8,7 +8,7 @@ SOURCES += \ $$PWD/qdeclarativeanimation.cpp \ $$PWD/qdeclarativesystempalette.cpp \ $$PWD/qdeclarativespringfollow.cpp \ - $$PWD/qdeclarativeeasefollow.cpp \ + $$PWD/qdeclarativesmoothedanimation.cpp \ $$PWD/qdeclarativestate.cpp\ $$PWD/qdeclarativetransitionmanager.cpp \ $$PWD/qdeclarativestateoperations.cpp \ @@ -37,7 +37,8 @@ HEADERS += \ $$PWD/qdeclarativeanimation_p_p.h \ $$PWD/qdeclarativesystempalette_p.h \ $$PWD/qdeclarativespringfollow_p.h \ - $$PWD/qdeclarativeeasefollow_p.h \ + $$PWD/qdeclarativesmoothedanimation_p.h \ + $$PWD/qdeclarativesmoothedanimation_p_p.h \ $$PWD/qdeclarativestate_p.h\ $$PWD/qdeclarativestateoperations_p.h \ $$PWD/qdeclarativepropertychanges_p.h \ |