diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2012-02-03 12:26:37 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-07 05:32:47 +0100 |
commit | ce3dee765c858a0b573d468ef8fee6b838e576d1 (patch) | |
tree | b7026a061b0b58bac6af30eaab6e610c5ebeb504 /src/quick | |
parent | 0ca9d3f0f720e1933379ef40bc5c29253e21cba0 (diff) |
Add and use new animation backend.
The new backend improves performance, and allows us to create
multiple running animation jobs from a single Transition. It is
based off of the existing Qt animation framework.
Change-Id: Id1d0162f6e5c65bf31267f3f9f2042c354375d57
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
Diffstat (limited to 'src/quick')
29 files changed, 1363 insertions, 759 deletions
diff --git a/src/quick/items/qquickanimation.cpp b/src/quick/items/qquickanimation.cpp index 3c9e93d4fd..baf1c8dc45 100644 --- a/src/quick/items/qquickanimation.cpp +++ b/src/quick/items/qquickanimation.cpp @@ -48,8 +48,8 @@ #include <QtDeclarative/qdeclarativeinfo.h> #include <QtCore/qmath.h> -#include <QtCore/qsequentialanimationgroup.h> -#include <QtCore/qparallelanimationgroup.h> +#include "private/qsequentialanimationgroupjob_p.h" +#include "private/qparallelanimationgroupjob_p.h" #include <QtGui/qtransform.h> QT_BEGIN_NAMESPACE @@ -95,21 +95,6 @@ QT_BEGIN_NAMESPACE QQuickParentAnimation::QQuickParentAnimation(QObject *parent) : QDeclarativeAnimationGroup(*(new QQuickParentAnimationPrivate), parent) { - Q_D(QQuickParentAnimation); - d->topLevelGroup = new QSequentialAnimationGroup; - QDeclarative_setParent_noEvent(d->topLevelGroup, this); - - d->startAction = new QActionAnimation; - QDeclarative_setParent_noEvent(d->startAction, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->startAction); - - d->ag = new QParallelAnimationGroup; - QDeclarative_setParent_noEvent(d->ag, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->ag); - - d->endAction = new QActionAnimation; - QDeclarative_setParent_noEvent(d->endAction, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->endAction); } QQuickParentAnimation::~QQuickParentAnimation() @@ -219,7 +204,7 @@ QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::Transfo } } -void QQuickParentAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QQuickParentAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { @@ -385,33 +370,46 @@ void QQuickParentAnimation::transition(QDeclarativeStateActions &actions, } } + QSequentialAnimationGroupJob *topLevelGroup = new QSequentialAnimationGroupJob; + QActionAnimation *viaAction = d->via ? new QActionAnimation : 0; + QActionAnimation *targetAction = new QActionAnimation; + //we'll assume the common case by far is to have children, and always create ag + QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob; + if (data->actions.count()) { - if (direction == QDeclarativeAbstractAnimation::Forward) { - d->startAction->setAnimAction(d->via ? viaData : data, QActionAnimation::DeleteWhenStopped); - d->endAction->setAnimAction(d->via ? data : 0, QActionAnimation::DeleteWhenStopped); + if (d->via) + viaAction->setAnimAction(viaData); + targetAction->setAnimAction(data); + + //take care of any child animations + bool valid = d->defaultProperty.isValid(); + QAbstractAnimationJob* anim; + for (int ii = 0; ii < d->animations.count(); ++ii) { + if (valid) + d->animations.at(ii)->setDefaultTarget(d->defaultProperty); + anim = d->animations.at(ii)->transition(actions, modified, direction); + ag->appendAnimation(anim); + } + + //TODO: simplify/clarify logic + bool forwards = direction == QDeclarativeAbstractAnimation::Forward; + if (forwards) { + topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); + topLevelGroup->appendAnimation(ag); + if (d->via) + topLevelGroup->appendAnimation(targetAction); } else { - d->endAction->setAnimAction(d->via ? viaData : data, QActionAnimation::DeleteWhenStopped); - d->startAction->setAnimAction(d->via ? data : 0, QActionAnimation::DeleteWhenStopped); + if (d->via) + topLevelGroup->appendAnimation(targetAction); + topLevelGroup->appendAnimation(ag); + topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); } } else { delete data; delete viaData; } - //take care of any child animations - bool valid = d->defaultProperty.isValid(); - for (int ii = 0; ii < d->animations.count(); ++ii) { - if (valid) - d->animations.at(ii)->setDefaultTarget(d->defaultProperty); - d->animations.at(ii)->transition(actions, modified, direction); - } - -} - -QAbstractAnimation *QQuickParentAnimation::qtAnimation() -{ - Q_D(QQuickParentAnimation); - return d->topLevelGroup; + return initInstance(topLevelGroup); } /*! @@ -442,21 +440,12 @@ QAbstractAnimation *QQuickParentAnimation::qtAnimation() QQuickAnchorAnimation::QQuickAnchorAnimation(QObject *parent) : QDeclarativeAbstractAnimation(*(new QQuickAnchorAnimationPrivate), parent) { - Q_D(QQuickAnchorAnimation); - d->va = new QDeclarativeBulkValueAnimator; - QDeclarative_setParent_noEvent(d->va, this); } QQuickAnchorAnimation::~QQuickAnchorAnimation() { } -QAbstractAnimation *QQuickAnchorAnimation::qtAnimation() -{ - Q_D(QQuickAnchorAnimation); - return d->va; -} - /*! \qmlproperty list<Item> QtQuick2::AnchorAnimation::targets The items to reanchor. @@ -479,7 +468,7 @@ QDeclarativeListProperty<QQuickItem> QQuickAnchorAnimation::targets() int QQuickAnchorAnimation::duration() const { Q_D(const QQuickAnchorAnimation); - return d->va->duration(); + return d->duration; } void QQuickAnchorAnimation::setDuration(int duration) @@ -490,9 +479,9 @@ void QQuickAnchorAnimation::setDuration(int duration) } Q_D(QQuickAnchorAnimation); - if (d->va->duration() == duration) + if (d->duration == duration) return; - d->va->setDuration(duration); + d->duration = duration; emit durationChanged(duration); } @@ -517,20 +506,20 @@ void QQuickAnchorAnimation::setDuration(int duration) QEasingCurve QQuickAnchorAnimation::easing() const { Q_D(const QQuickAnchorAnimation); - return d->va->easingCurve(); + return d->easing; } void QQuickAnchorAnimation::setEasing(const QEasingCurve &e) { Q_D(QQuickAnchorAnimation); - if (d->va->easingCurve() == e) + if (d->easing == e) return; - d->va->setEasingCurve(e); + d->easing = e; emit easingChanged(e); } -void QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { @@ -539,7 +528,6 @@ void QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeAnimationPropertyUpdater *data = new QDeclarativeAnimationPropertyUpdater; data->interpolatorType = QMetaType::QReal; data->interpolator = d->interpolator; - data->reverse = direction == Backward ? true : false; data->fromSourced = false; data->fromDefined = false; @@ -552,17 +540,15 @@ void QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, } } + QDeclarativeBulkValueAnimator *animator = new QDeclarativeBulkValueAnimator; if (data->actions.count()) { - if (!d->rangeIsSet) { - d->va->setStartValue(qreal(0)); - d->va->setEndValue(qreal(1)); - d->rangeIsSet = true; - } - d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); - d->va->setFromSourcedValue(&data->fromSourced); + animator->setAnimValue(data); + animator->setFromSourcedValue(&data->fromSourced); } else { delete data; } + + return initInstance(animator); } /*! @@ -593,13 +579,15 @@ void QQuickAnchorAnimation::transition(QDeclarativeStateActions &actions, QQuickPathAnimation::QQuickPathAnimation(QObject *parent) : QDeclarativeAbstractAnimation(*(new QQuickPathAnimationPrivate), parent) { - Q_D(QQuickPathAnimation); - d->pa = new QDeclarativeBulkValueAnimator; - QDeclarative_setParent_noEvent(d->pa, this); } QQuickPathAnimation::~QQuickPathAnimation() { + Q_D(QQuickPathAnimation); + QHash<QQuickItem*, QQuickPathAnimationAnimator* >::iterator it; + for (it = d->activeAnimations.begin(); it != d->activeAnimations.end(); ++it) { + it.value()->clearTemplate(); + } } /*! @@ -611,7 +599,7 @@ QQuickPathAnimation::~QQuickPathAnimation() int QQuickPathAnimation::duration() const { Q_D(const QQuickPathAnimation); - return d->pa->duration(); + return d->duration; } void QQuickPathAnimation::setDuration(int duration) @@ -622,9 +610,9 @@ void QQuickPathAnimation::setDuration(int duration) } Q_D(QQuickPathAnimation); - if (d->pa->duration() == duration) + if (d->duration == duration) return; - d->pa->setDuration(duration); + d->duration = duration; emit durationChanged(duration); } @@ -645,16 +633,16 @@ void QQuickPathAnimation::setDuration(int duration) QEasingCurve QQuickPathAnimation::easing() const { Q_D(const QQuickPathAnimation); - return d->pa->easingCurve(); + return d->easingCurve; } void QQuickPathAnimation::setEasing(const QEasingCurve &e) { Q_D(QQuickPathAnimation); - if (d->pa->easingCurve() == e) + if (d->easingCurve == e) return; - d->pa->setEasingCurve(e); + d->easingCurve = e; emit easingChanged(e); } @@ -833,24 +821,37 @@ void QQuickPathAnimation::setEndRotation(qreal rotation) emit endRotationChanged(d->endRotation); } - -QAbstractAnimation *QQuickPathAnimation::qtAnimation() -{ - Q_D(QQuickPathAnimation); - return d->pa; -} - -void QQuickPathAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QQuickPathAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { Q_D(QQuickPathAnimation); - QQuickPathAnimationUpdater *data = new QQuickPathAnimationUpdater; + + QQuickPathAnimationUpdater prevData; + bool havePrevData = false; + if (d->activeAnimations.contains(d->target)) { + havePrevData = true; + prevData = *d->activeAnimations[d->target]->pathUpdater(); + } + + QList<QQuickItem*> keys = d->activeAnimations.keys(); + foreach (QQuickItem *item, keys) { + QQuickPathAnimationAnimator *anim = d->activeAnimations.value(item); + if (anim->state() == QAbstractAnimationJob::Stopped) { + anim->clearTemplate(); + d->activeAnimations.remove(item); + } + } + + QQuickPathAnimationUpdater *data = new QQuickPathAnimationUpdater(); + QQuickPathAnimationAnimator *pa = new QQuickPathAnimationAnimator(d); + + d->activeAnimations[d->target] = pa; data->orientation = d->orientation; data->anchorPoint = d->anchorPoint; - data->entryInterval = duration() ? qreal(d->entryDuration) / duration() : qreal(0); - data->exitInterval = duration() ? qreal(d->exitDuration) / duration() : qreal(0); + data->entryInterval = d->duration ? qreal(d->entryDuration) / d->duration : qreal(0); + data->exitInterval = d->duration ? qreal(d->exitDuration) / d->duration : qreal(0); data->endRotation = d->endRotation; data->reverse = direction == Backward ? true : false; data->fromSourced = false; @@ -879,46 +880,41 @@ void QQuickPathAnimation::transition(QDeclarativeStateActions &actions, data->target = d->target; data->path = d->path; data->path->invalidateSequentialHistory(); - if (!d->rangeIsSet) { - d->pa->setStartValue(qreal(0)); - d->pa->setEndValue(qreal(1)); - d->rangeIsSet = true; - } - /* - NOTE: The following block relies on the fact that the previous value hasn't - yet been deleted, and has the same target, etc, which may be a bit fragile. - */ - if (d->pa->getAnimValue()) { - QQuickPathAnimationUpdater *prevData = static_cast<QQuickPathAnimationUpdater*>(d->pa->getAnimValue()); + if (havePrevData) { // get the original start angle that was used (so we can exactly reverse). - data->startRotation = prevData->startRotation; + data->startRotation = prevData.startRotation; // treat interruptions specially, otherwise we end up with strange paths - if ((data->reverse || prevData->reverse) && prevData->currentV > 0 && prevData->currentV < 1) { - if (!data->fromDefined && !data->toDefined && !prevData->painterPath.isEmpty()) { - QPointF pathPos = QDeclarativePath::sequentialPointAt(prevData->painterPath, prevData->pathLength, prevData->attributePoints, prevData->prevBez, prevData->currentV); - if (!prevData->anchorPoint.isNull()) - pathPos -= prevData->anchorPoint; + if ((data->reverse || prevData.reverse) && prevData.currentV > 0 && prevData.currentV < 1) { + if (!data->fromDefined && !data->toDefined && !prevData.painterPath.isEmpty()) { + QPointF pathPos = QDeclarativePath::sequentialPointAt(prevData.painterPath, prevData.pathLength, prevData.attributePoints, prevData.prevBez, prevData.currentV); + if (!prevData.anchorPoint.isNull()) + pathPos -= prevData.anchorPoint; if (pathPos == data->target->pos()) { //only treat as interruption if we interrupted ourself - data->painterPath = prevData->painterPath; + data->painterPath = prevData.painterPath; data->toDefined = data->fromDefined = data->fromSourced = true; data->prevBez.isValid = false; - data->interruptStart = prevData->currentV; - data->startRotation = prevData->startRotation; - data->pathLength = prevData->pathLength; - data->attributePoints = prevData->attributePoints; + data->interruptStart = prevData.currentV; + data->startRotation = prevData.startRotation; + data->pathLength = prevData.pathLength; + data->attributePoints = prevData.attributePoints; } } } } - d->pa->setFromSourcedValue(&data->fromSourced); - d->pa->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); + pa->setFromSourcedValue(&data->fromSourced); + pa->setAnimValue(data); } else { - d->pa->setFromSourcedValue(0); - d->pa->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped); + pa->setFromSourcedValue(0); + pa->setAnimValue(0); + delete pa; delete data; } + + pa->setDuration(d->duration); + pa->setEasingCurve(d->easingCurve); + return initInstance(pa); } void QQuickPathAnimationUpdater::setValue(qreal v) @@ -955,9 +951,7 @@ void QQuickPathAnimationUpdater::setValue(qreal v) } } - //### could cache properties rather than reconstructing each time - QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, QStringLiteral("x")), currentPos.x(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); - QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, QStringLiteral("y")), currentPos.y(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + target->setPos(currentPos); //adjust angle according to orientation if (!fixed) { @@ -1009,7 +1003,7 @@ void QQuickPathAnimationUpdater::setValue(qreal v) else if (v > exitStart) angle = endRotation * (v - exitStart) / exitInterval + angle * (exitInterval - (v - exitStart)) / exitInterval; } - QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, QStringLiteral("rotation")), angle, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + target->setRotation(angle); } /* @@ -1024,4 +1018,19 @@ void QQuickPathAnimationUpdater::setValue(qreal v) } } +QQuickPathAnimationAnimator::QQuickPathAnimationAnimator(QQuickPathAnimationPrivate *priv) + : animationTemplate(priv) +{ +} + +QQuickPathAnimationAnimator::~QQuickPathAnimationAnimator() +{ + if (animationTemplate && pathUpdater()) { + QHash<QQuickItem*, QQuickPathAnimationAnimator* >::iterator it = + animationTemplate->activeAnimations.find(pathUpdater()->target); + if (it != animationTemplate->activeAnimations.end() && it.value() == this) + animationTemplate->activeAnimations.erase(it); + } +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickanimation_p.h b/src/quick/items/qquickanimation_p.h index e16c6fb0a9..924fe5d35f 100644 --- a/src/quick/items/qquickanimation_p.h +++ b/src/quick/items/qquickanimation_p.h @@ -47,14 +47,12 @@ #include <QtQuick/private/qdeclarativeanimation_p.h> -#include <QtCore/qabstractanimation.h> - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QQuickParentAnimationPrivate; -class QQuickParentAnimation : public QDeclarativeAnimationGroup +class Q_QUICK_PRIVATE_EXPORT QQuickParentAnimation : public QDeclarativeAnimationGroup { Q_OBJECT Q_DECLARE_PRIVATE(QQuickParentAnimation) @@ -82,14 +80,13 @@ Q_SIGNALS: void viaChanged(); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; class QQuickAnchorAnimationPrivate; -class QQuickAnchorAnimation : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QQuickAnchorAnimation : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QQuickAnchorAnimation) @@ -114,16 +111,15 @@ Q_SIGNALS: void easingChanged(const QEasingCurve&); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; class QQuickItem; class QDeclarativePath; class QQuickPathAnimationPrivate; -class Q_AUTOTEST_EXPORT QQuickPathAnimation : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QQuickPathAnimation : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QQuickPathAnimation) @@ -179,11 +175,9 @@ public: void setEndRotation(qreal); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); - Q_SIGNALS: void durationChanged(int); void easingChanged(const QEasingCurve &); diff --git a/src/quick/items/qquickanimation_p_p.h b/src/quick/items/qquickanimation_p_p.h index 576abbac99..2e6157c140 100644 --- a/src/quick/items/qquickanimation_p_p.h +++ b/src/quick/items/qquickanimation_p_p.h @@ -65,18 +65,13 @@ class QQuickParentAnimationPrivate : public QDeclarativeAnimationGroupPrivate { Q_DECLARE_PUBLIC(QQuickParentAnimation) public: - QQuickParentAnimationPrivate() - : QDeclarativeAnimationGroupPrivate(), target(0), newParent(0), - via(0), topLevelGroup(0), startAction(0), endAction(0) {} + QQuickParentAnimationPrivate() + : QDeclarativeAnimationGroupPrivate(), target(0), newParent(0), via(0) {} QQuickItem *target; QQuickItem *newParent; QQuickItem *via; - QSequentialAnimationGroup *topLevelGroup; - QActionAnimation *startAction; - QActionAnimation *endAction; - QPointF computeTransformOrigin(QQuickItem::TransformOrigin origin, qreal width, qreal height) const; }; @@ -84,12 +79,11 @@ class QQuickAnchorAnimationPrivate : public QDeclarativeAbstractAnimationPrivate { Q_DECLARE_PUBLIC(QQuickAnchorAnimation) public: - QQuickAnchorAnimationPrivate() : rangeIsSet(false), va(0), - interpolator(QVariantAnimationPrivate::getInterpolator(QMetaType::QReal)) {} + QQuickAnchorAnimationPrivate() : interpolator(QVariantAnimationPrivate::getInterpolator(QMetaType::QReal)), duration(250) {} - bool rangeIsSet; - QDeclarativeBulkValueAnimator *va; QVariantAnimation::Interpolator interpolator; + int duration; + QEasingCurve easing; QList<QQuickItem*> targets; }; @@ -102,7 +96,7 @@ public: entryInterval(0), exitInterval(0) {} ~QQuickPathAnimationUpdater() {} - void setValue(qreal v); + void setValue(qreal v); QDeclarativePath *path; @@ -129,22 +123,37 @@ public: QDeclarativeNullableValue<qreal> startRotation; }; +class QQuickPathAnimationPrivate; +class QQuickPathAnimationAnimator : public QDeclarativeBulkValueAnimator +{ +public: + QQuickPathAnimationAnimator(QQuickPathAnimationPrivate * = 0); + ~QQuickPathAnimationAnimator(); + + void clearTemplate() { animationTemplate = 0; } + + QQuickPathAnimationUpdater *pathUpdater() { return static_cast<QQuickPathAnimationUpdater*>(getAnimValue()); } +private: + QQuickPathAnimationPrivate *animationTemplate; +}; + class QQuickPathAnimationPrivate : public QDeclarativeAbstractAnimationPrivate { Q_DECLARE_PUBLIC(QQuickPathAnimation) public: QQuickPathAnimationPrivate() : path(0), target(0), - rangeIsSet(false), orientation(QQuickPathAnimation::Fixed), entryDuration(0), exitDuration(0), pa(0) {} + orientation(QQuickPathAnimation::Fixed), entryDuration(0), exitDuration(0), duration(250) {} QDeclarativePath *path; QQuickItem *target; - bool rangeIsSet; QQuickPathAnimation::Orientation orientation; QPointF anchorPoint; qreal entryDuration; qreal exitDuration; QDeclarativeNullableValue<qreal> endRotation; - QDeclarativeBulkValueAnimator *pa; + int duration; + QEasingCurve easingCurve; + QHash<QQuickItem*, QQuickPathAnimationAnimator* > activeAnimations; }; diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 80ab2ac55a..522c09ae54 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -217,6 +217,11 @@ public: , snapMode(QQuickGridView::NoSnap) , highlightXAnimator(0), highlightYAnimator(0) {} + ~QQuickGridViewPrivate() + { + delete highlightXAnimator; + delete highlightYAnimator; + } }; Qt::Orientation QQuickGridViewPrivate::layoutOrientation() const @@ -639,10 +644,10 @@ void QQuickGridViewPrivate::createHighlight() FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true); if (autoHighlight) resetHighlightPosition(); - highlightXAnimator = new QSmoothedAnimation(q); + highlightXAnimator = new QSmoothedAnimation; highlightXAnimator->target = QDeclarativeProperty(item, QLatin1String("x")); highlightXAnimator->userDuration = highlightMoveDuration; - highlightYAnimator = new QSmoothedAnimation(q); + highlightYAnimator = new QSmoothedAnimation; highlightYAnimator->target = QDeclarativeProperty(item, QLatin1String("y")); highlightYAnimator->userDuration = highlightMoveDuration; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 129db0c3cf..424edc5843 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -168,6 +168,10 @@ public: , sectionCriteria(0), currentSectionItem(0), nextSectionItem(0) , overshootDist(0.0), correctFlick(false), inFlickCorrection(false) {} + ~QQuickListViewPrivate() { + delete highlightPosAnimator; + delete highlightSizeAnimator; + } friend class QQuickViewSection; }; @@ -787,13 +791,13 @@ void QQuickListViewPrivate::createHighlight() newHighlight->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition()); } const QLatin1String posProp(orient == QQuickListView::Vertical ? "y" : "x"); - highlightPosAnimator = new QSmoothedAnimation(q); + highlightPosAnimator = new QSmoothedAnimation; highlightPosAnimator->target = QDeclarativeProperty(item, posProp); highlightPosAnimator->velocity = highlightMoveSpeed; highlightPosAnimator->userDuration = highlightMoveDuration; const QLatin1String sizeProp(orient == QQuickListView::Vertical ? "height" : "width"); - highlightSizeAnimator = new QSmoothedAnimation(q); + highlightSizeAnimator = new QSmoothedAnimation; highlightSizeAnimator->velocity = highlightResizeSpeed; highlightSizeAnimator->userDuration = highlightResizeDuration; highlightSizeAnimator->target = QDeclarativeProperty(item, sizeProp); diff --git a/src/quick/particles/qquickitemparticle.cpp b/src/quick/particles/qquickitemparticle.cpp index 9c0e4624c1..db9e3d1519 100644 --- a/src/quick/particles/qquickitemparticle.cpp +++ b/src/quick/particles/qquickitemparticle.cpp @@ -103,10 +103,14 @@ QQuickItemParticle::QQuickItemParticle(QQuickItem *parent) : QQuickParticlePainter(parent), m_fade(true), m_delegate(0) { setFlag(QQuickItem::ItemHasContents); - clock = new Clock(this, this); + clock = new Clock(this); clock->start(); } +QQuickItemParticle::~QQuickItemParticle() +{ + delete clock; +} void QQuickItemParticle::freeze(QQuickItem* item) { diff --git a/src/quick/particles/qquickitemparticle_p.h b/src/quick/particles/qquickitemparticle_p.h index 8bc01b6009..df104a5644 100644 --- a/src/quick/particles/qquickitemparticle_p.h +++ b/src/quick/particles/qquickitemparticle_p.h @@ -59,6 +59,7 @@ class QQuickItemParticle : public QQuickParticlePainter Q_PROPERTY(QDeclarativeComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) public: explicit QQuickItemParticle(QQuickItem *parent = 0); + ~QQuickItemParticle(); bool fade() const { return m_fade; } diff --git a/src/quick/util/qdeclarativeanimation.cpp b/src/quick/util/qdeclarativeanimation.cpp index 2e09fc8d9d..9f6421b657 100644 --- a/src/quick/util/qdeclarativeanimation.cpp +++ b/src/quick/util/qdeclarativeanimation.cpp @@ -59,16 +59,14 @@ #include <qvariant.h> #include <qcolor.h> #include <qfile.h> -#include <QParallelAnimationGroup> -#include <QSequentialAnimationGroup> +#include "private/qparallelanimationgroupjob_p.h" +#include "private/qsequentialanimationgroupjob_p.h" #include <QtCore/qset.h> #include <QtCore/qrect.h> #include <QtCore/qpoint.h> #include <QtCore/qsize.h> #include <QtCore/qmath.h> -#include <private/qvariantanimation_p.h> - QT_BEGIN_NAMESPACE /*! @@ -90,6 +88,8 @@ QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QObject *parent) QDeclarativeAbstractAnimation::~QDeclarativeAbstractAnimation() { + Q_D(QDeclarativeAbstractAnimation); + delete d->animationInstance; } QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QDeclarativeAbstractAnimationPrivate &dd, QObject *parent) @@ -97,6 +97,12 @@ QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QDeclarativeAbstrac { } +QAbstractAnimationJob* QDeclarativeAbstractAnimation::qtAnimation() +{ + Q_D(QDeclarativeAbstractAnimation); + return d->animationInstance; +} + /*! \qmlproperty bool QtQuick2::Animation::running This property holds whether the animation is currently running. @@ -155,10 +161,16 @@ void QDeclarativeAbstractAnimationPrivate::commence() QDeclarativeStateActions actions; QDeclarativeProperties properties; - q->transition(actions, properties, QDeclarativeAbstractAnimation::Forward); - q->qtAnimation()->start(); - if (q->qtAnimation()->state() == QAbstractAnimation::Stopped) { + QAbstractAnimationJob *oldInstance = animationInstance; + animationInstance = q->transition(actions, properties, QDeclarativeAbstractAnimation::Forward); + if (oldInstance != animationInstance) { + animationInstance->addAnimationChangeListener(this, QAbstractAnimationJob::Completion); + if (oldInstance) + delete oldInstance; + } + animationInstance->start(); + if (animationInstance->isStopped()) { running = false; emit q->completed(); } @@ -187,7 +199,10 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) else if (!d->registered) { d->registered = true; QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this)); - engPriv->registerFinalizeCallback(this, this->metaObject()->indexOfSlot("componentFinalized()")); + static int finalizedIdx = -1; + if (finalizedIdx < 0) + finalizedIdx = metaObject()->indexOfSlot("componentFinalized()"); + engPriv->registerFinalizeCallback(this, finalizedIdx); } return; } @@ -204,29 +219,26 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) if (d->running) { bool supressStart = false; if (d->alwaysRunToEnd && d->loopCount != 1 - && qtAnimation()->state() == QAbstractAnimation::Running) { + && d->animationInstance && d->animationInstance->isRunning()) { //we've restarted before the final loop finished; restore proper loop count if (d->loopCount == -1) - qtAnimation()->setLoopCount(d->loopCount); + d->animationInstance->setLoopCount(d->loopCount); else - qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount); + d->animationInstance->setLoopCount(d->animationInstance->currentLoop() + d->loopCount); supressStart = true; //we want the animation to continue, rather than restart } - - if (!d->connectedTimeLine) { - FAST_CONNECT(qtAnimation(), SIGNAL(finished()), this, SLOT(timelineComplete())) - d->connectedTimeLine = true; - } if (!supressStart) d->commence(); emit started(); } else { - if (d->alwaysRunToEnd) { - if (d->loopCount != 1) - qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); //finish the current loop - } else - qtAnimation()->stop(); - + if (d->animationInstance) { + if (d->alwaysRunToEnd) { + if (d->loopCount != 1) + d->animationInstance->setLoopCount(d->animationInstance->currentLoop()+1); //finish the current loop + } else { + d->animationInstance->stop(); + } + } emit completed(); } @@ -264,13 +276,13 @@ void QDeclarativeAbstractAnimation::setPaused(bool p) d->paused = p; - if (!d->componentComplete) + if (!d->componentComplete || !d->animationInstance) return; if (d->paused) - qtAnimation()->pause(); + d->animationInstance->pause(); else - qtAnimation()->resume(); + d->animationInstance->resume(); emit pausedChanged(d->paused); } @@ -371,19 +383,27 @@ void QDeclarativeAbstractAnimation::setLoops(int loops) return; d->loopCount = loops; - qtAnimation()->setLoopCount(loops); emit loopCountChanged(loops); } +int QDeclarativeAbstractAnimation::duration() const +{ + Q_D(const QDeclarativeAbstractAnimation); + return d->animationInstance ? d->animationInstance->duration() : 0; +} int QDeclarativeAbstractAnimation::currentTime() { - return qtAnimation()->currentLoopTime(); + Q_D(QDeclarativeAbstractAnimation); + return d->animationInstance ? d->animationInstance->currentLoopTime() : 0; } void QDeclarativeAbstractAnimation::setCurrentTime(int time) { - qtAnimation()->setCurrentTime(time); + Q_D(QDeclarativeAbstractAnimation); + if (d->animationInstance) + d->animationInstance->setCurrentTime(time); + //TODO save value for start? } QDeclarativeAnimationGroup *QDeclarativeAbstractAnimation::group() const @@ -503,8 +523,9 @@ void QDeclarativeAbstractAnimation::restart() */ void QDeclarativeAbstractAnimation::complete() { - if (isRunning()) { - qtAnimation()->setCurrentTime(qtAnimation()->duration()); + Q_D(QDeclarativeAbstractAnimation); + if (isRunning() && d->animationInstance) { + d->animationInstance->setCurrentTime(d->animationInstance->duration()); } } @@ -539,22 +560,43 @@ void QDeclarativeAbstractAnimation::setDisableUserControl() d->disableUserControl = true; } -void QDeclarativeAbstractAnimation::transition(QDeclarativeStateActions &actions, +void QDeclarativeAbstractAnimation::setEnableUserControl() +{ + Q_D(QDeclarativeAbstractAnimation); + d->disableUserControl = false; + +} + +bool QDeclarativeAbstractAnimation::userControlDisabled() const +{ + Q_D(const QDeclarativeAbstractAnimation); + return d->disableUserControl; +} + +QAbstractAnimationJob* QDeclarativeAbstractAnimation::initInstance(QAbstractAnimationJob *animation) +{ + Q_D(QDeclarativeAbstractAnimation); + animation->setLoopCount(d->loopCount); + return animation; +} + +QAbstractAnimationJob* QDeclarativeAbstractAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { Q_UNUSED(actions); Q_UNUSED(modified); Q_UNUSED(direction); + return 0; } -void QDeclarativeAbstractAnimation::timelineComplete() +void QDeclarativeAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*) { - Q_D(QDeclarativeAbstractAnimation); - setRunning(false); - if (d->alwaysRunToEnd && d->loopCount != 1) { + Q_Q(QDeclarativeAbstractAnimation); + q->setRunning(false); + if (alwaysRunToEnd && loopCount != 1) { //restore the proper loopCount for the next run - qtAnimation()->setLoopCount(d->loopCount); + animationInstance->setLoopCount(loopCount); } } @@ -582,21 +624,12 @@ void QDeclarativeAbstractAnimation::timelineComplete() QDeclarativePauseAnimation::QDeclarativePauseAnimation(QObject *parent) : QDeclarativeAbstractAnimation(*(new QDeclarativePauseAnimationPrivate), parent) { - Q_D(QDeclarativePauseAnimation); - d->init(); } QDeclarativePauseAnimation::~QDeclarativePauseAnimation() { } -void QDeclarativePauseAnimationPrivate::init() -{ - Q_Q(QDeclarativePauseAnimation); - pa = new QPauseAnimation; - QDeclarative_setParent_noEvent(pa, q); -} - /*! \qmlproperty int QtQuick2::PauseAnimation::duration This property holds the duration of the pause in milliseconds @@ -606,7 +639,7 @@ void QDeclarativePauseAnimationPrivate::init() int QDeclarativePauseAnimation::duration() const { Q_D(const QDeclarativePauseAnimation); - return d->pa->duration(); + return d->duration; } void QDeclarativePauseAnimation::setDuration(int duration) @@ -617,16 +650,22 @@ void QDeclarativePauseAnimation::setDuration(int duration) } Q_D(QDeclarativePauseAnimation); - if (d->pa->duration() == duration) + if (d->duration == duration) return; - d->pa->setDuration(duration); + d->duration = duration; emit durationChanged(duration); } -QAbstractAnimation *QDeclarativePauseAnimation::qtAnimation() +QAbstractAnimationJob* QDeclarativePauseAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) { Q_D(QDeclarativePauseAnimation); - return d->pa; + Q_UNUSED(actions); + Q_UNUSED(modified); + Q_UNUSED(direction); + + return initInstance(new QPauseAnimationJob(d->duration)); } /*! @@ -663,8 +702,8 @@ QDeclarativeColorAnimation::QDeclarativeColorAnimation(QObject *parent) { Q_D(QDeclarativePropertyAnimation); d->interpolatorType = QMetaType::QColor; - d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); d->defaultToInterpolatorType = true; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); } QDeclarativeColorAnimation::~QDeclarativeColorAnimation() @@ -731,7 +770,47 @@ void QDeclarativeColorAnimation::setTo(const QColor &t) QDeclarativePropertyAnimation::setTo(t); } +QActionAnimation::QActionAnimation() + : QAbstractAnimationJob(), animAction(0) +{ +} + +QActionAnimation::QActionAnimation(QAbstractAnimationAction *action) + : QAbstractAnimationJob(), animAction(action) +{ +} + +QActionAnimation::~QActionAnimation() +{ + delete animAction; +} + +int QActionAnimation::duration() const +{ + return 0; +} + +void QActionAnimation::setAnimAction(QAbstractAnimationAction *action) +{ + if (isRunning()) + stop(); + animAction = action; +} + +void QActionAnimation::updateCurrentTime(int) +{ +} +void QActionAnimation::updateState(State newState, State oldState) +{ + Q_UNUSED(oldState); + + if (newState == Running) { + if (animAction) { + animAction->doAction(); + } + } +} /*! \qmlclass ScriptAction QDeclarativeScriptAction @@ -764,20 +843,14 @@ void QDeclarativeColorAnimation::setTo(const QColor &t) QDeclarativeScriptAction::QDeclarativeScriptAction(QObject *parent) :QDeclarativeAbstractAnimation(*(new QDeclarativeScriptActionPrivate), parent) { - Q_D(QDeclarativeScriptAction); - d->init(); } QDeclarativeScriptAction::~QDeclarativeScriptAction() { } -void QDeclarativeScriptActionPrivate::init() -{ - Q_Q(QDeclarativeScriptAction); - rsa = new QActionAnimation(&proxy); - QDeclarative_setParent_noEvent(rsa, q); -} +QDeclarativeScriptActionPrivate::QDeclarativeScriptActionPrivate() + : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false){} /*! \qmlproperty script QtQuick2::ScriptAction::script @@ -817,6 +890,11 @@ void QDeclarativeScriptAction::setStateChangeScriptName(const QString &name) d->name = name; } +QAbstractAnimationAction* QDeclarativeScriptActionPrivate::createAction() +{ + return new Proxy(this); +} + void QDeclarativeScriptActionPrivate::execute() { Q_Q(QDeclarativeScriptAction); @@ -833,7 +911,7 @@ void QDeclarativeScriptActionPrivate::execute() } } -void QDeclarativeScriptAction::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QDeclarativeScriptAction::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { @@ -853,16 +931,9 @@ void QDeclarativeScriptAction::transition(QDeclarativeStateActions &actions, break; //only match one (names should be unique) } } + return initInstance(new QActionAnimation(d->createAction())); } -QAbstractAnimation *QDeclarativeScriptAction::qtAnimation() -{ - Q_D(QDeclarativeScriptAction); - return d->rsa; -} - - - /*! \qmlclass PropertyAction QDeclarativePropertyAction \inqmlmodule QtQuick 2 @@ -906,21 +977,12 @@ QAbstractAnimation *QDeclarativeScriptAction::qtAnimation() QDeclarativePropertyAction::QDeclarativePropertyAction(QObject *parent) : QDeclarativeAbstractAnimation(*(new QDeclarativePropertyActionPrivate), parent) { - Q_D(QDeclarativePropertyAction); - d->init(); } QDeclarativePropertyAction::~QDeclarativePropertyAction() { } -void QDeclarativePropertyActionPrivate::init() -{ - Q_Q(QDeclarativePropertyAction); - spa = new QActionAnimation; - QDeclarative_setParent_noEvent(spa, q); -} - QObject *QDeclarativePropertyAction::target() const { Q_D(const QDeclarativePropertyAction); @@ -1023,13 +1085,7 @@ void QDeclarativePropertyAction::setValue(const QVariant &v) } } -QAbstractAnimation *QDeclarativePropertyAction::qtAnimation() -{ - Q_D(QDeclarativePropertyAction); - return d->spa; -} - -void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { @@ -1117,11 +1173,13 @@ void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions, } } + QActionAnimation *action = new QActionAnimation; if (data->actions.count()) { - d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped); + action->setAnimAction(data); } else { delete data; } + return initInstance(action); } /*! @@ -1258,8 +1316,8 @@ QDeclarativeVector3dAnimation::QDeclarativeVector3dAnimation(QObject *parent) { Q_D(QDeclarativePropertyAnimation); d->interpolatorType = QMetaType::QVector3D; - d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); d->defaultToInterpolatorType = true; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); } QDeclarativeVector3dAnimation::~QDeclarativeVector3dAnimation() @@ -1503,7 +1561,6 @@ void QDeclarativeRotationAnimation::setDirection(QDeclarativeRotationAnimation:: d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); break; } - emit directionChanged(); } @@ -1524,9 +1581,6 @@ void QDeclarativeAnimationGroupPrivate::append_animation(QDeclarativeListPropert QDeclarativeAnimationGroup *q = qobject_cast<QDeclarativeAnimationGroup *>(list->object); if (q) { a->setGroup(q); - // This is an optimization for the parenting that already occurs via addAnimation - QDeclarative_setParent_noEvent(a->qtAnimation(), q->d_func()->ag); - q->d_func()->ag->addAnimation(a->qtAnimation()); } } @@ -1536,8 +1590,6 @@ void QDeclarativeAnimationGroupPrivate::clear_animation(QDeclarativeListProperty if (q) { while (q->d_func()->animations.count()) { QDeclarativeAbstractAnimation *firstAnim = q->d_func()->animations.at(0); - QDeclarative_setParent_noEvent(firstAnim->qtAnimation(), 0); - q->d_func()->ag->removeAnimation(firstAnim->qtAnimation()); firstAnim->setGroup(0); } } @@ -1592,27 +1644,20 @@ QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeAnimationGro QDeclarativeSequentialAnimation::QDeclarativeSequentialAnimation(QObject *parent) : QDeclarativeAnimationGroup(parent) { - Q_D(QDeclarativeAnimationGroup); - d->ag = new QSequentialAnimationGroup; - QDeclarative_setParent_noEvent(d->ag, this); } QDeclarativeSequentialAnimation::~QDeclarativeSequentialAnimation() { } -QAbstractAnimation *QDeclarativeSequentialAnimation::qtAnimation() -{ - Q_D(QDeclarativeAnimationGroup); - return d->ag; -} - -void QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { Q_D(QDeclarativeAnimationGroup); + QSequentialAnimationGroupJob *ag = new QSequentialAnimationGroupJob; + int inc = 1; int from = 0; if (direction == Backward) { @@ -1621,11 +1666,15 @@ void QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actio } bool valid = d->defaultProperty.isValid(); + QAbstractAnimationJob* anim; for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) { if (valid) d->animations.at(ii)->setDefaultTarget(d->defaultProperty); - d->animations.at(ii)->transition(actions, modified, direction); + anim = d->animations.at(ii)->transition(actions, modified, direction); + inc == -1 ? ag->prependAnimation(anim) : ag->appendAnimation(anim); } + + return initInstance(ag); } @@ -1661,36 +1710,30 @@ void QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actio QDeclarativeParallelAnimation::QDeclarativeParallelAnimation(QObject *parent) : QDeclarativeAnimationGroup(parent) { - Q_D(QDeclarativeAnimationGroup); - d->ag = new QParallelAnimationGroup; - QDeclarative_setParent_noEvent(d->ag, this); } QDeclarativeParallelAnimation::~QDeclarativeParallelAnimation() { } -QAbstractAnimation *QDeclarativeParallelAnimation::qtAnimation() -{ - Q_D(QDeclarativeAnimationGroup); - return d->ag; -} - -void QDeclarativeParallelAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QDeclarativeParallelAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { Q_D(QDeclarativeAnimationGroup); + QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob; + bool valid = d->defaultProperty.isValid(); + QAbstractAnimationJob* anim; for (int ii = 0; ii < d->animations.count(); ++ii) { if (valid) d->animations.at(ii)->setDefaultTarget(d->defaultProperty); - d->animations.at(ii)->transition(actions, modified, direction); + anim = d->animations.at(ii)->transition(actions, modified, direction); + ag->appendAnimation(anim); } + return initInstance(ag); } - - //convert a variant from string type to another animatable type void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int type) { @@ -1744,6 +1787,41 @@ void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int } } +QDeclarativeBulkValueAnimator::QDeclarativeBulkValueAnimator() + : QAbstractAnimationJob(), animValue(0), fromSourced(0), m_duration(250) +{ +} + +QDeclarativeBulkValueAnimator::~QDeclarativeBulkValueAnimator() +{ + delete animValue; +} + +void QDeclarativeBulkValueAnimator::setAnimValue(QDeclarativeBulkValueUpdater *value) +{ + if (isRunning()) + stop(); + animValue = value; +} + +void QDeclarativeBulkValueAnimator::updateCurrentTime(int currentTime) +{ + if (isStopped()) + return; + + const qreal progress = easing.valueForProgress(((m_duration == 0) ? qreal(1) : qreal(currentTime) / qreal(m_duration))); + + if (animValue) + animValue->setValue(progress); +} + +void QDeclarativeBulkValueAnimator::topLevelAnimationLoopChanged() +{ + //check for new from every top-level loop (when the top level animation is started and all subsequent loops) + if (fromSourced) + *fromSourced = false; +} + /*! \qmlclass PropertyAnimation QDeclarativePropertyAnimation \inqmlmodule QtQuick 2 @@ -1809,28 +1887,17 @@ void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int QDeclarativePropertyAnimation::QDeclarativePropertyAnimation(QObject *parent) : QDeclarativeAbstractAnimation(*(new QDeclarativePropertyAnimationPrivate), parent) { - Q_D(QDeclarativePropertyAnimation); - d->init(); } QDeclarativePropertyAnimation::QDeclarativePropertyAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent) : QDeclarativeAbstractAnimation(dd, parent) { - Q_D(QDeclarativePropertyAnimation); - d->init(); } QDeclarativePropertyAnimation::~QDeclarativePropertyAnimation() { } -void QDeclarativePropertyAnimationPrivate::init() -{ - Q_Q(QDeclarativePropertyAnimation); - va = new QDeclarativeBulkValueAnimator; - QDeclarative_setParent_noEvent(va, q); -} - /*! \qmlproperty int QtQuick2::PropertyAnimation::duration This property holds the duration of the animation, in milliseconds. @@ -1840,7 +1907,7 @@ void QDeclarativePropertyAnimationPrivate::init() int QDeclarativePropertyAnimation::duration() const { Q_D(const QDeclarativePropertyAnimation); - return d->va->duration(); + return d->duration; } void QDeclarativePropertyAnimation::setDuration(int duration) @@ -1851,9 +1918,9 @@ void QDeclarativePropertyAnimation::setDuration(int duration) } Q_D(QDeclarativePropertyAnimation); - if (d->va->duration() == duration) + if (d->duration == duration) return; - d->va->setDuration(duration); + d->duration = duration; emit durationChanged(duration); } @@ -2122,16 +2189,16 @@ void QDeclarativePropertyAnimation::setTo(const QVariant &t) QEasingCurve QDeclarativePropertyAnimation::easing() const { Q_D(const QDeclarativePropertyAnimation); - return d->va->easingCurve(); + return d->easing; } void QDeclarativePropertyAnimation::setEasing(const QEasingCurve &e) { Q_D(QDeclarativePropertyAnimation); - if (d->va->easingCurve() == e) + if (d->easing == e) return; - d->va->setEasingCurve(e); + d->easing = e; emit easingChanged(e); } @@ -2288,28 +2355,23 @@ QDeclarativeListProperty<QObject> QDeclarativePropertyAnimation::exclude() return QDeclarativeListProperty<QObject>(this, d->exclude); } -QAbstractAnimation *QDeclarativePropertyAnimation::qtAnimation() -{ - Q_D(QDeclarativePropertyAnimation); - return d->va; -} - void QDeclarativeAnimationPropertyUpdater::setValue(qreal v) { bool deleted = false; wasDeleted = &deleted; - if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1 + if (reverse) v = 1 - v; for (int ii = 0; ii < actions.count(); ++ii) { QDeclarativeAction &action = actions[ii]; - if (v == 1.) + if (v == 1.) { QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); - else { + } else { if (!fromSourced && !fromDefined) { action.fromValue = action.property.read(); - if (interpolatorType) + if (interpolatorType) { QDeclarativePropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType); + } } if (!interpolatorType) { int propType = action.property.propertyType(); @@ -2328,11 +2390,11 @@ void QDeclarativeAnimationPropertyUpdater::setValue(qreal v) fromSourced = true; } -void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions, - QDeclarativeProperties &modified, - TransitionDirection direction) +QDeclarativeStateActions QDeclarativePropertyAnimation::createTransitionActions(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified) { Q_D(QDeclarativePropertyAnimation); + QDeclarativeStateActions newActions; QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(',')); for (int ii = 0; ii < props.count(); ++ii) @@ -2356,13 +2418,6 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions props << d->defaultProperties.split(QLatin1Char(',')); } - QDeclarativeAnimationPropertyUpdater *data = new QDeclarativeAnimationPropertyUpdater; - data->interpolatorType = d->interpolatorType; - data->interpolator = d->interpolator; - data->reverse = direction == Backward ? true : false; - data->fromSourced = false; - data->fromDefined = d->fromIsDefined; - bool hasExplicit = false; //an explicit animation has been specified if (d->toIsDefined) { @@ -2377,7 +2432,7 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions } myAction.toValue = d->to; d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - data->actions << myAction; + newActions << myAction; hasExplicit = true; for (int ii = 0; ii < actions.count(); ++ii) { QDeclarativeAction &action = actions[ii]; @@ -2420,31 +2475,39 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions modified << action.property; - data->actions << myAction; + newActions << myAction; action.fromValue = myAction.toValue; } } - - if (data->actions.count()) { - if (!d->rangeIsSet) { - d->va->setStartValue(qreal(0)); - d->va->setEndValue(qreal(1)); - d->rangeIsSet = true; - } - d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped); - d->va->setFromSourcedValue(&data->fromSourced); - d->actions = &data->actions; - } else { - delete data; - d->va->setFromSourcedValue(0); //clear previous data - d->va->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped); //clear previous data - d->actions = 0; - } + return newActions; } +QAbstractAnimationJob* QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) +{ + Q_D(QDeclarativePropertyAnimation); -QDeclarativeScriptActionPrivate::QDeclarativeScriptActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} + QDeclarativeStateActions dataActions = createTransitionActions(actions, modified); + + QDeclarativeBulkValueAnimator *animator = new QDeclarativeBulkValueAnimator; + animator->setDuration(d->duration); + animator->setEasingCurve(d->easing); + + if (!dataActions.isEmpty()) { + QDeclarativeAnimationPropertyUpdater *data = new QDeclarativeAnimationPropertyUpdater; + data->interpolatorType = d->interpolatorType; + data->interpolator = d->interpolator; + data->reverse = direction == Backward ? true : false; + data->fromSourced = false; + data->fromDefined = d->fromIsDefined; + data->actions = dataActions; + animator->setAnimValue(data); + animator->setFromSourcedValue(&data->fromSourced); + d->actions = &data->actions; //remove this? + } + return initInstance(animator); +} QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativeanimation_p.h b/src/quick/util/qdeclarativeanimation_p.h index 7cf6bbe35e..5b69c5fb29 100644 --- a/src/quick/util/qdeclarativeanimation_p.h +++ b/src/quick/util/qdeclarativeanimation_p.h @@ -51,7 +51,7 @@ #include <QtCore/qvariant.h> #include <QtCore/qeasingcurve.h> -#include <QtCore/QAbstractAnimation> +#include "private/qabstractanimationjob_p.h" #include <QtGui/qcolor.h> QT_BEGIN_HEADER @@ -89,6 +89,7 @@ public: int loops() const; void setLoops(int); + int duration() const; int currentTime(); void setCurrentTime(int); @@ -98,7 +99,8 @@ public: void setDefaultTarget(const QDeclarativeProperty &); void setDisableUserControl(); - + void setEnableUserControl(); + bool userControlDisabled() const; void classBegin(); void componentComplete(); @@ -120,27 +122,26 @@ public Q_SLOTS: protected: QDeclarativeAbstractAnimation(QDeclarativeAbstractAnimationPrivate &dd, QObject *parent); + QAbstractAnimationJob* initInstance(QAbstractAnimationJob *animation); public: enum TransitionDirection { Forward, Backward }; - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation() = 0; + QAbstractAnimationJob* qtAnimation(); private Q_SLOTS: - void timelineComplete(); void componentFinalized(); private: virtual void setTarget(const QDeclarativeProperty &); void notifyRunningChanged(bool running); friend class QDeclarativeBehavior; - - + friend class QDeclarativeBehaviorPrivate; }; class QDeclarativePauseAnimationPrivate; -class Q_AUTOTEST_EXPORT QDeclarativePauseAnimation : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativePauseAnimation : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePauseAnimation) @@ -158,7 +159,9 @@ Q_SIGNALS: void durationChanged(int); protected: - virtual QAbstractAnimation *qtAnimation(); + QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction); }; class QDeclarativeScriptActionPrivate; @@ -181,14 +184,13 @@ public: void setStateChangeScriptName(const QString &); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; class QDeclarativePropertyActionPrivate; -class QDeclarativePropertyAction : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativePropertyAction : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyAction) @@ -226,14 +228,13 @@ Q_SIGNALS: void propertyChanged(); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; class QDeclarativePropertyAnimationPrivate; -class Q_AUTOTEST_EXPORT QDeclarativePropertyAnimation : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativePropertyAnimation : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation) @@ -277,12 +278,13 @@ public: QDeclarativeListProperty<QObject> exclude(); protected: + QDeclarativeStateActions createTransitionActions(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified); + QDeclarativePropertyAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent); - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); - Q_SIGNALS: void durationChanged(int); void fromChanged(QVariant); @@ -293,7 +295,7 @@ Q_SIGNALS: void propertyChanged(); }; -class Q_AUTOTEST_EXPORT QDeclarativeColorAnimation : public QDeclarativePropertyAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeColorAnimation : public QDeclarativePropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation) @@ -311,7 +313,7 @@ public: void setTo(const QColor &); }; -class Q_AUTOTEST_EXPORT QDeclarativeNumberAnimation : public QDeclarativePropertyAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeNumberAnimation : public QDeclarativePropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation) @@ -336,7 +338,7 @@ private: void init(); }; -class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyAnimation) @@ -356,7 +358,7 @@ public: }; class QDeclarativeRotationAnimationPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeRotationAnimation : public QDeclarativePropertyAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeRotationAnimation : public QDeclarativePropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeRotationAnimation) @@ -385,7 +387,7 @@ Q_SIGNALS: }; class QDeclarativeAnimationGroupPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeAnimationGroup : public QDeclarativeAbstractAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeAnimationGroup : public QDeclarativeAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup) @@ -414,13 +416,12 @@ public: virtual ~QDeclarativeSequentialAnimation(); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; -class QDeclarativeParallelAnimation : public QDeclarativeAnimationGroup +class Q_QUICK_PRIVATE_EXPORT QDeclarativeParallelAnimation : public QDeclarativeAnimationGroup { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAnimationGroup) @@ -430,10 +431,9 @@ public: virtual ~QDeclarativeParallelAnimation(); protected: - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - virtual QAbstractAnimation *qtAnimation(); }; diff --git a/src/quick/util/qdeclarativeanimation_p_p.h b/src/quick/util/qdeclarativeanimation_p_p.h index 53408e1e8a..5bcd70472d 100644 --- a/src/quick/util/qdeclarativeanimation_p_p.h +++ b/src/quick/util/qdeclarativeanimation_p_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEANIMATION_P_H -#define QDECLARATIVEANIMATION_P_H +#ifndef QDECLARATIVEANIMATION2_P_H +#define QDECLARATIVEANIMATION2_P_H // // W A R N I N G @@ -60,13 +60,16 @@ #include <qdeclarative.h> #include <qdeclarativecontext.h> -#include <QtCore/QPauseAnimation> -#include <QtCore/QVariantAnimation> -#include <QtCore/QAnimationGroup> +#include <private/qvariantanimation_p.h> +#include "private/qpauseanimationjob_p.h" #include <QDebug> #include <private/qobject_p.h> -#include <private/qvariantanimation_p.h> +#include "private/qanimationgroupjob_p.h" +#include <QDebug> + +#include <private/qobject_p.h> + QT_BEGIN_NAMESPACE @@ -85,51 +88,32 @@ template<class T, void (T::*method)()> class QAnimationActionProxy : public QAbstractAnimationAction { public: - QAnimationActionProxy(T *p) : m_p(p) {} - virtual void doAction() { (m_p->*method)(); } + QAnimationActionProxy(T *instance) : m_instance(instance) {} + virtual void doAction() { (m_instance->*method)(); } private: - T *m_p; + T *m_instance; }; //performs an action of type QAbstractAnimationAction -class Q_AUTOTEST_EXPORT QActionAnimation : public QAbstractAnimation +class Q_AUTOTEST_EXPORT QActionAnimation : public QAbstractAnimationJob { - Q_OBJECT + Q_DISABLE_COPY(QActionAnimation) public: - QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {} - QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0) - : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {} - ~QActionAnimation() { if (policy == DeleteWhenStopped) { delete animAction; animAction = 0; } } - virtual int duration() const { return 0; } - void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p) - { - if (state() == Running) - stop(); - if (policy == DeleteWhenStopped) - delete animAction; - animAction = action; - policy = p; - } + QActionAnimation(); + + QActionAnimation(QAbstractAnimationAction *action); + ~QActionAnimation(); + + virtual int duration() const; + void setAnimAction(QAbstractAnimationAction *action); + protected: - virtual void updateCurrentTime(int) {} - - virtual void updateState(State newState, State /*oldState*/) - { - if (newState == Running) { - if (animAction) { - animAction->doAction(); - if (state() == Stopped && policy == DeleteWhenStopped) { - delete animAction; - animAction = 0; - } - } - } - } + virtual void updateCurrentTime(int); + virtual void updateState(State newState, State oldState); private: QAbstractAnimationAction *animAction; - DeletionPolicy policy; }; class QDeclarativeBulkValueUpdater @@ -140,83 +124,64 @@ public: }; //animates QDeclarativeBulkValueUpdater (assumes start and end values will be reals or compatible) -class Q_AUTOTEST_EXPORT QDeclarativeBulkValueAnimator : public QVariantAnimation +class Q_AUTOTEST_EXPORT QDeclarativeBulkValueAnimator : public QAbstractAnimationJob { - Q_OBJECT + Q_DISABLE_COPY(QDeclarativeBulkValueAnimator) public: - QDeclarativeBulkValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {} - ~QDeclarativeBulkValueAnimator() { if (policy == DeleteWhenStopped) { delete animValue; animValue = 0; } } - void setAnimValue(QDeclarativeBulkValueUpdater *value, DeletionPolicy p) - { - if (state() == Running) - stop(); - if (policy == DeleteWhenStopped) - delete animValue; - animValue = value; - policy = p; - } - QDeclarativeBulkValueUpdater *getAnimValue() const - { - return animValue; - } - void setFromSourcedValue(bool *value) - { - fromSourced = value; - } + QDeclarativeBulkValueAnimator(); + ~QDeclarativeBulkValueAnimator(); + + void setAnimValue(QDeclarativeBulkValueUpdater *value); + QDeclarativeBulkValueUpdater *getAnimValue() const { return animValue; } + + void setFromSourcedValue(bool *value) { fromSourced = value; } + + int duration() const { return m_duration; } + void setDuration(int msecs) { m_duration = msecs; } + + QEasingCurve easingCurve() const { return easing; } + void setEasingCurve(const QEasingCurve &curve) { easing = curve; } + protected: - virtual void updateCurrentValue(const QVariant &value) - { - if (state() == QAbstractAnimation::Stopped) - return; - - if (animValue) - animValue->setValue(value.toReal()); - } - virtual void updateState(State newState, State oldState) - { - QVariantAnimation::updateState(newState, oldState); - if (newState == Running) { - //check for new from every loop - if (fromSourced) - *fromSourced = false; - } - } + void updateCurrentTime(int currentTime); + void topLevelAnimationLoopChanged(); private: QDeclarativeBulkValueUpdater *animValue; bool *fromSourced; - DeletionPolicy policy; + int m_duration; + QEasingCurve easing; }; //an animation that just gives a tick template<class T, void (T::*method)(int)> -class QTickAnimationProxy : public QAbstractAnimation +class QTickAnimationProxy : public QAbstractAnimationJob { - //Q_OBJECT //doesn't work with templating + Q_DISABLE_COPY(QTickAnimationProxy) public: - QTickAnimationProxy(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {} + QTickAnimationProxy(T *instance) : QAbstractAnimationJob(), m_instance(instance) {} virtual int duration() const { return -1; } protected: - virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); } + virtual void updateCurrentTime(int msec) { (m_instance->*method)(msec); } private: - T *m_p; + T *m_instance; }; -class QDeclarativeAbstractAnimationPrivate : public QObjectPrivate +class QDeclarativeAbstractAnimationPrivate : public QObjectPrivate, public QAnimation2ChangeListener { Q_DECLARE_PUBLIC(QDeclarativeAbstractAnimation) public: QDeclarativeAbstractAnimationPrivate() : running(false), paused(false), alwaysRunToEnd(false), - connectedTimeLine(false), componentComplete(true), + /*connectedTimeLine(false), */componentComplete(true), avoidPropertyValueSourceStart(false), disableUserControl(false), - registered(false), loopCount(1), group(0) {} + registered(false), loopCount(1), group(0), animationInstance(0) {} bool running:1; bool paused:1; bool alwaysRunToEnd:1; - bool connectedTimeLine:1; + //bool connectedTimeLine:1; bool componentComplete:1; bool avoidPropertyValueSourceStart:1; bool disableUserControl:1; @@ -225,10 +190,12 @@ public: int loopCount; void commence(); + virtual void animationFinished(QAbstractAnimationJob *); QDeclarativeProperty defaultProperty; QDeclarativeAnimationGroup *group; + QAbstractAnimationJob* animationInstance; static QDeclarativeProperty createProperty(QObject *obj, const QString &str, QObject *infoObj); }; @@ -238,11 +205,9 @@ class QDeclarativePauseAnimationPrivate : public QDeclarativeAbstractAnimationPr Q_DECLARE_PUBLIC(QDeclarativePauseAnimation) public: QDeclarativePauseAnimationPrivate() - : QDeclarativeAbstractAnimationPrivate(), pa(0) {} + : QDeclarativeAbstractAnimationPrivate(), duration(250) {} - void init(); - - QPauseAnimation *pa; + int duration; }; class QDeclarativeScriptActionPrivate : public QDeclarativeAbstractAnimationPrivate @@ -251,8 +216,6 @@ class QDeclarativeScriptActionPrivate : public QDeclarativeAbstractAnimationPriv public: QDeclarativeScriptActionPrivate(); - void init(); - QDeclarativeScriptString script; QString name; QDeclarativeScriptString runScriptScript; @@ -260,10 +223,9 @@ public: bool reversing; void execute(); - - QAnimationActionProxy<QDeclarativeScriptActionPrivate, - &QDeclarativeScriptActionPrivate::execute> proxy; - QActionAnimation *rsa; + QAbstractAnimationAction* createAction(); + typedef QAnimationActionProxy<QDeclarativeScriptActionPrivate, + &QDeclarativeScriptActionPrivate::execute> Proxy; }; class QDeclarativePropertyActionPrivate : public QDeclarativeAbstractAnimationPrivate @@ -271,9 +233,7 @@ class QDeclarativePropertyActionPrivate : public QDeclarativeAbstractAnimationPr Q_DECLARE_PUBLIC(QDeclarativePropertyAction) public: QDeclarativePropertyActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), target(0), spa(0) {} - - void init(); + : QDeclarativeAbstractAnimationPrivate(), target(0) {} QObject *target; QString propertyName; @@ -282,8 +242,6 @@ public: QList<QObject *> exclude; QDeclarativeNullableValue<QVariant> value; - - QActionAnimation *spa; }; class QDeclarativeAnimationGroupPrivate : public QDeclarativeAbstractAnimationPrivate @@ -291,12 +249,11 @@ class QDeclarativeAnimationGroupPrivate : public QDeclarativeAbstractAnimationPr Q_DECLARE_PUBLIC(QDeclarativeAnimationGroup) public: QDeclarativeAnimationGroupPrivate() - : QDeclarativeAbstractAnimationPrivate(), ag(0) {} + : QDeclarativeAbstractAnimationPrivate() {} static void append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *role); static void clear_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list); QList<QDeclarativeAbstractAnimation *> animations; - QAnimationGroup *ag; }; class QDeclarativePropertyAnimationPrivate : public QDeclarativeAbstractAnimationPrivate @@ -305,9 +262,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), actions(0) {} - - void init(); + defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), duration(250), actions(0) {} QVariant from; QVariant to; @@ -322,12 +277,11 @@ public: bool fromSourced; bool fromIsDefined:1; bool toIsDefined:1; - bool rangeIsSet:1; bool defaultToInterpolatorType:1; int interpolatorType; QVariantAnimation::Interpolator interpolator; - - QDeclarativeBulkValueAnimator *va; + int duration; + QEasingCurve easing; // for animations that don't use the QDeclarativeBulkValueAnimator QDeclarativeStateActions *actions; @@ -348,19 +302,21 @@ public: class Q_AUTOTEST_EXPORT QDeclarativeAnimationPropertyUpdater : public QDeclarativeBulkValueUpdater { public: + QDeclarativeAnimationPropertyUpdater() : prevInterpolatorType(0), wasDeleted(0) {} + ~QDeclarativeAnimationPropertyUpdater() { if (wasDeleted) *wasDeleted = true; } + + void setValue(qreal v); + QDeclarativeStateActions actions; int interpolatorType; //for Number/ColorAnimation - int prevInterpolatorType; //for generic QVariantAnimation::Interpolator interpolator; + int prevInterpolatorType; //for generic bool reverse; bool fromSourced; bool fromDefined; bool *wasDeleted; - QDeclarativeAnimationPropertyUpdater() : prevInterpolatorType(0), wasDeleted(0) {} - ~QDeclarativeAnimationPropertyUpdater() { if (wasDeleted) *wasDeleted = true; } - void setValue(qreal v); }; QT_END_NAMESPACE -#endif // QDECLARATIVEANIMATION_P_H +#endif // QDECLARATIVEANIMATION2_P_H diff --git a/src/quick/util/qdeclarativeanimationcontroller.cpp b/src/quick/util/qdeclarativeanimationcontroller.cpp new file mode 100644 index 0000000000..3901a65cb6 --- /dev/null +++ b/src/quick/util/qdeclarativeanimationcontroller.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeanimationcontroller_p.h" +#include <QtDeclarative/qdeclarativeinfo.h> +#include <private/qdeclarativeengine_p.h> + +QT_BEGIN_NAMESPACE + + +class QDeclarativeAnimationControllerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeAnimationController) +public: + QDeclarativeAnimationControllerPrivate() + : progress(0.0), animation(0), animationInstance(0), finalized(false) {} + + qreal progress; + QDeclarativeAbstractAnimation *animation; + QAbstractAnimationJob *animationInstance; + bool finalized:1; + +}; + +/*! + \qmlclass AnimationController QDeclarativeAnimationController + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \brief The AnimationController element allows you to control animations manually. + + Normally animations are driven by an internal timer, but the AnimationController + allows the given \a animation to be driven by a \a progress value explicitly. +*/ + + +QDeclarativeAnimationController::QDeclarativeAnimationController(QObject *parent) +: QObject(*(new QDeclarativeAnimationControllerPrivate), parent) +{ +} + +QDeclarativeAnimationController::~QDeclarativeAnimationController() +{ + Q_D(QDeclarativeAnimationController); + delete d->animationInstance; +} + +/*! + \qmlproperty real QtQuick2::AnimationController::progress + This property holds the animation progress value. + + The valid \c progress value is 0.0 to 1.0, setting values less than 0 will be converted to 0, + setting values great than 1 will be converted to 1. +*/ +qreal QDeclarativeAnimationController::progress() const +{ + Q_D(const QDeclarativeAnimationController); + return d->progress; +} + +void QDeclarativeAnimationController::setProgress(qreal progress) +{ + Q_D(QDeclarativeAnimationController); + progress = qBound(qreal(0), progress, qreal(1)); + + if (progress != d->progress) { + d->progress = progress; + updateProgress(); + emit progressChanged(); + } +} + +/*! + \qmlproperty real QtQuick2::AnimationController::animation + \default + + This property holds the animation to be controlled by the AnimationController. + + Note:An animation controlled by AnimationController will always have its + \c running and \c paused properties set to true. It can not be manually + started or stopped (much like an animation in a Behavior can not be manually started or stopped). +*/ +QDeclarativeAbstractAnimation *QDeclarativeAnimationController::animation() const +{ + Q_D(const QDeclarativeAnimationController); + return d->animation; +} + +void QDeclarativeAnimationController::classBegin() +{ + QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this)); + engPriv->registerFinalizeCallback(this, this->metaObject()->indexOfSlot("componentFinalized()")); +} + + +void QDeclarativeAnimationController::setAnimation(QDeclarativeAbstractAnimation *animation) +{ + Q_D(QDeclarativeAnimationController); + + if (animation != d->animation) { + if (animation) { + if (animation->userControlDisabled()) { + qmlInfo(this) << "QDeclarativeAnimationController::setAnimation: the animation is controlled by others, can't be used in AnimationController."; + return; + } + animation->setDisableUserControl(); + } + + if (d->animation) + d->animation->setEnableUserControl(); + + d->animation = animation; + reload(); + emit animationChanged(); + } +} + +/*! + \qmlmethod QtQuick2::AnimationController::reload() + \brief Reloads the animation properties. + + If the animation properties changed, calling this method to reload the animation definations. +*/ +void QDeclarativeAnimationController::reload() +{ + Q_D(QDeclarativeAnimationController); + if (!d->finalized) + return; + + if (!d->animation) { + d->animationInstance = 0; + } else { + QDeclarativeStateActions actions; + QDeclarativeProperties properties; + QAbstractAnimationJob *oldInstance = d->animationInstance; + d->animationInstance = d->animation->transition(actions, properties, QDeclarativeAbstractAnimation::Forward); + if (oldInstance && oldInstance != d->animationInstance) + delete oldInstance; + d->animationInstance->setLoopCount(1); + d->animationInstance->start(); + d->animationInstance->pause(); + updateProgress(); + } +} + +void QDeclarativeAnimationController::updateProgress() +{ + Q_D(QDeclarativeAnimationController); + if (!d->animationInstance) + return; + + d->animationInstance->start(); + QDeclarativeAnimationTimer::unregisterAnimation(d->animationInstance); + d->animationInstance->setCurrentTime(d->progress * d->animationInstance->duration()); +} + +void QDeclarativeAnimationController::componentFinalized() +{ + Q_D(QDeclarativeAnimationController); + d->finalized = true; + reload(); +} + + +QT_END_NAMESPACE + + diff --git a/src/quick/util/qdeclarativeanimationcontroller_p.h b/src/quick/util/qdeclarativeanimationcontroller_p.h new file mode 100644 index 0000000000..d4000b53d9 --- /dev/null +++ b/src/quick/util/qdeclarativeanimationcontroller_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEANIMATIONCONTROLLER_H +#define QDECLARATIVEANIMATIONCONTROLLER_H + +#include <qdeclarative.h> +#include "qdeclarativeanimation_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeAnimationControllerPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeAnimationController : public QObject, public QDeclarativeParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeAnimationController) + Q_CLASSINFO("DefaultProperty", "animation") + + Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged) + Q_PROPERTY(QDeclarativeAbstractAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged) + +public: + QDeclarativeAnimationController(QObject *parent=0); + ~QDeclarativeAnimationController(); + + qreal progress() const; + void setProgress(qreal progress); + + QDeclarativeAbstractAnimation *animation() const; + void setAnimation(QDeclarativeAbstractAnimation *animation); + + void classBegin(); + void componentComplete() {} +Q_SIGNALS: + void progressChanged(); + void animationChanged(); +public Q_SLOTS: + void reload(); +private Q_SLOTS: + void componentFinalized(); + void updateProgress(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeAnimationController) + +QT_END_HEADER + +#endif // QDECLARATIVEANIMATIONCONTROLLER_H diff --git a/src/quick/util/qdeclarativebehavior.cpp b/src/quick/util/qdeclarativebehavior.cpp index daed2e806d..726c39fa9f 100644 --- a/src/quick/util/qdeclarativebehavior.cpp +++ b/src/quick/util/qdeclarativebehavior.cpp @@ -47,21 +47,26 @@ #include <private/qdeclarativeproperty_p.h> #include <private/qdeclarativeguard_p.h> #include <private/qdeclarativeengine_p.h> +#include <private/qabstractanimationjob_p.h> +#include <private/qdeclarativetransition_p.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE -class QDeclarativeBehaviorPrivate : public QObjectPrivate +class QDeclarativeBehaviorPrivate : public QObjectPrivate, public QAnimation2ChangeListener { Q_DECLARE_PUBLIC(QDeclarativeBehavior) public: - QDeclarativeBehaviorPrivate() : animation(0), enabled(true), finalized(false) + QDeclarativeBehaviorPrivate() : animation(0), animationInstance(0), enabled(true), finalized(false) , blockRunningChanged(false) {} + virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); + QDeclarativeProperty property; QVariant targetValue; QDeclarativeGuard<QDeclarativeAbstractAnimation> animation; + QAbstractAnimationJob *animationInstance; bool enabled; bool finalized; bool blockRunningChanged; @@ -102,6 +107,8 @@ QDeclarativeBehavior::QDeclarativeBehavior(QObject *parent) QDeclarativeBehavior::~QDeclarativeBehavior() { + Q_D(QDeclarativeBehavior); + delete d->animationInstance; } /*! @@ -129,22 +136,16 @@ void QDeclarativeBehavior::setAnimation(QDeclarativeAbstractAnimation *animation if (d->animation) { d->animation->setDefaultTarget(d->property); d->animation->setDisableUserControl(); - FAST_CONNECT(d->animation->qtAnimation(), - SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), - this, - SLOT(qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State))) } } -void QDeclarativeBehavior::qtAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State) +void QDeclarativeBehaviorPrivate::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState,QAbstractAnimationJob::State) { - Q_D(QDeclarativeBehavior); - if (!d->blockRunningChanged) - d->animation->notifyRunningChanged(newState == QAbstractAnimation::Running); + if (!blockRunningChanged) + animation->notifyRunningChanged(newState == QAbstractAnimationJob::Running); } - /*! \qmlproperty bool QtQuick2::Behavior::enabled @@ -187,10 +188,10 @@ void QDeclarativeBehavior::write(const QVariant &value) const QVariant ¤tValue = d->property.read(); d->targetValue = value; - if (d->animation->qtAnimation()->duration() != -1 - && d->animation->qtAnimation()->state() != QAbstractAnimation::Stopped) { + if (d->animationInstance && d->animationInstance->duration() != -1 + && !d->animationInstance->isStopped()) { d->blockRunningChanged = true; - d->animation->qtAnimation()->stop(); + d->animationInstance->stop(); } QDeclarativeStateOperation::ActionList actions; @@ -201,8 +202,14 @@ void QDeclarativeBehavior::write(const QVariant &value) actions << action; QList<QDeclarativeProperty> after; - d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward); - d->animation->qtAnimation()->start(); + QAbstractAnimationJob *prev = d->animationInstance; + d->animationInstance = d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward); + if (d->animationInstance != prev) { + d->animationInstance->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange); + if (prev) + delete prev; + } + d->animationInstance->start(); d->blockRunningChanged = false; if (!after.contains(d->property)) QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); @@ -216,7 +223,10 @@ void QDeclarativeBehavior::setTarget(const QDeclarativeProperty &property) d->animation->setDefaultTarget(property); QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this)); - engPriv->registerFinalizeCallback(this, this->metaObject()->indexOfSlot("componentFinalized()")); + static int finalizedIdx = -1; + if (finalizedIdx < 0) + finalizedIdx = metaObject()->indexOfSlot("componentFinalized()"); + engPriv->registerFinalizeCallback(this, finalizedIdx); } void QDeclarativeBehavior::componentFinalized() diff --git a/src/quick/util/qdeclarativebehavior_p.h b/src/quick/util/qdeclarativebehavior_p.h index 5b26aa90d3..c95304dce7 100644 --- a/src/quick/util/qdeclarativebehavior_p.h +++ b/src/quick/util/qdeclarativebehavior_p.h @@ -46,7 +46,6 @@ #include <private/qdeclarativepropertyvalueinterceptor_p.h> #include <qdeclarative.h> -#include <QtCore/QAbstractAnimation> QT_BEGIN_HEADER @@ -83,7 +82,6 @@ Q_SIGNALS: private Q_SLOTS: void componentFinalized(); - void qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State); }; QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativesmoothedanimation.cpp b/src/quick/util/qdeclarativesmoothedanimation.cpp index 52e870a3be..9b61561fef 100644 --- a/src/quick/util/qdeclarativesmoothedanimation.cpp +++ b/src/quick/util/qdeclarativesmoothedanimation.cpp @@ -57,42 +57,88 @@ QT_BEGIN_NAMESPACE -QSmoothedAnimation::QSmoothedAnimation(QObject *parent) - : QAbstractAnimation(parent), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1), + +QSmoothedAnimationTimer::QSmoothedAnimationTimer(QSmoothedAnimation *animation, QObject *parent) + : QTimer(parent) + , m_animation(animation) +{ + connect(this, SIGNAL(timeout()), this, SLOT(stopAnimation())); +} + +QSmoothedAnimationTimer::~QSmoothedAnimationTimer() +{ +} + +void QSmoothedAnimationTimer::stopAnimation() +{ + m_animation->stop(); +} + +QSmoothedAnimation::QSmoothedAnimation(QDeclarativeSmoothedAnimationPrivate *priv) + : QAbstractAnimationJob(), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1), reversingMode(QDeclarativeSmoothedAnimation::Eased), initialVelocity(0), - trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0) + trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0), + useDelta(false), delayedStopTimer(new QSmoothedAnimationTimer(this)), animationTemplate(priv) +{ + delayedStopTimer->setInterval(DELAY_STOP_TIMER_INTERVAL); + delayedStopTimer->setSingleShot(true); +} + +QSmoothedAnimation::~QSmoothedAnimation() { + delete delayedStopTimer; + if (animationTemplate) { + if (target.object()) { + QHash<QDeclarativeProperty, QSmoothedAnimation* >::iterator it = + animationTemplate->activeAnimations.find(target); + if (it != animationTemplate->activeAnimations.end() && it.value() == this) + animationTemplate->activeAnimations.erase(it); + } else { + //target is no longer valid, need to search linearly + QHash<QDeclarativeProperty, QSmoothedAnimation* >::iterator it; + for (it = animationTemplate->activeAnimations.begin(); it != animationTemplate->activeAnimations.end(); ++it) { + if (it.value() == this) { + animationTemplate->activeAnimations.erase(it); + break; + } + } + } + } } void QSmoothedAnimation::restart() { initialVelocity = trackVelocity; - if (state() != QAbstractAnimation::Running) - start(); - else + if (isRunning()) init(); + else + start(); } -void QSmoothedAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/) +void QSmoothedAnimation::prepareForRestart() { - if (newState == QAbstractAnimation::Running) + initialVelocity = trackVelocity; + if (isRunning()) { + //we are joining a new wrapper group while running, our times need to be restarted + useDelta = true; init(); + lastTime = 0; + } else { + useDelta = false; + //we'll be started when the group starts, which will force an init() + } } -void QSmoothedAnimation::timerEvent(QTimerEvent *event) +void QSmoothedAnimation::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State /*oldState*/) { - if (event->timerId() == delayedStopTimer.timerId()) { - delayedStopTimer.stop(); - stop(); - } else { - QAbstractAnimation::timerEvent(event); - } + if (newState == QAbstractAnimationJob::Running) + init(); } void QSmoothedAnimation::delayedStop() { - if (!delayedStopTimer.isActive()) - delayedStopTimer.start(DELAY_STOP_TIMER_INTERVAL, this); + if (!delayedStopTimer->isActive()) + delayedStopTimer->start(); } int QSmoothedAnimation::duration() const @@ -196,7 +242,9 @@ qreal QSmoothedAnimation::easeFollow(qreal time_seconds) void QSmoothedAnimation::updateCurrentTime(int t) { - qreal time_seconds = qreal(t - lastTime) / 1000.; + qreal time_seconds = useDelta ? qreal(QDeclarativeAnimationTimer::instance()->currentDelta()) / 1000. : qreal(t - lastTime) / 1000.; + if (useDelta) + useDelta = false; qreal value = easeFollow(time_seconds); value *= (invert? -1.0: 1.0); @@ -212,8 +260,8 @@ void QSmoothedAnimation::init() return; } - if (delayedStopTimer.isActive()) - delayedStopTimer.stop(); + if (delayedStopTimer->isActive()) + delayedStopTimer->stop(); initialValue = target.read().toReal(); lastTime = this->currentTime(); @@ -312,14 +360,22 @@ QDeclarativeSmoothedAnimation::QDeclarativeSmoothedAnimation(QObject *parent) QDeclarativeSmoothedAnimation::~QDeclarativeSmoothedAnimation() { + } QDeclarativeSmoothedAnimationPrivate::QDeclarativeSmoothedAnimationPrivate() - : wrapperGroup(new QParallelAnimationGroup), anim(new QSmoothedAnimation) + : anim(0) { - Q_Q(QDeclarativeSmoothedAnimation); - QDeclarative_setParent_noEvent(wrapperGroup, q); - QDeclarative_setParent_noEvent(anim, q); + anim = new QSmoothedAnimation; +} + +QDeclarativeSmoothedAnimationPrivate::~QDeclarativeSmoothedAnimationPrivate() +{ + delete anim; + QHash<QDeclarativeProperty, QSmoothedAnimation* >::iterator it; + for (it = activeAnimations.begin(); it != activeAnimations.end(); ++it) { + it.value()->clearTemplate(); + } } void QDeclarativeSmoothedAnimationPrivate::updateRunningAnimations() @@ -333,59 +389,56 @@ void QDeclarativeSmoothedAnimationPrivate::updateRunningAnimations() } } -QAbstractAnimation* QDeclarativeSmoothedAnimation::qtAnimation() -{ - Q_D(QDeclarativeSmoothedAnimation); - return d->wrapperGroup; -} - -void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { + Q_UNUSED(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; - 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); - needsRestart = false; - } else { - ease = d->activeAnimations.value((*d->actions)[i].property); - needsRestart = true; + QDeclarativeStateActions dataActions = QDeclarativePropertyAnimation::createTransitionActions(actions, modified); + + QParallelAnimationGroupJob *wrapperGroup = new QParallelAnimationGroupJob(); + + if (!dataActions.isEmpty()) { + QSet<QAbstractAnimationJob*> anims; + for (int i = 0; i < dataActions.size(); i++) { + QSmoothedAnimation *ease; + bool isActive; + if (!d->activeAnimations.contains(dataActions[i].property)) { + ease = new QSmoothedAnimation(d); + d->activeAnimations.insert(dataActions[i].property, ease); + ease->target = dataActions[i].property; + isActive = false; + } else { + ease = d->activeAnimations.value(dataActions[i].property); + isActive = true; + } + wrapperGroup->appendAnimation(initInstance(ease)); + + ease->to = dataActions[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->initialVelocity = ease->trackVelocity; + + if (isActive) + ease->prepareForRestart(); + anims.insert(ease); } - 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->initialVelocity = ease->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; + foreach (QSmoothedAnimation *ease, d->activeAnimations.values()){ + if (!anims.contains(ease)) { + ease->clearTemplate(); + d->activeAnimations.remove(ease->target); + } } } + return wrapperGroup; } /*! diff --git a/src/quick/util/qdeclarativesmoothedanimation_p.h b/src/quick/util/qdeclarativesmoothedanimation_p.h index 02acf205d9..d065a20516 100644 --- a/src/quick/util/qdeclarativesmoothedanimation_p.h +++ b/src/quick/util/qdeclarativesmoothedanimation_p.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeProperty; class QDeclarativeSmoothedAnimationPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation) @@ -81,11 +81,9 @@ public: int maximumEasingTime() const; void setMaximumEasingTime(int); - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); - QAbstractAnimation* qtAnimation(); - Q_SIGNALS: void velocityChanged(); void reversingModeChanged(); diff --git a/src/quick/util/qdeclarativesmoothedanimation_p_p.h b/src/quick/util/qdeclarativesmoothedanimation_p_p.h index 07d8b2b271..9afb6506a7 100644 --- a/src/quick/util/qdeclarativesmoothedanimation_p_p.h +++ b/src/quick/util/qdeclarativesmoothedanimation_p_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVESMOOTHEDANIMATION_P_H -#define QDECLARATIVESMOOTHEDANIMATION_P_H +#ifndef QDECLARATIVESMOOTHEDANIMATION2_P_H +#define QDECLARATIVESMOOTHEDANIMATION2_P_H // // W A R N I N G @@ -58,18 +58,33 @@ #include "qdeclarativeanimation_p_p.h" -#include <qparallelanimationgroup.h> +#include "private/qparallelanimationgroupjob_p.h" #include <private/qobject_p.h> #include <QBasicTimer> QT_BEGIN_NAMESPACE +class QSmoothedAnimation; +class QSmoothedAnimationTimer : public QTimer +{ + Q_OBJECT +public: + explicit QSmoothedAnimationTimer(QSmoothedAnimation *animation, QObject *parent = 0); + ~QSmoothedAnimationTimer(); +public Q_SLOTS: + void stopAnimation(); +private: + QSmoothedAnimation *m_animation; +}; -class Q_AUTOTEST_EXPORT QSmoothedAnimation : public QAbstractAnimation +class QDeclarativeSmoothedAnimationPrivate; +class Q_AUTOTEST_EXPORT QSmoothedAnimation : public QAbstractAnimationJob { + Q_DISABLE_COPY(QSmoothedAnimation) public: - QSmoothedAnimation(QObject *parent=0); + QSmoothedAnimation(QDeclarativeSmoothedAnimationPrivate * = 0); + ~QSmoothedAnimation(); qreal to; qreal velocity; int userDuration; @@ -86,10 +101,12 @@ public: void restart(); void init(); + void prepareForRestart(); + void clearTemplate() { animationTemplate = 0; } + protected: virtual void updateCurrentTime(int); - virtual void updateState(QAbstractAnimation::State, QAbstractAnimation::State); - virtual void timerEvent(QTimerEvent *); + virtual void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State); private: qreal easeFollow(qreal); @@ -112,11 +129,12 @@ private: qreal s; // Total s int lastTime; + bool useDelta; bool recalc(); void delayedStop(); - - QBasicTimer delayedStopTimer; + QSmoothedAnimationTimer *delayedStopTimer; + QDeclarativeSmoothedAnimationPrivate *animationTemplate; }; class QDeclarativeSmoothedAnimationPrivate : public QDeclarativePropertyAnimationPrivate @@ -124,13 +142,13 @@ class QDeclarativeSmoothedAnimationPrivate : public QDeclarativePropertyAnimatio Q_DECLARE_PUBLIC(QDeclarativeSmoothedAnimation) public: QDeclarativeSmoothedAnimationPrivate(); + ~QDeclarativeSmoothedAnimationPrivate(); void updateRunningAnimations(); - QParallelAnimationGroup *wrapperGroup; QSmoothedAnimation *anim; QHash<QDeclarativeProperty, QSmoothedAnimation*> activeAnimations; }; QT_END_NAMESPACE -#endif // QDECLARATIVESMOOTHEDANIMATION_P_H +#endif // QDECLARATIVESMOOTHEDANIMATION2_P_H diff --git a/src/quick/util/qdeclarativespringanimation.cpp b/src/quick/util/qdeclarativespringanimation.cpp index 27ef5bd62e..40408bb112 100644 --- a/src/quick/util/qdeclarativespringanimation.cpp +++ b/src/quick/util/qdeclarativespringanimation.cpp @@ -43,6 +43,7 @@ #include "qdeclarativeanimation_p_p.h" #include <private/qdeclarativeproperty_p.h> +#include "private/qparallelanimationgroupjob_p.h" #include <QtCore/qdebug.h> @@ -51,29 +52,39 @@ #include <limits.h> #include <math.h> -QT_BEGIN_NAMESPACE +#define DELAY_STOP_TIMER_INTERVAL 32 +QT_BEGIN_NAMESPACE -class QDeclarativeSpringAnimationPrivate : public QDeclarativePropertyAnimationPrivate +class QDeclarativeSpringAnimationPrivate; +class Q_AUTOTEST_EXPORT QSpringAnimation : public QAbstractAnimationJob { - Q_DECLARE_PUBLIC(QDeclarativeSpringAnimation) + Q_DISABLE_COPY(QSpringAnimation) public: - - - struct SpringAnimation { - SpringAnimation() - : currentValue(0), to(0), velocity(0), start(0), duration(0) {} - qreal currentValue; - qreal to; - qreal velocity; - int start; - int duration; + QSpringAnimation(QDeclarativeSpringAnimationPrivate * = 0); + + ~QSpringAnimation(); + int duration() const; + void restart(); + void init(); + + qreal currentValue; + qreal to; + qreal velocity; + int startTime; + int dura; + int lastTime; + int stopTime; + enum Mode { + Track, + Velocity, + Spring }; - QHash<QDeclarativeProperty, SpringAnimation> activeAnimations; + Mode mode; + QDeclarativeProperty target; - qreal maxVelocity; qreal velocityms; - int lastTime; + qreal maxVelocity; qreal mass; qreal spring; qreal damping; @@ -82,75 +93,161 @@ public: bool useMass : 1; bool haveModulus : 1; + bool useDelta : 1; + typedef QHash<QDeclarativeProperty, QSpringAnimation*> ActiveAnimationHash; - enum Mode { - Track, - Velocity, - Spring - }; - Mode mode; + void clearTemplate() { animationTemplate = 0; } +protected: + virtual void updateCurrentTime(int time); + virtual void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State); + +private: + QDeclarativeSpringAnimationPrivate *animationTemplate; +}; + +class QDeclarativeSpringAnimationPrivate : public QDeclarativePropertyAnimationPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeSpringAnimation) +public: QDeclarativeSpringAnimationPrivate() - : maxVelocity(0), velocityms(0), lastTime(0) - , mass(1.0), spring(0.), damping(0.), epsilon(0.01) - , modulus(0.0), useMass(false), haveModulus(false) - , mode(Track), clock(0) - { } - - void tick(int time); - bool animate(const QDeclarativeProperty &property, SpringAnimation &animation, int elapsed); + : QDeclarativePropertyAnimationPrivate() + , velocityms(0) + , maxVelocity(0) + , mass(1.0) + , spring(0.) + , damping(0.) + , epsilon(0.01) + , modulus(0.0) + , useMass(false) + , haveModulus(false) + , mode(QSpringAnimation::Track) + { elapsed.start(); } + void updateMode(); + qreal velocityms; + qreal maxVelocity; + qreal mass; + qreal spring; + qreal damping; + qreal epsilon; + qreal modulus; + + bool useMass : 1; + bool haveModulus : 1; + QSpringAnimation::Mode mode; - typedef QTickAnimationProxy<QDeclarativeSpringAnimationPrivate, &QDeclarativeSpringAnimationPrivate::tick> Clock; - Clock *clock; + QSpringAnimation::ActiveAnimationHash activeAnimations; + QElapsedTimer elapsed; }; -void QDeclarativeSpringAnimationPrivate::tick(int time) +QSpringAnimation::QSpringAnimation(QDeclarativeSpringAnimationPrivate *priv) + : QAbstractAnimationJob() + , currentValue(0) + , to(0) + , velocity(0) + , startTime(0) + , dura(0) + , lastTime(0) + , stopTime(-1) + , mode(Track) + , velocityms(0) + , maxVelocity(0) + , mass(1.0) + , spring(0.) + , damping(0.) + , epsilon(0.01) + , modulus(0.0) + , useMass(false) + , haveModulus(false) + , useDelta(false) + , animationTemplate(priv) +{ +} + +QSpringAnimation::~QSpringAnimation() +{ + if (animationTemplate) { + if (target.object()) { + QSpringAnimation::ActiveAnimationHash::iterator it = + animationTemplate->activeAnimations.find(target); + if (it != animationTemplate->activeAnimations.end() && it.value() == this) + animationTemplate->activeAnimations.erase(it); + } else { + //target is no longer valid, need to search linearly + QSpringAnimation::ActiveAnimationHash::iterator it; + for (it = animationTemplate->activeAnimations.begin(); it != animationTemplate->activeAnimations.end(); ++it) { + if (it.value() == this) { + animationTemplate->activeAnimations.erase(it); + break; + } + } + } + } +} + +int QSpringAnimation::duration() const +{ + return -1; +} + +void QSpringAnimation::restart() +{ + if (isRunning() || (stopTime != -1 && (animationTemplate->elapsed.elapsed() - stopTime) < DELAY_STOP_TIMER_INTERVAL)) { + useDelta = true; + init(); + lastTime = 0; + } else { + useDelta = false; + //init() will be triggered when group starts + } +} + +void QSpringAnimation::init() +{ + lastTime = startTime = 0; + stopTime = -1; +} + +void QSpringAnimation::updateCurrentTime(int time) { if (mode == Track) { - clock->stop(); + stop(); return; } - int elapsed = time - lastTime; + + int elapsed = useDelta ? QDeclarativeAnimationTimer::instance()->currentDelta() : time - lastTime; + if (useDelta) { + startTime = time - elapsed; + useDelta = false; + } + if (!elapsed) return; + int count = elapsed / 16; + if (mode == Spring) { if (elapsed < 16) // capped at 62fps. return; - int count = elapsed / 16; lastTime = time - (elapsed - count * 16); } else { lastTime = time; } - QMutableHashIterator<QDeclarativeProperty, SpringAnimation> it(activeAnimations); - while (it.hasNext()) { - it.next(); - if (animate(it.key(), it.value(), elapsed)) - it.remove(); - } - - if (activeAnimations.isEmpty()) - clock->stop(); -} - -bool QDeclarativeSpringAnimationPrivate::animate(const QDeclarativeProperty &property, SpringAnimation &animation, int elapsed) -{ - qreal srcVal = animation.to; + qreal srcVal = to; - bool stop = false; + bool stopped = false; if (haveModulus) { - animation.currentValue = fmod(animation.currentValue, modulus); + currentValue = fmod(currentValue, modulus); srcVal = fmod(srcVal, modulus); } if (mode == Spring) { // Real men solve the spring DEs using RK4. // We'll do something much simpler which gives a result that looks fine. - int count = elapsed / 16; for (int i = 0; i < count; ++i) { - qreal diff = srcVal - animation.currentValue; + qreal diff = srcVal - currentValue; if (haveModulus && qAbs(diff) > modulus / 2) { if (diff < 0) diff += modulus; @@ -158,31 +255,31 @@ bool QDeclarativeSpringAnimationPrivate::animate(const QDeclarativeProperty &pro diff -= modulus; } if (useMass) - animation.velocity = animation.velocity + (spring * diff - damping * animation.velocity) / mass; + velocity = velocity + (spring * diff - damping * velocity) / mass; else - animation.velocity = animation.velocity + spring * diff - damping * animation.velocity; + velocity = velocity + spring * diff - damping * velocity; if (maxVelocity > 0.) { // limit velocity - if (animation.velocity > maxVelocity) - animation.velocity = maxVelocity; - else if (animation.velocity < -maxVelocity) - animation.velocity = -maxVelocity; + if (velocity > maxVelocity) + velocity = maxVelocity; + else if (velocity < -maxVelocity) + velocity = -maxVelocity; } - animation.currentValue += animation.velocity * 16.0 / 1000.0; + currentValue += velocity * 16.0 / 1000.0; if (haveModulus) { - animation.currentValue = fmod(animation.currentValue, modulus); - if (animation.currentValue < 0.0) - animation.currentValue += modulus; + currentValue = fmod(currentValue, modulus); + if (currentValue < 0.0) + currentValue += modulus; } } - if (qAbs(animation.velocity) < epsilon && qAbs(srcVal - animation.currentValue) < epsilon) { - animation.velocity = 0.0; - animation.currentValue = srcVal; - stop = true; + if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) { + velocity = 0.0; + currentValue = srcVal; + stopped = true; } } else { qreal moveBy = elapsed * velocityms; - qreal diff = srcVal - animation.currentValue; + qreal diff = srcVal - currentValue; if (haveModulus && qAbs(diff) > modulus / 2) { if (diff < 0) diff += modulus; @@ -190,45 +287,54 @@ bool QDeclarativeSpringAnimationPrivate::animate(const QDeclarativeProperty &pro diff -= modulus; } if (diff > 0) { - animation.currentValue += moveBy; + currentValue += moveBy; if (haveModulus) - animation.currentValue = fmod(animation.currentValue, modulus); + currentValue = fmod(currentValue, modulus); } else { - animation.currentValue -= moveBy; - if (haveModulus && animation.currentValue < 0.0) - animation.currentValue = fmod(animation.currentValue, modulus) + modulus; + currentValue -= moveBy; + if (haveModulus && currentValue < 0.0) + currentValue = fmod(currentValue, modulus) + modulus; } - if (lastTime - animation.start >= animation.duration) { - animation.currentValue = animation.to; - stop = true; + if (lastTime - startTime >= dura) { + currentValue = to; + stopped = true; } } - qreal old_to = animation.to; + qreal old_to = to; - QDeclarativePropertyPrivate::write(property, animation.currentValue, + QDeclarativePropertyPrivate::write(target, currentValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); - return (stop && old_to == animation.to); // do not stop if we got restarted + if (stopped && old_to == to) { // do not stop if we got restarted + stopTime = animationTemplate->elapsed.elapsed(); + stop(); + } +} + +void QSpringAnimation::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State /*oldState*/) +{ + if (newState == QAbstractAnimationJob::Running) + init(); } void QDeclarativeSpringAnimationPrivate::updateMode() { if (spring == 0. && maxVelocity == 0.) - mode = Track; + mode = QSpringAnimation::Track; else if (spring > 0.) - mode = Spring; + mode = QSpringAnimation::Spring; else { - mode = Velocity; - QHash<QDeclarativeProperty, SpringAnimation>::iterator it; + mode = QSpringAnimation::Velocity; + QSpringAnimation::ActiveAnimationHash::iterator it; for (it = activeAnimations.begin(); it != activeAnimations.end(); ++it) { - SpringAnimation &animation = *it; - animation.start = lastTime; - qreal dist = qAbs(animation.currentValue - animation.to); + QSpringAnimation *animation = *it; + animation->startTime = animation->lastTime; + qreal dist = qAbs(animation->currentValue - animation->to); if (haveModulus && dist > modulus / 2) dist = modulus - fmod(dist, modulus); - animation.duration = dist / velocityms; + animation->dura = dist / velocityms; } } } @@ -264,12 +370,15 @@ void QDeclarativeSpringAnimationPrivate::updateMode() QDeclarativeSpringAnimation::QDeclarativeSpringAnimation(QObject *parent) : QDeclarativeNumberAnimation(*(new QDeclarativeSpringAnimationPrivate),parent) { - Q_D(QDeclarativeSpringAnimation); - d->clock = new QDeclarativeSpringAnimationPrivate::Clock(d, this); } QDeclarativeSpringAnimation::~QDeclarativeSpringAnimation() { + Q_D(QDeclarativeSpringAnimation); + QSpringAnimation::ActiveAnimationHash::iterator it; + for (it = d->activeAnimations.begin(); it != d->activeAnimations.end(); ++it) { + it.value()->clearTemplate(); + } } /*! @@ -415,48 +524,69 @@ void QDeclarativeSpringAnimation::setMass(qreal mass) } } -void QDeclarativeSpringAnimation::transition(QDeclarativeStateActions &actions, - QDeclarativeProperties &modified, - TransitionDirection direction) +QAbstractAnimationJob* QDeclarativeSpringAnimation::transition(QDeclarativeStateActions &actions, + QDeclarativeProperties &modified, + TransitionDirection direction) { Q_D(QDeclarativeSpringAnimation); Q_UNUSED(direction); - if (d->clock->state() != QAbstractAnimation::Running) { - d->lastTime = 0; - } - - QDeclarativeNumberAnimation::transition(actions, modified, direction); - - if (!d->actions) - return; + QParallelAnimationGroupJob *wrapperGroup = new QParallelAnimationGroupJob(); + + QDeclarativeStateActions dataActions = QDeclarativeNumberAnimation::createTransitionActions(actions, modified); + if (!dataActions.isEmpty()) { + QSet<QAbstractAnimationJob*> anims; + for (int i = 0; i < dataActions.size(); ++i) { + QSpringAnimation *animation; + bool needsRestart = false; + const QDeclarativeProperty &property = dataActions.at(i).property; + if (d->activeAnimations.contains(property)) { + animation = d->activeAnimations[property]; + needsRestart = true; + } else { + animation = new QSpringAnimation(d); + d->activeAnimations.insert(property, animation); + animation->target = property; + } + wrapperGroup->appendAnimation(initInstance(animation)); + + animation->to = dataActions.at(i).toValue.toReal(); + animation->startTime = 0; + animation->velocityms = d->velocityms; + animation->mass = d->mass; + animation->spring = d->spring; + animation->damping = d->damping; + animation->epsilon = d->epsilon; + animation->modulus = d->modulus; + animation->useMass = d->useMass; + animation->haveModulus = d->haveModulus; + animation->mode = d->mode; + animation->dura = -1; + animation->maxVelocity = d->maxVelocity; - if (!d->actions->isEmpty()) { - for (int i = 0; i < d->actions->size(); ++i) { - const QDeclarativeProperty &property = d->actions->at(i).property; - QDeclarativeSpringAnimationPrivate::SpringAnimation &animation - = d->activeAnimations[property]; - animation.to = d->actions->at(i).toValue.toReal(); - animation.start = d->lastTime; if (d->fromIsDefined) - animation.currentValue = d->actions->at(i).fromValue.toReal(); + animation->currentValue = dataActions.at(i).fromValue.toReal(); else - animation.currentValue = property.read().toReal(); - if (d->mode == QDeclarativeSpringAnimationPrivate::Velocity) { - qreal dist = qAbs(animation.currentValue - animation.to); + animation->currentValue = property.read().toReal(); + if (animation->mode == QSpringAnimation::Velocity) { + qreal dist = qAbs(animation->currentValue - animation->to); if (d->haveModulus && dist > d->modulus / 2) dist = d->modulus - fmod(dist, d->modulus); - animation.duration = dist / d->velocityms; + animation->dura = dist / animation->velocityms; + } + + if (needsRestart) + animation->restart(); + anims.insert(animation); + } + foreach (QSpringAnimation *anim, d->activeAnimations.values()){ + if (!anims.contains(anim)) { + anim->clearTemplate(); + d->activeAnimations.remove(anim->target); } } } -} - - -QAbstractAnimation *QDeclarativeSpringAnimation::qtAnimation() -{ - Q_D(QDeclarativeSpringAnimation); - return d->clock; + return wrapperGroup; } QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativespringanimation_p.h b/src/quick/util/qdeclarativespringanimation_p.h index 169cd89e9d..21515d087b 100644 --- a/src/quick/util/qdeclarativespringanimation_p.h +++ b/src/quick/util/qdeclarativespringanimation_p.h @@ -52,7 +52,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QDeclarativeSpringAnimationPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeSpringAnimation : public QDeclarativeNumberAnimation +class Q_QUICK_PRIVATE_EXPORT QDeclarativeSpringAnimation : public QDeclarativeNumberAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeSpringAnimation) @@ -87,13 +87,10 @@ public: qreal modulus() const; void setModulus(qreal modulus); - virtual void transition(QDeclarativeStateActions &actions, + virtual QAbstractAnimationJob* transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); -protected: - virtual QAbstractAnimation *qtAnimation(); - Q_SIGNALS: void modulusChanged(); void massChanged(); diff --git a/src/quick/util/qdeclarativetimeline.cpp b/src/quick/util/qdeclarativetimeline.cpp index b38f361e88..a33fdd5104 100644 --- a/src/quick/util/qdeclarativetimeline.cpp +++ b/src/quick/util/qdeclarativetimeline.cpp @@ -311,7 +311,7 @@ qreal QDeclarativeTimeLinePrivate::value(const Op &op, int time, qreal base, boo Construct a new QDeclarativeTimeLine with the specified \a parent. */ QDeclarativeTimeLine::QDeclarativeTimeLine(QObject *parent) -: QAbstractAnimation(parent) + : QObject(parent) { d = new QDeclarativeTimeLinePrivate(this); } diff --git a/src/quick/util/qdeclarativetimeline_p_p.h b/src/quick/util/qdeclarativetimeline_p_p.h index 2f82bd75ae..421e2e5976 100644 --- a/src/quick/util/qdeclarativetimeline_p_p.h +++ b/src/quick/util/qdeclarativetimeline_p_p.h @@ -54,7 +54,7 @@ // #include <QtCore/QObject> -#include <QtCore/QAbstractAnimation> +#include "private/qabstractanimationjob_p.h" QT_BEGIN_NAMESPACE @@ -63,7 +63,7 @@ class QDeclarativeTimeLineValue; class QDeclarativeTimeLineCallback; struct QDeclarativeTimeLinePrivate; class QDeclarativeTimeLineObject; -class Q_AUTOTEST_EXPORT QDeclarativeTimeLine : public QAbstractAnimation +class Q_AUTOTEST_EXPORT QDeclarativeTimeLine : public QObject, QAbstractAnimationJob { Q_OBJECT public: diff --git a/src/quick/util/qdeclarativetimer.cpp b/src/quick/util/qdeclarativetimer.cpp index e4ec54f7eb..f54e9b305a 100644 --- a/src/quick/util/qdeclarativetimer.cpp +++ b/src/quick/util/qdeclarativetimer.cpp @@ -42,7 +42,7 @@ #include "qdeclarativetimer_p.h" #include <QtCore/qcoreapplication.h> -#include <QtCore/qpauseanimation.h> +#include "private/qpauseanimationjob_p.h" #include <qdebug.h> #include <private/qobject_p.h> @@ -51,15 +51,19 @@ QT_BEGIN_NAMESPACE -class QDeclarativeTimerPrivate : public QObjectPrivate +class QDeclarativeTimerPrivate : public QObjectPrivate, public QAnimation2ChangeListener { Q_DECLARE_PUBLIC(QDeclarativeTimer) public: QDeclarativeTimerPrivate() : interval(1000), running(false), repeating(false), triggeredOnStart(false) , classBegun(false), componentComplete(false), firstTick(true) {} + + virtual void animationFinished(QAbstractAnimationJob *); + virtual void animationCurrentLoopChanged(QAbstractAnimationJob *) { Q_Q(QDeclarativeTimer); q->ticked(); } + int interval; - QPauseAnimation pause; + QPauseAnimationJob pause; bool running : 1; bool repeating : 1; bool triggeredOnStart : 1; @@ -111,8 +115,7 @@ QDeclarativeTimer::QDeclarativeTimer(QObject *parent) : QObject(*(new QDeclarativeTimerPrivate), parent) { Q_D(QDeclarativeTimer); - connect(&d->pause, SIGNAL(currentLoopChanged(int)), this, SLOT(ticked())); - connect(&d->pause, SIGNAL(finished()), this, SLOT(finished())); + d->pause.addAnimationChangeListener(d, QAbstractAnimationJob::Completion | QAbstractAnimationJob::CurrentLoop); d->pause.setLoopCount(1); d->pause.setDuration(d->interval); } @@ -310,15 +313,15 @@ void QDeclarativeTimer::ticked() d->firstTick = false; } -void QDeclarativeTimer::finished() +void QDeclarativeTimerPrivate::animationFinished(QAbstractAnimationJob *) { - Q_D(QDeclarativeTimer); - if (d->repeating || !d->running) + Q_Q(QDeclarativeTimer); + if (repeating || !running) return; - d->running = false; - d->firstTick = false; - emit triggered(); - emit runningChanged(); + running = false; + firstTick = false; + emit q->triggered(); + emit q->runningChanged(); } QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativetimer_p.h b/src/quick/util/qdeclarativetimer_p.h index 8cec031a12..e400b3dda3 100644 --- a/src/quick/util/qdeclarativetimer_p.h +++ b/src/quick/util/qdeclarativetimer_p.h @@ -45,7 +45,6 @@ #include <qdeclarative.h> #include <QtCore/qobject.h> -#include <QtCore/qabstractanimation.h> #include <private/qtquickglobal_p.h> @@ -101,7 +100,6 @@ private: private Q_SLOTS: void ticked(); - void finished(); }; QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativetransition.cpp b/src/quick/util/qdeclarativetransition.cpp index 12966b53f7..2a05dd20d3 100644 --- a/src/quick/util/qdeclarativetransition.cpp +++ b/src/quick/util/qdeclarativetransition.cpp @@ -48,7 +48,7 @@ #include "qdeclarativeanimation_p_p.h" #include "qdeclarativetransitionmanager_p_p.h" -#include <QParallelAnimationGroup> +#include "private/qparallelanimationgroupjob_p.h" QT_BEGIN_NAMESPACE @@ -96,16 +96,44 @@ QT_BEGIN_NAMESPACE \sa {QML Animation and Transitions}, {declarative/animation/states}{states example}, {qmlstates}{States}, {QtDeclarative} */ +QDeclarativeTransitionInstance::QDeclarativeTransitionInstance() + : m_anim(0) +{ +} + +QDeclarativeTransitionInstance::~QDeclarativeTransitionInstance() +{ + delete m_anim; +} + +void QDeclarativeTransitionInstance::start() +{ + if (m_anim) + m_anim->start(); +} + +void QDeclarativeTransitionInstance::stop() +{ + if (m_anim) + m_anim->stop(); +} + +bool QDeclarativeTransitionInstance::isRunning() const +{ + return m_anim && m_anim->state() == QAbstractAnimationJob::Running; +} + + //ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting //and disconnecting signals and slots frequently -class ParallelAnimationWrapper : public QParallelAnimationGroup +class ParallelAnimationWrapper : public QParallelAnimationGroupJob { - Q_OBJECT public: - ParallelAnimationWrapper(QObject *parent = 0) : QParallelAnimationGroup(parent) {} - QDeclarativeTransitionPrivate *trans; + ParallelAnimationWrapper() : QParallelAnimationGroupJob() {} + QDeclarativeTransitionManager *manager; + protected: - virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); + virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); }; class QDeclarativeTransitionPrivate : public QObjectPrivate @@ -114,9 +142,8 @@ class QDeclarativeTransitionPrivate : public QObjectPrivate public: QDeclarativeTransitionPrivate() : fromState(QLatin1String("*")), toState(QLatin1String("*")), - reversed(false), reversible(false), enabled(true), manager(0) + reversed(false), reversible(false), enabled(true) { - group.trans = this; } QString fromState; @@ -124,13 +151,7 @@ public: bool reversed; bool reversible; bool enabled; - ParallelAnimationWrapper group; - QDeclarativeTransitionManager *manager; - void complete() - { - manager->complete(); - } static void append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a); static int animation_count(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list); static QDeclarativeAbstractAnimation* animation_at(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, int pos); @@ -142,7 +163,6 @@ void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QD { QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object); q->d_func()->animations.append(a); - q->d_func()->group.addAnimation(a->qtAnimation()); a->setDisableUserControl(); } @@ -163,24 +183,22 @@ void QDeclarativeTransitionPrivate::clear_animations(QDeclarativeListProperty<QD QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object); while (q->d_func()->animations.count()) { QDeclarativeAbstractAnimation *firstAnim = q->d_func()->animations.at(0); - q->d_func()->group.removeAnimation(firstAnim->qtAnimation()); q->d_func()->animations.removeAll(firstAnim); } } -void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) +void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) { - QParallelAnimationGroup::updateState(newState, oldState); + QParallelAnimationGroupJob::updateState(newState, oldState); if (newState == Stopped && (duration() == -1 - || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) - || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0))) + || (direction() == QAbstractAnimationJob::Forward && currentLoopTime() == duration()) + || (direction() == QAbstractAnimationJob::Backward && currentLoopTime() == 0))) { - trans->complete(); + manager->complete(); } } - QDeclarativeTransition::QDeclarativeTransition(QObject *parent) : QObject(*(new QDeclarativeTransitionPrivate), parent) { @@ -188,12 +206,7 @@ QDeclarativeTransition::QDeclarativeTransition(QObject *parent) QDeclarativeTransition::~QDeclarativeTransition() { -} - -void QDeclarativeTransition::stop() -{ Q_D(QDeclarativeTransition); - d->group.stop(); } void QDeclarativeTransition::setReversed(bool r) @@ -202,7 +215,7 @@ void QDeclarativeTransition::setReversed(bool r) d->reversed = r; } -void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &actions, +QDeclarativeTransitionInstance *QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &actions, QList<QDeclarativeProperty> &after, QDeclarativeTransitionManager *manager) { @@ -210,19 +223,26 @@ void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &act qmlExecuteDeferred(this); - if (d->reversed) { - for (int ii = d->animations.count() - 1; ii >= 0; --ii) { - d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Backward); - } - } else { - for (int ii = 0; ii < d->animations.count(); ++ii) { - d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Forward); - } + ParallelAnimationWrapper *group = new ParallelAnimationWrapper(); + group->manager = manager; + + QDeclarativeAbstractAnimation::TransitionDirection direction = d->reversed ? QDeclarativeAbstractAnimation::Backward : QDeclarativeAbstractAnimation::Forward; + int start = d->reversed ? d->animations.count() - 1 : 0; + int end = d->reversed ? -1 : d->animations.count(); + + QAbstractAnimationJob *anim = 0; + for (int i = start; i != end;) { + anim = d->animations.at(i)->transition(actions, after, direction); + if (anim) + d->reversed ? group->prependAnimation(anim) : group->appendAnimation(anim); + d->reversed ? --i : ++i; } - d->manager = manager; - d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward); - d->group.start(); + group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward); + + QDeclarativeTransitionInstance *wrapper = new QDeclarativeTransitionInstance; + wrapper->m_anim = group; + return wrapper; } /*! @@ -389,4 +409,4 @@ QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeTransition:: QT_END_NAMESPACE -#include <qdeclarativetransition.moc> +//#include <qdeclarativetransition.moc> diff --git a/src/quick/util/qdeclarativetransition_p.h b/src/quick/util/qdeclarativetransition_p.h index a4f6dc46a5..64fd45b725 100644 --- a/src/quick/util/qdeclarativetransition_p.h +++ b/src/quick/util/qdeclarativetransition_p.h @@ -43,7 +43,6 @@ #define QDECLARATIVETRANSITION_H #include "qdeclarativestate_p.h" - #include <qdeclarative.h> #include <QtCore/qobject.h> @@ -55,6 +54,25 @@ QT_BEGIN_NAMESPACE class QDeclarativeAbstractAnimation; class QDeclarativeTransitionPrivate; class QDeclarativeTransitionManager; +class QDeclarativeTransition; +class QAbstractAnimationJob; + +class Q_QUICK_EXPORT QDeclarativeTransitionInstance +{ +public: + QDeclarativeTransitionInstance(); + ~QDeclarativeTransitionInstance(); + + void start(); + void stop(); + + bool isRunning() const; + +private: + QAbstractAnimationJob *m_anim; + friend class QDeclarativeTransition; +}; + class Q_QUICK_EXPORT QDeclarativeTransition : public QObject { Q_OBJECT @@ -86,12 +104,11 @@ public: QDeclarativeListProperty<QDeclarativeAbstractAnimation> animations(); - void prepare(QDeclarativeStateOperation::ActionList &actions, + QDeclarativeTransitionInstance *prepare(QDeclarativeStateOperation::ActionList &actions, QList<QDeclarativeProperty> &after, QDeclarativeTransitionManager *end); void setReversed(bool r); - void stop(); Q_SIGNALS: void fromChanged(); diff --git a/src/quick/util/qdeclarativetransitionmanager.cpp b/src/quick/util/qdeclarativetransitionmanager.cpp index 5542548937..a2de7dbae6 100644 --- a/src/quick/util/qdeclarativetransitionmanager.cpp +++ b/src/quick/util/qdeclarativetransitionmanager.cpp @@ -43,7 +43,6 @@ #include "qdeclarativetransition_p.h" #include "qdeclarativestate_p_p.h" -#include "qdeclarativestate_p.h" #include <private/qdeclarativebinding_p.h> #include <private/qdeclarativeglobal_p.h> @@ -59,12 +58,12 @@ class QDeclarativeTransitionManagerPrivate { public: QDeclarativeTransitionManagerPrivate() - : state(0) {} + : state(0), transitionInstance(0) {} void applyBindings(); typedef QList<QDeclarativeSimpleAction> SimpleActionList; QDeclarativeState *state; - QDeclarativeGuard<QDeclarativeTransition> transition; + QDeclarativeTransitionInstance *transitionInstance; QDeclarativeStateOperation::ActionList bindingsList; SimpleActionList completeList; }; @@ -81,9 +80,15 @@ void QDeclarativeTransitionManager::setState(QDeclarativeState *s) QDeclarativeTransitionManager::~QDeclarativeTransitionManager() { + delete d->transitionInstance; delete d; d = 0; } +bool QDeclarativeTransitionManager::isRunning() const +{ + return d->transitionInstance && d->transitionInstance->isRunning(); +} + void QDeclarativeTransitionManager::complete() { d->applyBindings(); @@ -97,6 +102,8 @@ void QDeclarativeTransitionManager::complete() if (d->state) static_cast<QDeclarativeStatePrivate*>(QObjectPrivate::get(d->state))->complete(); + + finished(); } void QDeclarativeTransitionManagerPrivate::applyBindings() @@ -116,6 +123,10 @@ void QDeclarativeTransitionManagerPrivate::applyBindings() bindingsList.clear(); } +void QDeclarativeTransitionManager::finished() +{ +} + void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> &list, QDeclarativeTransition *transition) { @@ -196,8 +207,11 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> & if (transition) { QList<QDeclarativeProperty> touched; - d->transition = transition; - d->transition->prepare(applyList, touched, this); + QDeclarativeTransitionInstance *oldInstance = d->transitionInstance; + d->transitionInstance = transition->prepare(applyList, touched, this); + d->transitionInstance->start(); + if (oldInstance && oldInstance != d->transitionInstance) + delete oldInstance; // Modify the action list to remove actions handled in the transition for (int ii = 0; ii < applyList.count(); ++ii) { @@ -257,11 +271,8 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> & void QDeclarativeTransitionManager::cancel() { - if (d->transition) { - // ### this could potentially trigger a complete in rare circumstances - d->transition->stop(); - d->transition = 0; - } + if (d->transitionInstance && d->transitionInstance->isRunning()) + d->transitionInstance->stop(); for(int i = 0; i < d->bindingsList.count(); ++i) { QDeclarativeAction action = d->bindingsList[i]; diff --git a/src/quick/util/qdeclarativetransitionmanager_p_p.h b/src/quick/util/qdeclarativetransitionmanager_p_p.h index adbde004df..4e5d1a9617 100644 --- a/src/quick/util/qdeclarativetransitionmanager_p_p.h +++ b/src/quick/util/qdeclarativetransitionmanager_p_p.h @@ -54,6 +54,7 @@ // #include "qdeclarativestateoperations_p.h" +#include "qdeclarativeanimation_p.h" QT_BEGIN_NAMESPACE @@ -65,10 +66,15 @@ public: QDeclarativeTransitionManager(); ~QDeclarativeTransitionManager(); + bool isRunning() const; + void transition(const QList<QDeclarativeAction> &, QDeclarativeTransition *transition); void cancel(); +protected: + virtual void finished(); + private: Q_DISABLE_COPY(QDeclarativeTransitionManager) QDeclarativeTransitionManagerPrivate *d; @@ -77,7 +83,7 @@ private: void setState(QDeclarativeState *); friend class QDeclarativeState; - friend class QDeclarativeTransitionPrivate; + friend class ParallelAnimationWrapper; }; QT_END_NAMESPACE diff --git a/src/quick/util/qdeclarativeutilmodule.cpp b/src/quick/util/qdeclarativeutilmodule.cpp index 80f517c9a1..1841a8c94f 100644 --- a/src/quick/util/qdeclarativeutilmodule.cpp +++ b/src/quick/util/qdeclarativeutilmodule.cpp @@ -59,6 +59,7 @@ #include "qdeclarativetransition_p.h" #include <qdeclarativeinfo.h> #include <private/qdeclarativetypenotavailable_p.h> +#include <private/qdeclarativeanimationcontroller_p.h> #include <QtCore/qcoreapplication.h> #include <QtGui/QInputPanel> @@ -83,6 +84,7 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeScriptAction>("QtQuick",2,0,"ScriptAction"); qmlRegisterType<QDeclarativeSequentialAnimation>("QtQuick",2,0,"SequentialAnimation"); qmlRegisterType<QDeclarativeSpringAnimation>("QtQuick",2,0,"SpringAnimation"); + qmlRegisterType<QDeclarativeAnimationController>("QtQuick",2,0,"AnimationController"); qmlRegisterType<QDeclarativeStateChangeScript>("QtQuick",2,0,"StateChangeScript"); qmlRegisterType<QDeclarativeStateGroup>("QtQuick",2,0,"StateGroup"); qmlRegisterType<QDeclarativeState>("QtQuick",2,0,"State"); diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index 9c8964bfef..d933459596 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -6,6 +6,7 @@ SOURCES += \ $$PWD/qdeclarativesystempalette.cpp \ $$PWD/qdeclarativespringanimation.cpp \ $$PWD/qdeclarativesmoothedanimation.cpp \ + $$PWD/qdeclarativeanimationcontroller.cpp \ $$PWD/qdeclarativestate.cpp\ $$PWD/qdeclarativetransitionmanager.cpp \ $$PWD/qdeclarativestateoperations.cpp \ @@ -34,6 +35,7 @@ HEADERS += \ $$PWD/qdeclarativeanimation_p_p.h \ $$PWD/qdeclarativesystempalette_p.h \ $$PWD/qdeclarativespringanimation_p.h \ + $$PWD/qdeclarativeanimationcontroller_p.h \ $$PWD/qdeclarativesmoothedanimation_p.h \ $$PWD/qdeclarativesmoothedanimation_p_p.h \ $$PWD/qdeclarativestate_p.h\ @@ -56,4 +58,4 @@ HEADERS += \ $$PWD/qdeclarativechangeset_p.h \ $$PWD/qdeclarativelistcompositor_p.h \ $$PWD/qdeclarativepathinterpolator_p.h \ - $$PWD/qdeclarativesvgparser_p.h + $$PWD/qdeclarativesvgparser_p.h
\ No newline at end of file |