diff options
Diffstat (limited to 'src/quick/items/qquickanimation.cpp')
-rw-r--r-- | src/quick/items/qquickanimation.cpp | 487 |
1 files changed, 365 insertions, 122 deletions
diff --git a/src/quick/items/qquickanimation.cpp b/src/quick/items/qquickanimation.cpp index 34377e92dd..517b504640 100644 --- a/src/quick/items/qquickanimation.cpp +++ b/src/quick/items/qquickanimation.cpp @@ -48,36 +48,66 @@ #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 -QQuickParentAnimation::QQuickParentAnimation(QObject *parent) - : QDeclarativeAnimationGroup(*(new QQuickParentAnimationPrivate), parent) -{ - Q_D(QQuickParentAnimation); - d->topLevelGroup = new QSequentialAnimationGroup; - QDeclarative_setParent_noEvent(d->topLevelGroup, this); +/*! + \qmlclass ParentAnimation QQuickParentAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \since QtQuick 2.0 + \inherits Animation + \brief The ParentAnimation element animates changes in parent values. + + ParentAnimation is used to animate a parent change for an \l Item. - d->startAction = new QActionAnimation; - QDeclarative_setParent_noEvent(d->startAction, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->startAction); + For example, the following ParentChange changes \c blueRect to become + a child of \c redRect when it is clicked. The inclusion of the + ParentAnimation, which defines a NumberAnimation to be applied during + the transition, ensures the item animates smoothly as it moves to + its new parent: - d->ag = new QParallelAnimationGroup; - QDeclarative_setParent_noEvent(d->ag, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->ag); + \snippet doc/src/snippets/declarative/parentanimation.qml 0 - d->endAction = new QActionAnimation; - QDeclarative_setParent_noEvent(d->endAction, d->topLevelGroup); - d->topLevelGroup->addAnimation(d->endAction); + A ParentAnimation can contain any number of animations. These animations will + be run in parallel; to run them sequentially, define them within a + SequentialAnimation. + + In some cases, such as when reparenting between items with clipping enabled, it is useful + to animate the parent change via another item that does not have clipping + enabled. Such an item can be set using the \l via property. + + For convenience, when a ParentAnimation is used in a \l Transition, it will + animate any ParentChange that has occurred during the state change. + This can be overridden by setting a specific target item using the + \l target property. + + Like any other animation element, a ParentAnimation can be applied in a + number of ways, including transitions, behaviors and property value + sources. The \l {QML Animation and Transitions} documentation shows a + variety of methods for creating animations. + + \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example} +*/ +QQuickParentAnimation::QQuickParentAnimation(QObject *parent) + : QDeclarativeAnimationGroup(*(new QQuickParentAnimationPrivate), parent) +{ } QQuickParentAnimation::~QQuickParentAnimation() { } +/*! + \qmlproperty Item QtQuick2::ParentAnimation::target + The item to reparent. + + When used in a transition, if no target is specified, all + ParentChange occurrences are animated by the ParentAnimation. +*/ QQuickItem *QQuickParentAnimation::target() const { Q_D(const QQuickParentAnimation); @@ -94,6 +124,15 @@ void QQuickParentAnimation::setTarget(QQuickItem *target) emit targetChanged(); } +/*! + \qmlproperty Item QtQuick2::ParentAnimation::newParent + The new parent to animate to. + + If the ParentAnimation is defined within a \l Transition or \l Behavior, + this value defaults to the value defined in the end state of the + \l Transition, or the value of the property change that triggered the + \l Behavior. +*/ QQuickItem *QQuickParentAnimation::newParent() const { Q_D(const QQuickParentAnimation); @@ -110,6 +149,19 @@ void QQuickParentAnimation::setNewParent(QQuickItem *newParent) emit newParentChanged(); } +/*! + \qmlproperty Item QtQuick2::ParentAnimation::via + The item to reparent via. This provides a way to do an unclipped animation + when both the old parent and new parent are clipped. + + \qml + ParentAnimation { + target: myItem + via: topLevelItem + // ... + } + \endqml +*/ QQuickItem *QQuickParentAnimation::via() const { Q_D(const QQuickParentAnimation); @@ -152,7 +204,7 @@ QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::Transfo } } -void QQuickParentAnimation::transition(QDeclarativeStateActions &actions, +QAbstractAnimationJob* QQuickParentAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) { @@ -318,63 +370,105 @@ 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); - } - + return initInstance(topLevelGroup); } -QAbstractAnimation *QQuickParentAnimation::qtAnimation() -{ - Q_D(QQuickParentAnimation); - return d->topLevelGroup; -} +/*! + \qmlclass AnchorAnimation QQuickAnchorAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \inherits Animation + \brief The AnchorAnimation element animates changes in anchor values. + + AnchorAnimation is used to animate an anchor change. + In the following snippet we animate the addition of a right anchor to a \l Rectangle: + + \snippet doc/src/snippets/declarative/anchoranimation.qml 0 + + For convenience, when an AnchorAnimation is used in a \l Transition, it will + animate any AnchorChanges that have occurred during the state change. + This can be overridden by setting a specific target item using the + \l target property. + + Like any other animation element, an AnchorAnimation can be applied in a + number of ways, including transitions, behaviors and property value + sources. The \l {QML Animation and Transitions} documentation shows a + variety of methods for creating animations. + + \sa {QML Animation and Transitions}, AnchorChanges +*/ 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. + If no targets are specified all AnchorChanges will be + animated by the AnchorAnimation. +*/ QDeclarativeListProperty<QQuickItem> QQuickAnchorAnimation::targets() { Q_D(QQuickAnchorAnimation); return QDeclarativeListProperty<QQuickItem>(this, d->targets); } +/*! + \qmlproperty int QtQuick2::AnchorAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ int QQuickAnchorAnimation::duration() const { Q_D(const QQuickAnchorAnimation); - return d->va->duration(); + return d->duration; } void QQuickAnchorAnimation::setDuration(int duration) @@ -385,29 +479,47 @@ 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); } +/*! + \qmlproperty enumeration QtQuick2::AnchorAnimation::easing.type + \qmlproperty real QtQuick2::AnchorAnimation::easing.amplitude + \qmlproperty real QtQuick2::AnchorAnimation::easing.overshoot + \qmlproperty real QtQuick2::AnchorAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period and/or overshoot. The default easing curve is + Linear. + + \qml + AnchorAnimation { easing.type: Easing.InOutQuad } + \endqml + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ 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) { @@ -416,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; @@ -429,35 +540,65 @@ 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); } +/*! + \qmlclass PathAnimation QQuickPathAnimation + \inqmlmodule QtQuick 2 + \ingroup qml-animation-transition + \inherits Animation + \brief The PathAnimation element animates an item along a path. + + When used in a transition, the path can be specified without start + or end points, for example: + \qml + PathAnimation { + path: Path { + //no startX, startY + PathCurve { x: 100; y: 100} + PathCurve {} //last element is empty with no end point specified + } + } + \endqml + + In the above case, the path start will be the item's current position, and the + path end will be the item's target position in the target state. + + \sa {QML Animation and Transitions}, PathInterpolator +*/ 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(); + } } +/*! + \qmlproperty int QtQuick2::PathAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ int QQuickPathAnimation::duration() const { Q_D(const QQuickPathAnimation); - return d->pa->duration(); + return d->duration; } void QQuickPathAnimation::setDuration(int duration) @@ -468,28 +609,48 @@ 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); } +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::easing.type + \qmlproperty real QtQuick2::PathAnimation::easing.amplitude + \qmlproperty list<real> QtQuick2::PathAnimation::easing.bezierCurve + \qmlproperty real QtQuick2::PathAnimation::easing.overshoot + \qmlproperty real QtQuick2::PathAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period, overshoot or custom bezierCurve data. The default easing curve is \c Easing.Linear. + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ 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); } +/*! + \qmlproperty Path QtQuick2::PathAnimation::path + This property holds the path to animate along. + + For more information on defining a path see the \l Path documentation. +*/ QDeclarativePath *QQuickPathAnimation::path() const { Q_D(const QQuickPathAnimation); @@ -506,6 +667,10 @@ void QQuickPathAnimation::setPath(QDeclarativePath *path) emit pathChanged(); } +/*! + \qmlproperty Item QtQuick2::PathAnimation::target + This property holds the item to animate. +*/ QQuickItem *QQuickPathAnimation::target() const { Q_D(const QQuickPathAnimation); @@ -522,6 +687,22 @@ void QQuickPathAnimation::setTarget(QQuickItem *target) emit targetChanged(); } +/*! + \qmlproperty enumeration QtQuick2::PathAnimation::orientation + This property controls the rotation of the item as it animates along the path. + + If a value other than \c Fixed is specified, the PathAnimation will rotate the + item to achieve the specified orientation as it travels along the path. + + \list + \o PathAnimation.Fixed (default) - the PathAnimation will not control + the rotation of the item. + \o PathAnimation.RightFirst - The right side of the item will lead along the path. + \o PathAnimation.LeftFirst - The left side of the item will lead along the path. + \o PathAnimation.BottomFirst - The bottom of the item will lead along the path. + \o PathAnimation.TopFirst - The top of the item will lead along the path. + \endlist +*/ QQuickPathAnimation::Orientation QQuickPathAnimation::orientation() const { Q_D(const QQuickPathAnimation); @@ -538,6 +719,15 @@ void QQuickPathAnimation::setOrientation(Orientation orientation) emit orientationChanged(d->orientation); } +/*! + \qmlproperty point QtQuick2::PathAnimation::anchorPoint + This property holds the anchor point for the item being animated. + + By default, the upper-left corner of the target (its 0,0 point) + will be anchored to (or follow) the path. The anchorPoint property can be used to + specify a different point for anchoring. For example, specifying an anchorPoint of + 5,5 for a 10x10 item means the center of the item will follow the path. +*/ QPointF QQuickPathAnimation::anchorPoint() const { Q_D(const QQuickPathAnimation); @@ -554,36 +744,66 @@ void QQuickPathAnimation::setAnchorPoint(const QPointF &point) emit anchorPointChanged(point); } -qreal QQuickPathAnimation::orientationEntryInterval() const +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationEntryDuration + This property holds the duration (in milliseconds) of the transition in to the orientation. + + If an orientation has been specified for the PathAnimation, and the starting + rotation of the item does not match that given by the orientation, + orientationEntryDuration can be used to smoothly transition from the item's + starting rotation to the rotation given by the path orientation. +*/ +int QQuickPathAnimation::orientationEntryDuration() const { Q_D(const QQuickPathAnimation); - return d->entryInterval; + return d->entryDuration; } -void QQuickPathAnimation::setOrientationEntryInterval(qreal interval) +void QQuickPathAnimation::setOrientationEntryDuration(int duration) { Q_D(QQuickPathAnimation); - if (d->entryInterval == interval) + if (d->entryDuration == duration) return; - d->entryInterval = interval; - emit orientationEntryIntervalChanged(interval); + d->entryDuration = duration; + emit orientationEntryDurationChanged(duration); } -qreal QQuickPathAnimation::orientationExitInterval() const +/*! + \qmlproperty real QtQuick2::PathAnimation::orientationExitDuration + This property holds the duration (in milliseconds) of the transition out of the orientation. + + If an orientation and endRotation have been specified for the PathAnimation, + orientationExitDuration can be used to smoothly transition from the rotation given + by the path orientation to the specified endRotation. +*/ +int QQuickPathAnimation::orientationExitDuration() const { Q_D(const QQuickPathAnimation); - return d->exitInterval; + return d->exitDuration; } -void QQuickPathAnimation::setOrientationExitInterval(qreal interval) +void QQuickPathAnimation::setOrientationExitDuration(int duration) { Q_D(QQuickPathAnimation); - if (d->exitInterval == interval) + if (d->exitDuration == duration) return; - d->exitInterval = interval; - emit orientationExitIntervalChanged(interval); + d->exitDuration = duration; + emit orientationExitDurationChanged(duration); } +/*! + \qmlproperty real QtQuick2::PathAnimation::endRotation + This property holds the ending rotation for the target. + + If an orientation has been specified for the PathAnimation, + and the path doesn't end with the item at the desired rotation, + the endRotation property can be used to manually specify an end + rotation. + + This property is typically used with orientationExitDuration, as specifying + an endRotation without an orientationExitDuration may cause a jump to + the final rotation, rather than a smooth transition. +*/ qreal QQuickPathAnimation::endRotation() const { Q_D(const QQuickPathAnimation); @@ -600,24 +820,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 = d->entryInterval; - data->exitInterval = d->exitInterval; + 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; @@ -645,46 +878,42 @@ void QQuickPathAnimation::transition(QDeclarativeStateActions &actions, (modified.count() > origModifiedSize || data->toDefined)) { data->target = d->target; data->path = d->path; - 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()); + data->path->invalidateSequentialHistory(); + 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) @@ -721,9 +950,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) { @@ -761,6 +988,7 @@ void QQuickPathAnimationUpdater::setValue(qreal v) } //smoothly transition to the desired orientation + //TODO: shortest distance calculations if (startRotation.isValid()) { if (reverse && v == 0.0) angle = startRotation; @@ -768,13 +996,13 @@ void QQuickPathAnimationUpdater::setValue(qreal v) angle = angle * v / entryInterval + startRotation * (entryInterval - v) / entryInterval; } if (endRotation.isValid()) { - qreal exitStart = 1 - exitInterval; + qreal exitStart = 1 - entryInterval; if (!reverse && v == 1.0) angle = endRotation; 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); } /* @@ -789,4 +1017,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 |