aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/animations/qabstractanimationjob.cpp2
-rw-r--r--src/qml/animations/qabstractanimationjob_p.h6
-rw-r--r--src/quick/doc/snippets/qml/animators.qml282
-rw-r--r--src/quick/items/qquickwindow.cpp10
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp23
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h2
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp7
-rw-r--r--src/quick/util/qquickanimation.cpp61
-rw-r--r--src/quick/util/qquickanimation_p.h10
-rw-r--r--src/quick/util/qquickanimationcontroller.cpp2
-rw-r--r--src/quick/util/qquickanimationcontroller_p.h2
-rw-r--r--src/quick/util/qquickanimator.cpp565
-rw-r--r--src/quick/util/qquickanimator_p.h196
-rw-r--r--src/quick/util/qquickanimator_p_p.h97
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp202
-rw-r--r--src/quick/util/qquickanimatorcontroller_p.h116
-rw-r--r--src/quick/util/qquickanimatorjob.cpp532
-rw-r--r--src/quick/util/qquickanimatorjob_p.h284
-rw-r--r--src/quick/util/qquickbehavior.cpp14
-rw-r--r--src/quick/util/qquicktransition.cpp7
-rw-r--r--src/quick/util/qquickutilmodule.cpp9
-rw-r--r--src/quick/util/util.pri11
-rw-r--r--tests/auto/quick/qquickanimators/data/Box.qml70
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_behavior.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_nested.qml92
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_on.qml79
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_opacity.qml76
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_parallel.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_restart.qml85
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_rotation.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_scale.qml75
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_sequential.qml74
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_transformorigin.qml160
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_transition.qml91
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_x.qml77
-rw-r--r--tests/auto/quick/qquickanimators/data/tst_y.qml77
-rw-r--r--tests/auto/quick/qquickanimators/qquickanimators.pro14
-rw-r--r--tests/auto/quick/qquickanimators/tst_qquickanimators.cpp44
41 files changed, 3804 insertions, 22 deletions
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index 343338c661..da961763ed 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -277,6 +277,8 @@ QAbstractAnimationJob::QAbstractAnimationJob()
, m_isGroup(false)
, m_disableUserControl(false)
, m_hasCurrentTimeChangeListeners(false)
+ , m_isRenderThreadJob(false)
+ , m_isRenderThreadProxy(false)
{
}
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index abf3cd6df6..95a238405c 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -113,6 +113,10 @@ public:
QAbstractAnimationJob *nextSibling() const { return m_nextSibling; }
QAbstractAnimationJob *previousSibling() const { return m_previousSibling; }
+ bool isGroup() const { return m_isGroup; }
+ bool isRenderThreadJob() const { return m_isRenderThreadJob; }
+ bool isRenderThreadProxy() const { return m_isRenderThreadProxy; }
+
protected:
virtual void updateCurrentTime(int) {}
virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
@@ -157,6 +161,8 @@ protected:
bool m_isGroup:1;
bool m_disableUserControl:1;
bool m_hasCurrentTimeChangeListeners:1;
+ bool m_isRenderThreadJob:1;
+ bool m_isRenderThreadProxy:1;
friend class QQmlAnimationTimer;
friend class QAnimationGroupJob;
diff --git a/src/quick/doc/snippets/qml/animators.qml b/src/quick/doc/snippets/qml/animators.qml
new file mode 100644
index 0000000000..4b9e4f4250
--- /dev/null
+++ b/src/quick/doc/snippets/qml/animators.qml
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Rectangle {
+
+ width: 320
+ height: 480
+
+ color: "steelblue"
+
+ Grid {
+ anchors.fill: parent
+ anchors.margins: 20
+ columnSpacing: 30
+ rowSpacing: 30
+ columns: 4
+ rows: 4
+
+ property real cellWidth: (width - (columns - 1) * columnSpacing) / columns;
+ property real cellHeight: (height - (rows - 1) * rowSpacing) / rows;
+
+ Item {
+ width: parent.cellWidth
+ height: parent.cellHeight
+//! [x on]
+Rectangle {
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ XAnimator on x {
+ from: 10;
+ to: 0;
+ duration: 1000
+ }
+}
+//! [x on]
+ }
+ Item {
+ width: parent.cellWidth
+ height: parent.cellHeight
+//! [x target]
+Rectangle {
+ id: xmovingBox
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ XAnimator {
+ target: xmovingBox;
+ from: 10;
+ to: 0;
+ duration: 1000
+ running: true
+ }
+}
+//! [x target]
+ }
+ Item {
+ width: parent.cellWidth
+ height: parent.cellHeight
+//! [y on]
+Rectangle {
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ YAnimator on y {
+ from: 10;
+ to: 0;
+ duration: 1000
+ }
+}
+//! [y on]
+ }
+ Item {
+ width: parent.cellWidth
+ height: parent.cellHeight
+//! [y target]
+Rectangle {
+ id: ymovingBox
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ YAnimator {
+ target: ymovingBox;
+ from: 10;
+ to: 0;
+ duration: 1000
+ running: true
+ }
+}
+//! [y target]
+ }
+//! [rotation on]
+Rectangle {
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ RotationAnimator on rotation {
+ from: 0;
+ to: 360;
+ duration: 1000
+ }
+}
+//! [rotation on]
+//! [rotation target]
+Rectangle {
+ id: rotatingBox
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ RotationAnimator {
+ target: rotatingBox;
+ from: 0;
+ to: 360;
+ duration: 1000
+ running: true
+ }
+}
+//! [rotation target]
+//! [scale on]
+Rectangle {
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ ScaleAnimator on scale {
+ from: 0.5;
+ to: 1;
+ duration: 1000
+ }
+}
+//! [scale on]
+//! [scale target]
+Rectangle {
+ id: scalingBox
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ ScaleAnimator {
+ target: scalingBox;
+ from: 0.5;
+ to: 1;
+ duration: 1000
+ running: true
+ }
+}
+//! [scale target]
+//! [opacity on]
+Rectangle {
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ OpacityAnimator on opacity{
+ from: 0;
+ to: 1;
+ duration: 1000
+ }
+}
+//! [opacity on]
+//! [opacity target]
+Rectangle {
+ id: opacityBox
+ width: 50
+ height: 50
+ color: "lightsteelblue"
+ OpacityAnimator {
+ target: opacityBox;
+ from: 0;
+ to: 1;
+ duration: 1000
+ running: true
+ }
+}
+//! [opacity target]
+//![shaderon]
+ShaderEffect {
+ width: 50
+ height: 50
+ property variant t;
+ UniformAnimator on t {
+ from: 0
+ to: 1
+ duration: 1000
+ }
+ fragmentShader:
+ "
+ uniform lowp float t;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ lowp float c = qt_TexCoord0.y;
+ gl_FragColor = vec4(c * t, 0, 0, 1);
+ }
+ "
+}
+//![shaderon]
+//![shader target]
+ShaderEffect {
+ id: shader
+ width: 50
+ height: 50
+ property variant t;
+ UniformAnimator {
+ target: shader
+ uniform: "t"
+ from: 0
+ to: 1
+ duration: 1000
+ running: true
+ }
+ fragmentShader:
+ "
+ uniform lowp float t;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ lowp float c = qt_TexCoord0.y;
+ gl_FragColor = vec4(0, 0, c * t, 1);
+ }
+ "
+}
+//![shader target]
+//![mixed]
+Rectangle {
+ id: mixBox
+ width: 50
+ height: 50
+ ParallelAnimation {
+ ColorAnimation {
+ target: mixBox
+ property: "color"
+ from: "forestgreen"
+ to: "lightsteelblue";
+ duration: 1000
+ }
+ ScaleAnimator {
+ target: mixBox
+ from: 2
+ to: 1
+ duration: 1000
+ }
+ running: true
+ }
+}
+//! [mixed]
+ }
+}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 5b4145e235..923b7605e1 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -53,6 +53,7 @@
#include <QtQuick/private/qsgflashnode_p.h>
#include <private/qsgrenderloop_p.h>
+#include <private/qquickanimatorcontroller_p.h>
#include <private/qguiapplication_p.h>
#include <QtGui/QInputMethod>
@@ -319,6 +320,8 @@ void QQuickWindowPrivate::syncSceneGraph()
QML_MEMORY_SCOPE_STRING("SceneGraph");
Q_Q(QQuickWindow);
+ animationController->beforeNodeSync();
+
emit q->beforeSynchronizing();
if (!renderer) {
forceUpdate(contentItem);
@@ -331,6 +334,8 @@ void QQuickWindowPrivate::syncSceneGraph()
updateDirtyNodes();
+ animationController->afterNodeSync();
+
// Copy the current state of clearing from window into renderer.
renderer->setClearColor(clearColor);
QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
@@ -344,6 +349,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
{
QML_MEMORY_SCOPE_STRING("SceneGraph");
Q_Q(QQuickWindow);
+ animationController->advance();
emit q->beforeRendering();
int fboId = 0;
const qreal devicePixelRatio = q->devicePixelRatio();
@@ -414,6 +420,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
q->setSurfaceType(QWindow::OpenGLSurface);
q->setFormat(context->defaultSurfaceFormat());
+ animationController = new QQuickAnimatorController();
+ animationController->window = q;
+
QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
@@ -990,6 +999,7 @@ QQuickWindow::~QQuickWindow()
{
Q_D(QQuickWindow);
+ d->animationController->deleteLater();
d->windowManager->windowDestroyed(this);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index e29ceb521f..c656eacce7 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE
//Make it easy to identify and customize the root item if needed
+class QQuickAnimatorController;
class QSGRenderLoop;
class QQuickDragGrabber;
@@ -197,6 +198,7 @@ public:
QSGRenderer *renderer;
QSGRenderLoop *windowManager;
+ QQuickAnimatorController *animationController;
QColor clearColor;
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index e099d94a53..890f579315 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -124,6 +124,18 @@ public:
bool eventPending;
};
+bool QSGRenderLoop::useConsistentTiming()
+{
+ bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
+ // Enable fixed animation steps...
+ QByteArray fixed = qgetenv("QSG_FIXED_ANIMATION_STEP");
+ bool fixedAnimationSteps = bufferQueuing;
+ if (fixed == "no")
+ fixedAnimationSteps = false;
+ else if (fixed.length())
+ fixedAnimationSteps = true;
+ return fixedAnimationSteps;
+}
QSGRenderLoop *QSGRenderLoop::instance()
{
@@ -131,16 +143,7 @@ QSGRenderLoop *QSGRenderLoop::instance()
s_instance = QSGContext::createWindowManager();
- bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
-
- // Enable fixed animation steps...
- QByteArray fixed = qgetenv("QML_FIXED_ANIMATION_STEP");
- bool fixedAnimationSteps = bufferQueuing;
- if (fixed == "no")
- fixedAnimationSteps = false;
- else if (fixed.length())
- fixedAnimationSteps = true;
- if (fixedAnimationSteps)
+ if (useConsistentTiming())
QUnifiedTimer::instance(true)->setConsistentTiming(true);
if (!s_instance) {
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 1e9a645cf4..99b3ab677d 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -79,6 +79,8 @@ public:
static QSGRenderLoop *instance();
static void setInstance(QSGRenderLoop *instance);
+ static bool useConsistentTiming();
+
virtual bool interleaveIncubation() const { return false; }
Q_SIGNALS:
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index ba7bdbb2f4..88bc013306 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -55,6 +55,7 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include "qsgthreadedrenderloop_p.h"
+#include <private/qquickanimatorcontroller_p.h>
#include <private/qqmlprofilerservice_p.h>
@@ -329,8 +330,6 @@ public:
QOpenGLContext *gl;
QSGContext *sg;
- QEventLoop eventLoop;
-
uint pendingUpdate;
uint sleeping;
uint syncResultedInChanges;
@@ -861,6 +860,10 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
m_thread->gl = ctx;
}
+ QQuickAnimatorController *controller = QQuickWindowPrivate::get(window)->animationController;
+ if (controller->thread() != m_thread)
+ controller->moveToThread(m_thread);
+
m_thread->start();
} else {
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index c05b254b51..904842b91e 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -42,6 +42,8 @@
#include "qquickanimation_p.h"
#include "qquickanimation_p_p.h"
+#include "qquickanimatorjob_p.h"
+
#include <private/qquickstatechangescript_p.h>
#include <private/qqmlcontext_p.h>
@@ -171,8 +173,11 @@ void QQuickAbstractAnimationPrivate::commence()
delete oldInstance;
if (animationInstance) {
- if (oldInstance != animationInstance)
+ if (oldInstance != animationInstance) {
+ if (q->threadingModel() == QQuickAbstractAnimation::RenderThread)
+ animationInstance = new QQuickAnimatorProxyJob(animationInstance, q);
animationInstance->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
+ }
animationInstance->start();
if (animationInstance->isStopped()) {
running = false;
@@ -643,6 +648,11 @@ void QQuickAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*)
}
}
+QQuickAbstractAnimation::ThreadingModel QQuickAbstractAnimation::threadingModel() const
+{
+ return GuiThread;
+}
+
/*!
\qmltype PauseAnimation
\instantiates QQuickPauseAnimation
@@ -1713,6 +1723,21 @@ QQuickSequentialAnimation::~QQuickSequentialAnimation()
{
}
+QQuickAbstractAnimation::ThreadingModel QQuickSequentialAnimation::threadingModel() const
+{
+ Q_D(const QQuickAnimationGroup);
+
+ ThreadingModel style = AnyThread;
+ for (int i=0; i<d->animations.size(); ++i) {
+ ThreadingModel ces = d->animations.at(i)->threadingModel();
+ if (ces == GuiThread)
+ return GuiThread;
+ else if (ces == RenderThread)
+ style = RenderThread;
+ }
+ return style;
+}
+
QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
@@ -1729,14 +1754,19 @@ QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions
from = d->animations.count() - 1;
}
+ ThreadingModel execution = threadingModel();
+
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);
anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
- if (anim)
+ if (anim) {
+ if (d->animations.at(ii)->threadingModel() == RenderThread && execution != RenderThread)
+ anim = new QQuickAnimatorProxyJob(anim, this);
inc == -1 ? ag->prependAnimation(anim) : ag->appendAnimation(anim);
+ }
}
return initInstance(ag);
@@ -1782,6 +1812,23 @@ QQuickParallelAnimation::~QQuickParallelAnimation()
{
}
+QQuickAbstractAnimation::ThreadingModel QQuickParallelAnimation::threadingModel() const
+{
+ Q_D(const QQuickAnimationGroup);
+
+ ThreadingModel style = AnyThread;
+ for (int i=0; i<d->animations.size(); ++i) {
+ ThreadingModel ces = d->animations.at(i)->threadingModel();
+ if (ces == GuiThread)
+ return GuiThread;
+ else if (ces == RenderThread)
+ style = RenderThread;
+ }
+ return style;
+}
+
+
+
QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
@@ -1790,14 +1837,19 @@ QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &a
Q_D(QQuickAnimationGroup);
QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob;
+ ThreadingModel style = threadingModel();
+
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, defaultTarget);
- if (anim)
+ if (anim) {
+ if (d->animations.at(ii)->threadingModel() == RenderThread && style != RenderThread)
+ anim = new QQuickAnimatorProxyJob(anim, this);
ag->appendAnimation(anim);
+ }
}
return initInstance(ag);
}
@@ -2034,6 +2086,8 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
\qmlproperty real QtQuick2::PropertyAnimation::easing.overshoot
\qmlproperty real QtQuick2::PropertyAnimation::easing.period
\qmlproperty list<real> QtQuick2::PropertyAnimation::easing.bezierCurve
+
+//! propertyanimation.easing
\brief Specifies 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
@@ -2235,6 +2289,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
See the \l {qml/animation/easing}{easing} example for a demonstration of
the different easing settings.
+//! propertyanimation.easing
*/
QEasingCurve QQuickPropertyAnimation::easing() const
{
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 82d1ba269e..8851bed969 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -73,6 +73,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ
Q_CLASSINFO("DefaultMethod", "start()")
public:
+ enum ThreadingModel {
+ GuiThread,
+ RenderThread,
+ AnyThread
+ };
+
QQuickAbstractAnimation(QObject *parent=0);
virtual ~QQuickAbstractAnimation();
@@ -102,6 +108,8 @@ public:
void classBegin();
void componentComplete();
+ virtual ThreadingModel threadingModel() const;
+
Q_SIGNALS:
void started();
void stopped();
@@ -421,6 +429,7 @@ public:
virtual ~QQuickSequentialAnimation();
protected:
+ virtual ThreadingModel threadingModel() const;
virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
@@ -437,6 +446,7 @@ public:
virtual ~QQuickParallelAnimation();
protected:
+ virtual ThreadingModel threadingModel() const;
virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp
index dd9ced4bd9..caf1408bb3 100644
--- a/src/quick/util/qquickanimationcontroller.cpp
+++ b/src/quick/util/qquickanimationcontroller.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h
index 5286e77534..b11a602f32 100644
--- a/src/quick/util/qquickanimationcontroller_p.h
+++ b/src/quick/util/qquickanimationcontroller_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp
new file mode 100644
index 0000000000..c6f9f20aae
--- /dev/null
+++ b/src/quick/util/qquickanimator.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimator_p_p.h"
+#include "qquickanimatorjob_p.h"
+
+#include <private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Animator
+ \instantiates QQuickAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief Is the base of all QML animators.
+
+ Animator types are a special type of animation which operate
+ directly on Qt Quick's scene graph, rather than the QML objects and their
+ properties like regular Animation types do. This has the benefit that
+ Animator based animations can animate on the \l
+ {Threaded Render Loop}{scene graph's rendering thread} even when the
+ UI thread is blocked.
+
+ The value of the QML property will be updated after the animation has
+ finished. The property is not updated while the animation is running.
+
+ The Animator types can be used just like any other Animation type.
+
+ \snippet qml/animators.qml mixed
+
+ If all sub-animations of ParallelAnimation and SequentialAnimation
+ are Animator types, the ParallelAnimation and SequentialAnimation will
+ also be treated as an Animator and be run on the scene graph's rendering
+ thread when possible.
+
+ The Animator type cannot be used directly in a QML file. It exists
+ to provide a set of common properties and methods, available across all the
+ other animator types that inherit from it. Attempting to use the Animator
+ type directly will result in an error.
+ */
+
+QQuickAnimator::QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent)
+ : QQuickAbstractAnimation(dd, parent)
+{
+}
+
+QQuickAnimator::QQuickAnimator(QObject *parent)
+ : QQuickAbstractAnimation(*new QQuickAnimatorPrivate, parent)
+{
+}
+
+/*!
+ \qmlproperty QtQuick2::Item QtQuick2::Animator::target
+
+ This property holds the target item of the animator.
+
+ \note Animator targets must be Item based types.
+ */
+
+void QQuickAnimator::setTargetItem(QQuickItem *target)
+{
+ Q_D(QQuickAnimator);
+ if (target == d->target)
+ return;
+ d->target = target;
+ Q_EMIT targetItemChanged(d->target);
+}
+
+QQuickItem *QQuickAnimator::targetItem() const
+{
+ Q_D(const QQuickAnimator);
+ return d->target;
+}
+
+/*!
+ \qmlproperty int QtQuick2::Animator::duration
+ This property holds the duration of the animation in milliseconds.
+
+ The default value is 250.
+*/
+void QQuickAnimator::setDuration(int duration)
+{
+ Q_D(QQuickAnimator);
+ if (duration == d->duration)
+ return;
+ d->duration = duration;
+ Q_EMIT durationChanged(duration);
+}
+
+int QQuickAnimator::duration() const
+{
+ Q_D(const QQuickAnimator);
+ return d->duration;
+}
+
+/*!
+ \qmlpropertygroup QtQuick2::Animator::easing
+ \qmlproperty enumeration QtQuick2::Animator::easing.type
+ \qmlproperty real QtQuick2::Animator::easing.amplitude
+ \qmlproperty real QtQuick2::Animator::easing.overshoot
+ \qmlproperty real QtQuick2::Animator::easing.period
+ \qmlproperty list<real> QtQuick2::Animator::easing.bezierCurve
+ \include qquickanimation.cpp propertyanimation.easing
+*/
+
+void QQuickAnimator::setEasing(const QEasingCurve &easing)
+{
+ Q_D(QQuickAnimator);
+ if (easing == d->easing)
+ return;
+ d->easing = easing;
+ Q_EMIT easingChanged(d->easing);
+}
+
+QEasingCurve QQuickAnimator::easing() const
+{
+ Q_D(const QQuickAnimator);
+ return d->easing;
+}
+
+/*!
+ \qmlproperty real QtQuick2::Animator::to
+ This property holds the end value for the animation.
+
+ If the Animator 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.
+ */
+
+void QQuickAnimator::setTo(qreal to)
+{
+ Q_D(QQuickAnimator);
+ if (to == d->to)
+ return;
+ d->isToDefined = true;
+ d->to = to;
+ Q_EMIT toChanged(d->to);
+}
+
+qreal QQuickAnimator::to() const
+{
+ Q_D(const QQuickAnimator);
+ return d->to;
+}
+
+/*!
+ \qmlproperty real QtQuick2::Animator::from
+ This property holds the starting value for the animation.
+
+ If the Animator is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {Animation and Transitions in Qt Quick}
+*/
+
+void QQuickAnimator::setFrom(qreal from)
+{
+ Q_D(QQuickAnimator);
+ if (from == d->from)
+ return;
+ d->isFromDefined = true;
+ d->from = from;
+ Q_EMIT fromChanged(d->from);
+}
+
+qreal QQuickAnimator::from() const
+{
+ Q_D(const QQuickAnimator);
+ return d->from;
+}
+
+void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
+ const QString &propertyName,
+ QQuickStateActions &actions,
+ QQmlProperties &modified)
+{
+
+ if (actions.size()) {
+ for (int i=0; i<actions.size(); ++i) {
+ QQuickAction &action = actions[i];
+ if (action.property.name() != propertyName)
+ continue;
+ modified << action.property;
+
+ job->setTarget(qobject_cast<QQuickItem *>(action.property.object()));
+
+ if (isFromDefined)
+ job->setFrom(from);
+ else if (action.fromValue.isValid())
+ job->setFrom(action.fromValue.toReal());
+ else
+ job->setFrom(action.property.read().toReal());
+
+ if (isToDefined)
+ job->setTo(to);
+ else if (action.toValue.isValid())
+ job->setTo(action.toValue.toReal());
+ else
+ job->setTo(action.property.read().toReal());
+
+ // This magic line is in sync with what PropertyAnimation does
+ // and prevents the animation to end up in the "completeList"
+ // which forces action.toValue to be written directly to
+ // the item when a transition is cancelled.
+ action.fromValue = action.toValue;
+ }
+ } else {
+ job->setTarget(target);
+ job->setFrom(from);
+ job->setTo(to);
+ }
+
+ if (!job->target() && defaultProperty.object())
+ job->setTarget(qobject_cast<QQuickItem *>(defaultProperty.object()));
+
+ job->setDuration(duration);
+ job->setLoopCount(loopCount);
+ job->setEasingCurve(easing);
+}
+
+QAbstractAnimationJob *QQuickAnimator::transition(QQuickStateActions &actions,
+ QQmlProperties &modified,
+ TransitionDirection,
+ QObject *)
+{
+ Q_D(QQuickAnimator);
+
+ if (d->defaultProperty.isValid() && propertyName() != d->defaultProperty.name()) {
+ qDebug() << Q_FUNC_INFO << "property name conflict...";
+ return 0;
+ }
+
+ QQuickAnimatorJob *job = createJob();
+ if (!job)
+ return 0;
+
+ d->apply(job, propertyName(), actions, modified);
+
+ if (!job->target()) {
+ delete job;
+ return 0;
+ }
+
+ return job;
+}
+
+/*!
+ \qmltype XAnimator
+ \instantiates QQuickXAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The XAnimator type animates the x position of an Item.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of Item::x is updated after the animation has finished.
+
+ The following snippet shows how to use a XAnimator together
+ with a Rectangle item.
+
+ \snippet qml/animators.qml x target
+
+ It is also possible to use the \c on keyword to tie the
+ XAnimator directly to an Item instance.
+
+ \snippet qml/animators.qml x on
+
+
+ */
+
+QQuickXAnimator::QQuickXAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickXAnimator::createJob() const { return new QQuickXAnimatorJob(); }
+
+/*!
+ \qmltype YAnimator
+ \instantiates QQuickYAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The YAnimator type animates the y position of an Item.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of Item::y is updated after the animation has finished.
+
+ The following snippet shows how to use a YAnimator together
+ with a Rectangle item.
+
+ \snippet qml/animators.qml y target
+
+ It is also possible to use the \c on keyword to tie the
+ YAnimator directly to an Item instance.
+
+ \snippet qml/animators.qml y on
+
+
+ */
+
+QQuickYAnimator::QQuickYAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickYAnimator::createJob() const { return new QQuickYAnimatorJob(); }
+
+/*!
+ \qmltype ScaleAnimator
+ \instantiates QQuickScaleAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The ScaleAnimator type animates the scale factor of an Item.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of Item::scale is updated after the animation has finished.
+
+ The following snippet shows how to use a ScaleAnimator together
+ with a Rectangle item.
+
+ \snippet qml/animators.qml scale target
+
+ It is also possible to use the \c on keyword to tie the
+ ScaleAnimator directly to an Item instance.
+
+ \snippet qml/animators.qml scale on
+
+ \sa Item::transformOrigin, RotationAnimator
+ */
+
+QQuickScaleAnimator::QQuickScaleAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickScaleAnimator::createJob() const { return new QQuickScaleAnimatorJob(); }
+
+/*!
+ \qmltype OpacityAnimator
+ \instantiates QQuickOpacityAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The OpacityAnimator type animates the opacity of an Item.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of Item::opacity is updated after the animation has finished.
+
+ The following snippet shows how to use a OpacityAnimator together
+ with a Rectangle item.
+
+ \snippet qml/animators.qml opacity target
+
+ It is also possible to use the \c on keyword to tie the
+ OpacityAnimator directly to an Item instance.
+
+ \snippet qml/animators.qml opacity on
+
+ */
+
+QQuickOpacityAnimator::QQuickOpacityAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickOpacityAnimator::createJob() const { return new QQuickOpacityAnimatorJob(); }
+
+/*!
+ \qmltype RotationAnimator
+ \instantiates QQuickRotationAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The RotationAnimator type animates the rotation of an Item.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of Item::rotation is updated after the animation has finished.
+
+ The following snippet shows how to use a RotationAnimator together
+ with a Rectangle item.
+
+ \snippet qml/animators.qml rotation target
+
+ It is also possible to use the \c on keyword to tie the
+ RotationAnimator directly to the \c rotation property of an Item
+ instance.
+
+ \snippet qml/animators.qml rotation on
+
+ \sa Item::transformOrigin, ScaleAnimator
+ */
+
+QQuickRotationAnimator::QQuickRotationAnimator(QObject *parent)
+ : QQuickAnimator(*new QQuickRotationAnimatorPrivate, parent)
+{
+}
+
+QQuickAnimatorJob *QQuickRotationAnimator::createJob() const {
+ Q_D(const QQuickRotationAnimator);
+ QQuickRotationAnimatorJob *job = new QQuickRotationAnimatorJob();
+ job->setDirection(d->direction);
+ return job;
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::RotationAnimator::direction
+ This property holds the direction of the rotation.
+
+ Possible values are:
+
+ \list
+ \li RotationAnimator.Numerical (default) - Rotate by linearly interpolating between the two numbers.
+ A rotation from 10 to 350 will rotate 340 degrees clockwise.
+ \li RotationAnimator.Clockwise - Rotate clockwise between the two values
+ \li RotationAnimator.Counterclockwise - Rotate counterclockwise between the two values
+ \li RotationAnimator.Shortest - Rotate in the direction that produces the shortest animation path.
+ A rotation from 10 to 350 will rotate 20 degrees counterclockwise.
+ \endlist
+*/
+void QQuickRotationAnimator::setDirection(RotationDirection dir)
+{
+ Q_D(QQuickRotationAnimator);
+ if (d->direction == dir)
+ return;
+ d->direction = dir;
+ Q_EMIT directionChanged(d->direction);
+}
+
+QQuickRotationAnimator::RotationDirection QQuickRotationAnimator::direction() const
+{
+ Q_D(const QQuickRotationAnimator);
+ return d->direction;
+}
+
+/*!
+ \qmltype UniformAnimator
+ \instantiates QQuickUniformAnimator
+ \inqmlmodule QtQuick 2
+ \since QtQuick 2.2
+ \ingroup qtquick-transitions-animations
+ \brief The UniformAnimator type animates a uniform of a ShaderEffect.
+
+ \l{Animator} types are different from normal Animation types. When
+ using an Animator, the animation can be run in the render thread
+ and the property value will jump to the end when the animation is
+ complete.
+
+ The value of the QML property defining the uniform is updated after
+ the animation has finished.
+
+ The following snippet shows how to use a UniformAnimator together
+ with a ShaderEffect item.
+
+ \snippet qml/animators.qml shader target
+
+ It is also possible to use the \c on keyword to tie the
+ UniformAnimator directly to a uniform of a ShaderEffect
+ instance.
+
+ \snippet qml/animators.qml shader on
+
+ \sa ShaderEffect, ShaderEffectSource
+ */
+
+QQuickUniformAnimator::QQuickUniformAnimator(QObject *parent)
+ : QQuickAnimator(*new QQuickUniformAnimatorPrivate, parent)
+{
+}
+
+/*!
+ \qmlproperty string QtQuick2::UniformAnimator::uniform
+ This property holds the name of the uniform to animate.
+
+ The value of the uniform must correspond to both a property
+ on the target ShaderEffect and must be a uniform of type
+ \c float in the fragment or vertex shader.
+ */
+void QQuickUniformAnimator::setUniform(const QString &uniform)
+{
+ Q_D(QQuickUniformAnimator);
+ if (d->uniform == uniform)
+ return;
+ d->uniform = uniform;
+ Q_EMIT uniformChanged(d->uniform);
+}
+
+QString QQuickUniformAnimator::uniform() const
+{
+ Q_D(const QQuickUniformAnimator);
+ return d->uniform;
+}
+
+QString QQuickUniformAnimator::propertyName() const
+{
+ Q_D(const QQuickUniformAnimator);
+ if (!d->uniform.isEmpty())
+ return d->uniform;
+ return d->defaultProperty.name();
+}
+
+QQuickAnimatorJob *QQuickUniformAnimator::createJob() const
+{
+ QString u = propertyName();
+ if (u.isEmpty())
+ return 0;
+
+ QQuickUniformAnimatorJob *job = new QQuickUniformAnimatorJob();
+ job->setUniform(u.toLatin1());
+ return job;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
new file mode 100644
index 0000000000..e5916c624c
--- /dev/null
+++ b/src/quick/util/qquickanimator_p.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATOR_P_H
+#define QQUICKANIMATOR_P_H
+
+#include "qquickanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+
+class QQuickAnimatorJob;
+class QQuickAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimator : public QQuickAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickAnimator)
+ Q_PROPERTY(QQuickItem *target READ targetItem WRITE setTargetItem NOTIFY targetItemChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
+
+public:
+ QQuickItem *targetItem() const;
+ void setTargetItem(QQuickItem *target);
+
+ int duration() const;
+ void setDuration(int duration);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve & easing);
+
+ qreal to() const;
+ void setTo(qreal to);
+
+ qreal from() const;
+ void setFrom(qreal from);
+
+protected:
+ ThreadingModel threadingModel() const { return RenderThread; }
+ virtual QQuickAnimatorJob *createJob() const = 0;
+ virtual QString propertyName() const = 0;
+ QAbstractAnimationJob *transition(QQuickStateActions &actions,
+ QQmlProperties &modified,
+ TransitionDirection,
+ QObject *);
+
+ QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent = 0);
+ QQuickAnimator(QObject *parent = 0);
+
+Q_SIGNALS:
+ void targetItemChanged(QQuickItem *);
+ void durationChanged(int duration);
+ void easingChanged(const QEasingCurve &curve);
+ void toChanged(qreal to);
+ void fromChanged(qreal from);
+};
+
+class QQuickScaleAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+public:
+ QQuickScaleAnimator(QObject *parent = 0);
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const { return QStringLiteral("scale"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+public:
+ QQuickXAnimator(QObject *parent = 0);
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const{ return QStringLiteral("x"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+public:
+ QQuickYAnimator(QObject *parent = 0);
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const { return QStringLiteral("y"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+public:
+ QQuickOpacityAnimator(QObject *parent = 0);
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const { return QStringLiteral("opacity"); }
+};
+
+class QQuickRotationAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickRotationAnimator)
+ Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+ Q_ENUMS(RotationDirection)
+
+public:
+ enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+
+ QQuickRotationAnimator(QObject *parent = 0);
+
+ void setDirection(RotationDirection dir);
+ RotationDirection direction() const;
+
+Q_SIGNALS:
+ void directionChanged(RotationDirection dir);
+
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const { return QStringLiteral("rotation"); }
+};
+
+class QQuickUniformAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimator : public QQuickAnimator
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickUniformAnimator)
+ Q_PROPERTY(QString uniform READ uniform WRITE setUniform NOTIFY uniformChanged)
+
+public:
+ QQuickUniformAnimator(QObject *parent = 0);
+
+ QString uniform() const;
+ void setUniform(const QString &);
+
+Q_SIGNALS:
+ void uniformChanged(const QString &);
+
+protected:
+ QQuickAnimatorJob *createJob() const;
+ QString propertyName() const;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickAnimator)
+QML_DECLARE_TYPE(QQuickXAnimator)
+QML_DECLARE_TYPE(QQuickYAnimator)
+QML_DECLARE_TYPE(QQuickScaleAnimator)
+QML_DECLARE_TYPE(QQuickRotationAnimator)
+QML_DECLARE_TYPE(QQuickOpacityAnimator)
+QML_DECLARE_TYPE(QQuickUniformAnimator)
+
+#endif // QQUICKANIMATOR_P_H
diff --git a/src/quick/util/qquickanimator_p_p.h b/src/quick/util/qquickanimator_p_p.h
new file mode 100644
index 0000000000..cc25496a8f
--- /dev/null
+++ b/src/quick/util/qquickanimator_p_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATOR_P_P_H
+#define QQUICKANIMATOR_P_P_H
+
+#include "qquickanimator_p.h"
+#include "qquickanimation_p_p.h"
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimatorJob;
+
+class QQuickAnimatorPrivate : public QQuickAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickAnimator)
+public:
+ QQuickAnimatorPrivate()
+ : target(0)
+ , duration(250)
+ , from(0)
+ , to(0)
+ , isFromDefined(false)
+ , isToDefined(false)
+ {
+ }
+
+ QPointer<QQuickItem> target;
+ int duration;
+ QEasingCurve easing;
+ qreal from;
+ qreal to;
+
+ uint isFromDefined : 1;
+ uint isToDefined : 1;
+
+ void apply(QQuickAnimatorJob *job, const QString &propertyName, QQuickStateActions &actions, QQmlProperties &modified);
+};
+
+class QQuickRotationAnimatorPrivate : public QQuickAnimatorPrivate
+{
+public:
+ QQuickRotationAnimatorPrivate()
+ : direction(QQuickRotationAnimator::Numerical)
+ {
+ }
+ QQuickRotationAnimator::RotationDirection direction;
+};
+
+class QQuickUniformAnimatorPrivate : public QQuickAnimatorPrivate
+{
+public:
+ QString uniform;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATOR_P_P_H
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
new file mode 100644
index 0000000000..73d2882c05
--- /dev/null
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimatorcontroller_p.h"
+
+#include <private/qquickwindow_p.h>
+#include <private/qsgrenderloop_p.h>
+
+#include <private/qanimationgroupjob_p.h>
+
+#include <QtGui/qscreen.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickAnimatorController::QQuickAnimatorController()
+ : window(0)
+ , driver(0)
+{
+}
+
+QQuickAnimatorController::~QQuickAnimatorController()
+{
+ qDeleteAll(activeRootAnimations);
+}
+
+void QQuickAnimatorController::advance()
+{
+ if (driver && driver->isRunning()) {
+ // This lock is to prevent conflicts with syncBackCurrentValues
+ mutex.lock();
+ driver->advance();
+ mutex.unlock();
+ }
+
+ // The animation system uses a chain of queued connections to
+ // start the animation driver and these won't get delievered until,
+ // at best, after this frame. We need to track if animations
+ // are running here so we can keep on rendering in that case.
+ bool running = driver && driver->isRunning();
+ for (QSet<QAbstractAnimationJob *>::const_iterator it = activeRootAnimations.constBegin();
+ !running && it != activeRootAnimations.constEnd(); ++it) {
+ if ((*it)->isRunning())
+ running = true;
+ }
+
+ for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+ it != activeLeafAnimations.constEnd(); ++it) {
+ if ((*it)->isTransform()) {
+ QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(*it);
+ xform->transformHelper()->apply();
+ }
+ }
+
+ if (running)
+ window->update();
+}
+
+static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c)
+{
+ if (job->isRenderThreadJob()) {
+ QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
+ j->initialize(c);
+ } else if (job->isGroup()) {
+ QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
+ for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
+ qquick_initialize_helper(a, c);
+ }
+}
+
+void QQuickAnimatorController::beforeNodeSync()
+{
+ if (!driver && window->thread() != window->openglContext()->thread()) {
+ driver = QQuickWindowPrivate::get(window)->context->createAnimationDriver(this);
+ connect(driver, SIGNAL(started()), this, SLOT(animationsStarted()), Qt::DirectConnection);
+ connect(driver, SIGNAL(stopped()), this, SLOT(animationsStopped()), Qt::DirectConnection);
+ driver->install();
+
+ QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming());
+ }
+
+ // Force a render pass if we are adding new animations
+ // so that advance will be called..
+ if (starting.size())
+ window->update();
+
+ for (int i=0; i<starting.size(); ++i) {
+ QAbstractAnimationJob *job = starting.at(i);
+ qquick_initialize_helper(job, this);
+ job->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
+ job->start();
+ }
+ starting.clear();
+
+ for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+ it != activeLeafAnimations.constEnd(); ++it) {
+ if ((*it)->isTransform()) {
+ QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(*it);
+ xform->transformHelper()->sync();
+ }
+ }
+}
+
+void QQuickAnimatorController::afterNodeSync()
+{
+ for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+ it != activeLeafAnimations.constEnd(); ++it) {
+ if ((*it)->isUniform()) {
+ QQuickUniformAnimatorJob *job = static_cast<QQuickUniformAnimatorJob *>(*it);
+ job->afterNodeSync();
+ }
+ }
+}
+
+
+void QQuickAnimatorController::startAnimation(QAbstractAnimationJob *job)
+{
+ mutex.lock();
+ starting << job;
+ mutex.unlock();
+}
+
+void QQuickAnimatorController::animationsStopped()
+{
+}
+
+void QQuickAnimatorController::animationsStarted()
+{
+ window->update();
+}
+
+void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job,
+ QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State)
+{
+ if (newState == QAbstractAnimationJob::Running)
+ activeRootAnimations << job;
+ else
+ activeRootAnimations.remove(job);
+}
+
+bool QQuickAnimatorController::event(QEvent *e)
+{
+ if ((int) e->type() == StopAnimation) {
+ QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
+ mutex.lock();
+ starting.removeOne(job);
+ mutex.unlock();
+ job->stop();
+ return true;
+
+ } else if ((uint) e->type() == DeleteAnimation) {
+ QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
+ mutex.lock();
+ starting.removeOne(job);
+ mutex.unlock();
+ job->stop();
+ delete job;
+ return true;
+ }
+
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
new file mode 100644
index 0000000000..1c79e3c493
--- /dev/null
+++ b/src/quick/util/qquickanimatorcontroller_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATORCONTROLLER_P_H
+#define QQUICKANIMATORCONTROLLER_P_H
+
+#include "qquickanimatorjob_p.h"
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qquickitem.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimatorController : public QObject, public QAnimationJobChangeListener
+{
+ Q_OBJECT
+
+public:
+
+ enum EventType {
+ // GUI to RT events
+ StartAnimation = QEvent::User + 1,
+ StopAnimation,
+ DeleteAnimation,
+
+ // RT back to GUI events
+ AnimationFinished
+ };
+
+ class Event : public QEvent {
+ public:
+ Event(QAbstractAnimationJob *j, EventType type)
+ : QEvent(QEvent::Type(type))
+ , job(j)
+ {
+ }
+ QAbstractAnimationJob *job;
+ };
+
+ QQuickAnimatorController();
+ ~QQuickAnimatorController();
+
+ void advance();
+ void beforeNodeSync();
+ void afterNodeSync();
+
+ bool event(QEvent *);
+
+ void startAnimation(QAbstractAnimationJob *job);
+
+ void animationStateChanged(QAbstractAnimationJob *job,
+ QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State oldState);
+
+public Q_SLOTS:
+ void animationsStarted();
+ void animationsStopped();
+
+public:
+ QList<QAbstractAnimationJob *> starting;
+ QList<QAbstractAnimationJob *> stopped;
+
+ QSet<QAbstractAnimationJob *> activeRootAnimations;
+ QSet<QQuickAnimatorJob *> activeLeafAnimations;
+
+ QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> transforms;
+
+ QQuickWindow *window;
+
+ QAnimationDriver *driver;
+
+ QMutex mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATORCONTROLLER_P_H
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
new file mode 100644
index 0000000000..3270faa652
--- /dev/null
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -0,0 +1,532 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimatorcontroller_p.h"
+#include "qquickanimatorjob_p.h"
+#include "qquickanimator_p.h"
+#include "qquickanimator_p_p.h"
+#include <private/qquickwindow_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qquickshadereffectnode_p.h>
+
+#include <private/qanimationgroupjob_p.h>
+
+#include <qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item)
+ : m_controller(0)
+ , m_job(job)
+ , m_internalState(State_Stopped)
+{
+ m_isRenderThreadProxy = true;
+ m_animation = qobject_cast<QQuickAbstractAnimation *>(item);
+
+ setLoopCount(job->loopCount());
+
+ // Instead of setting duration to job->duration() we need to set it to -1 so that
+ // it runs as long as the job is running on the render thread. If we gave it
+ // an explicit duration, it would be stopped, potentially stopping the RT animation
+ // prematurely.
+ // This means that the animation driver will tick on the GUI thread as long
+ // as the animation is running on the render thread, but this overhead will
+ // be negligiblie compared to animating and re-rendering the scene on the render thread.
+ m_duration = -1;
+
+ job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
+
+ QObject *ctx = findAnimationContext(m_animation);
+ if (!ctx) {
+ qWarning("QtQuick: unable to find animation context for RT animation...");
+ return;
+ }
+
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(ctx);
+ if (window) {
+ setWindow(window);
+ } else {
+ QQuickItem *item = qobject_cast<QQuickItem *>(ctx);
+ if (item->window())
+ setWindow(item->window());
+ else
+ connect(item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(windowChanged(QQuickWindow*)));
+ }
+}
+
+QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob()
+{
+ deleteJob();
+}
+
+void QQuickAnimatorProxyJob::deleteJob()
+{
+ if (m_job) {
+ if (m_controller && m_internalState != State_Starting)
+ QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::DeleteAnimation));
+ else
+ delete m_job;
+ m_job = 0;
+ }
+}
+
+QObject *QQuickAnimatorProxyJob::findAnimationContext(QQuickAbstractAnimation *a)
+{
+ QObject *p = a->parent();
+ while (p != 0 && qobject_cast<QQuickWindow *>(p) == 0 && qobject_cast<QQuickItem *>(p) == 0)
+ p = p->parent();
+ return p;
+}
+
+void QQuickAnimatorProxyJob::updateCurrentTime(int)
+{
+}
+
+void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+{
+ if (m_state == Running) {
+ if (m_controller) {
+ m_internalState = State_Running;
+ startOnRenderThread();
+ } else {
+ m_internalState = State_Starting;
+ }
+ } else if (newState == Stopped) {
+ syncBackCurrentValues();
+ if (m_internalState == State_Starting)
+ m_internalState = State_Stopped;
+ else {
+ QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::StopAnimation));
+ }
+ }
+}
+
+void QQuickAnimatorProxyJob::windowChanged(QQuickWindow *window)
+{
+ setWindow(window);
+}
+
+void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
+{
+ if (m_controller) {
+ stop();
+ deleteJob();
+ m_controller = 0;
+ }
+ if (!window)
+ return;
+
+ m_controller = QQuickWindowPrivate::get(window)->animationController;
+
+ if (window->openglContext())
+ readyToAnimate();
+ else
+ connect(window, SIGNAL(sceneGraphInitialized()), this, SLOT(sceneGraphInitialized()));
+}
+
+void QQuickAnimatorProxyJob::sceneGraphInitialized()
+{
+ readyToAnimate();
+ disconnect(this, SLOT(sceneGraphInitialized()));
+}
+
+void QQuickAnimatorProxyJob::readyToAnimate()
+{
+ if (m_internalState == State_Starting) {
+ startOnRenderThread();
+ }
+}
+
+void QQuickAnimatorProxyJob::animationFinished(QAbstractAnimationJob *job)
+{
+ QCoreApplication::postEvent(this, new QQuickAnimatorController::Event(job, QQuickAnimatorController::AnimationFinished));
+}
+
+bool QQuickAnimatorProxyJob::event(QEvent *e)
+{
+ if ((uint) e->type() == QQuickAnimatorController::AnimationFinished) {
+ // Update the duration of this proxy to the current time and stop it so
+ // that parent animations can progress gracefully
+ m_duration = m_currentTime;
+ stop();
+ return true;
+ }
+
+ return QObject::event(e);
+}
+
+void QQuickAnimatorProxyJob::startOnRenderThread()
+{
+ m_internalState = State_Running;
+ // Force a "sync" pass as the newly started animation needs to sync properties from GUI.
+ m_controller->startAnimation(m_job);
+ QQuickWindowPrivate::get(m_controller->window)->dirtyItem(0);
+}
+
+static void qquick_syncback_helper(QAbstractAnimationJob *job)
+{
+ if (job->isRenderThreadJob()) {
+ QQuickAnimatorJob *a = static_cast<QQuickAnimatorJob *>(job);
+ if (a->controller())
+ a->writeBack();
+ } else if (job->isGroup()) {
+ QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
+ for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
+ qquick_syncback_helper(a);
+ }
+}
+
+void QQuickAnimatorProxyJob::syncBackCurrentValues()
+{
+ qquick_syncback_helper(m_job);
+}
+
+QQuickAnimatorJob::QQuickAnimatorJob()
+ : m_target(0)
+ , m_controller(0)
+ , m_from(0)
+ , m_to(0)
+ , m_value(0)
+ , m_duration(0)
+ , m_isTransform(false)
+ , m_isUniform(false)
+{
+ m_isRenderThreadJob = true;
+}
+
+qreal QQuickAnimatorJob::value() const
+{
+ qreal v;
+ m_controller->mutex.lock();
+ v = m_value;
+ m_controller->mutex.unlock();
+ return v;
+}
+
+void QQuickAnimatorJob::setTarget(QQuickItem *target)
+{
+ m_target = target;
+}
+
+void QQuickAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+ m_controller = controller;
+}
+
+void QQuickAnimatorJob::updateState(State newState, State oldState)
+{
+ if (newState == Running) {
+ m_controller->activeLeafAnimations << this;
+ } else if (oldState == Running) {
+ m_controller->activeLeafAnimations.remove(this);
+ }
+}
+
+QQuickTransformAnimatorJob::QQuickTransformAnimatorJob()
+ : m_helper(0)
+{
+ m_isTransform = true;
+}
+
+QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob()
+{
+ if (m_helper && --m_helper->ref == 0) {
+ m_controller->transforms.remove(m_helper->item);
+ delete m_helper;
+ }
+}
+
+void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+ QQuickAnimatorJob::initialize(controller);
+
+ m_helper = m_controller->transforms.value(m_target);
+ if (!m_helper) {
+ m_helper = new Helper();
+ m_helper->item = m_target;
+ m_controller->transforms.insert(m_target, m_helper);
+ } else {
+ ++m_helper->ref;
+ }
+ m_helper->sync();
+}
+
+
+void QQuickTransformAnimatorJob::Helper::sync()
+{
+ const quint32 mask = QQuickItemPrivate::Position
+ | QQuickItemPrivate::BasicTransform
+ | QQuickItemPrivate::TransformOrigin;
+
+ quint32 dirty = mask & QQuickItemPrivate::get(item)->dirtyAttributes;
+
+ if (!wasSynced) {
+ dirty = 0xffffffffu;
+ wasSynced = true;
+ }
+
+ if (dirty == 0)
+ return;
+
+ node = QQuickItemPrivate::get(item)->itemNode();
+
+ if (dirty & QQuickItemPrivate::Position) {
+ dx = item->x();
+ dy = item->y();
+ }
+
+ if (dirty & QQuickItemPrivate::BasicTransform) {
+ scale = item->scale();
+ rotation = item->rotation();
+ }
+
+ if (dirty & QQuickItemPrivate::TransformOrigin) {
+ QPointF o = item->transformOriginPoint();
+ ox = o.x();
+ oy = o.y();
+ }
+}
+
+void QQuickTransformAnimatorJob::Helper::apply()
+{
+ if (!wasChanged)
+ return;
+
+ QMatrix4x4 m;
+ m.translate(dx, dy);
+ m.translate(ox, oy);
+ m.scale(scale);
+ m.rotate(rotation, 0, 0, 1);
+ m.translate(-ox, -oy);
+ node->setMatrix(m);
+
+ wasChanged = false;
+}
+
+
+
+void QQuickXAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setX(value());
+}
+
+void QQuickXAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+ m_helper->dx = m_value;
+ m_helper->wasChanged = true;
+}
+
+void QQuickYAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setY(value());
+}
+
+void QQuickYAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+ m_helper->dy = m_value;
+ m_helper->wasChanged = true;
+}
+
+QQuickOpacityAnimatorJob::QQuickOpacityAnimatorJob()
+ : m_opacityNode(0)
+{
+}
+
+void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+ QQuickAnimatorJob::initialize(controller);
+ QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
+ m_opacityNode = d->opacityNode();
+ if (!m_opacityNode) {
+ m_opacityNode = new QSGOpacityNode();
+ d->extra.value().opacityNode = m_opacityNode;
+
+ QSGNode *child = d->clipNode();
+ if (!child)
+ child = d->rootNode();
+ if (!child)
+ child = d->groupNode;
+
+ if (child) {
+ if (child->parent())
+ child->parent()->removeChildNode(child);
+ m_opacityNode->appendChildNode(child);
+ }
+
+ d->itemNode()->appendChildNode(m_opacityNode);
+ }
+}
+
+void QQuickOpacityAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setOpacity(value());
+}
+
+void QQuickOpacityAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+ m_opacityNode->setOpacity(m_value);
+}
+
+void QQuickScaleAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setScale(value());
+}
+
+void QQuickScaleAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+ m_helper->scale = m_value;
+ m_helper->wasChanged = true;
+}
+
+QQuickRotationAnimatorJob::QQuickRotationAnimatorJob()
+ : m_direction(QQuickRotationAnimator::Numerical)
+{
+}
+
+extern QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress);
+extern QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress);
+extern QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress);
+
+void QQuickRotationAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ float t = m_easing.valueForProgress(time / (qreal) m_duration);
+ switch (m_direction) {
+ case QQuickRotationAnimator::Clockwise:
+ m_value = _q_interpolateClockwiseRotation(m_from, m_to, t).toFloat();
+ break;
+ case QQuickRotationAnimator::Counterclockwise:
+ m_value = _q_interpolateCounterclockwiseRotation(m_from, m_to, t).toFloat();
+ break;
+ case QQuickRotationAnimator::Shortest:
+ m_value = _q_interpolateShortestRotation(m_from, m_to, t).toFloat();
+ break;
+ case QQuickRotationAnimator::Numerical:
+ m_value = m_from + (m_to - m_from) * t;
+ break;
+ }
+ m_helper->rotation = m_value;
+ m_helper->wasChanged = true;
+}
+
+void QQuickRotationAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setRotation(value());
+}
+
+QQuickUniformAnimatorJob::QQuickUniformAnimatorJob()
+ : m_node(0)
+ , m_uniformIndex(-1)
+ , m_uniformType(-1)
+{
+ m_isUniform = true;
+}
+
+void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
+{
+ if (qobject_cast<QQuickShaderEffect *>(target) != 0)
+ m_target = target;
+}
+
+void QQuickUniformAnimatorJob::afterNodeSync()
+{
+ m_node = static_cast<QQuickShaderEffectNode *>(QQuickItemPrivate::get(m_target)->paintNode);
+
+ if (m_node) {
+ m_uniformIndex = -1;
+ m_uniformType = -1;
+ QQuickShaderEffectMaterial *material =
+ static_cast<QQuickShaderEffectMaterial *>(m_node->material());
+ bool found = false;
+ for (int t=0; !found && t<QQuickShaderEffectMaterialKey::ShaderTypeCount; ++t) {
+ const QVector<QQuickShaderEffectMaterial::UniformData> &uniforms = material->uniforms[t];
+ for (int i=0; i<uniforms.size(); ++i) {
+ if (uniforms.at(i).name == m_uniform) {
+ m_uniformIndex = i;
+ m_uniformType = t;
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+void QQuickUniformAnimatorJob::updateCurrentTime(int time)
+{
+ Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+ if (!m_node || m_uniformIndex == -1 || m_uniformType == -1)
+ return;
+
+ m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+
+ QQuickShaderEffectMaterial *material =
+ static_cast<QQuickShaderEffectMaterial *>(m_node->material());
+ material->uniforms[m_uniformType][m_uniformIndex].value = m_value;
+}
+
+void QQuickUniformAnimatorJob::writeBack()
+{
+ if (m_target)
+ m_target->setProperty(m_uniform, value());
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
new file mode 100644
index 0000000000..c6814523c6
--- /dev/null
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATORJOB_P_H
+#define QQUICKANIMATORJOB_P_H
+
+#include <private/qabstractanimationjob_p.h>
+#include <private/qquickanimator_p.h>
+#include <private/qtquickglobal_p.h>
+
+#include <QtQuick/qquickitem.h>
+
+#include <QtCore/qeasingcurve.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimator;
+class QQuickWindow;
+class QQuickItem;
+class QQuickAbstractAnimation;
+
+class QQuickAnimatorController;
+class QQuickAnimatorProxyJobPrivate;
+class QQuickShaderEffectNode;
+
+class QSGOpacityNode;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorProxyJob : public QObject, public QAbstractAnimationJob, public QAnimationJobChangeListener
+{
+ Q_OBJECT
+
+public:
+ QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item);
+ ~QQuickAnimatorProxyJob();
+
+ int duration() const { return m_duration; }
+
+ virtual void animationFinished(QAbstractAnimationJob *);
+
+protected:
+ bool event(QEvent *);
+
+ void updateCurrentTime(int);
+ void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
+
+public Q_SLOTS:
+ void windowChanged(QQuickWindow *window);
+ void sceneGraphInitialized();
+
+private:
+ void deleteJob();
+ void syncBackCurrentValues();
+ void readyToAnimate();
+ void setWindow(QQuickWindow *window);
+ static QObject *findAnimationContext(QQuickAbstractAnimation *);
+ void startOnRenderThread();
+
+ QQuickAnimatorController *m_controller;
+ QQuickAbstractAnimation *m_animation;
+ QAbstractAnimationJob *m_job;
+ int m_duration;
+
+ enum InternalState {
+ State_Starting, // Used when it should be running, but no we're still missing the controller.
+ State_Running,
+ State_Paused,
+ State_Stopped
+ };
+
+ InternalState m_internalState;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorJob : public QAbstractAnimationJob
+{
+public:
+ virtual void setTarget(QQuickItem *target);
+ QQuickItem *target() const { return m_target; }
+
+ void setFrom(qreal scale) { m_from = scale; }
+ qreal from() const { return m_from; }
+
+ void setTo(qreal to) { m_to = to; }
+ qreal to() const { return m_to; }
+
+ void setDuration(int duration) { m_duration = duration; }
+ int duration() const { return m_duration; }
+
+ QEasingCurve easingCurve() const { return m_easing; }
+ void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; }
+
+ virtual void initialize(QQuickAnimatorController *controller);
+ virtual void writeBack() = 0;
+
+ bool isTransform() const { return m_isTransform; }
+ bool isUniform() const { return m_isUniform; }
+
+ qreal value() const;
+
+ QQuickAnimatorController *controller() const { return m_controller; }
+
+protected:
+ QQuickAnimatorJob();
+ void updateState(State newState, State oldState);
+
+ QPointer<QQuickItem> m_target;
+ QQuickAnimatorController *m_controller;
+
+ qreal m_from;
+ qreal m_to;
+ qreal m_value;
+
+ QEasingCurve m_easing;
+
+ int m_duration;
+
+ uint m_feedback : 1;
+ uint m_isTransform : 1;
+ uint m_isUniform : 1;
+};
+
+class QQuickTransformAnimatorJob : public QQuickAnimatorJob
+{
+public:
+
+ struct Helper
+ {
+ Helper()
+ : ref(1)
+ , item(0)
+ , node(0)
+ , ox(0)
+ , oy(0)
+ , dx(0)
+ , dy(0)
+ , scale(1)
+ , rotation(0)
+ , wasSynced(false)
+ , wasChanged(false)
+ {
+ }
+
+ void sync();
+ void apply();
+
+ int ref;
+ QQuickItem *item;
+ QSGTransformNode *node;
+
+ // Origin
+ float ox;
+ float oy;
+
+ float dx;
+ float dy;
+ float scale;
+ float rotation;
+
+ uint wasSynced : 1;
+ uint wasChanged : 1;
+ };
+
+ ~QQuickTransformAnimatorJob();
+ Helper *transformHelper() const { return m_helper; }
+
+protected:
+ QQuickTransformAnimatorJob();
+ void initialize(QQuickAnimatorController *controller);
+
+ Helper *m_helper;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+ void updateCurrentTime(int time);
+ void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickXAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+ void updateCurrentTime(int time);
+ void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickYAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+ void updateCurrentTime(int time);
+ void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+ QQuickRotationAnimatorJob();
+
+ void updateCurrentTime(int time);
+ void writeBack();
+
+ void setDirection(QQuickRotationAnimator::RotationDirection direction) { m_direction = direction; }
+ QQuickRotationAnimator::RotationDirection direction() const { return m_direction; }
+
+private:
+ QQuickRotationAnimator::RotationDirection m_direction;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimatorJob : public QQuickAnimatorJob
+{
+public:
+ QQuickOpacityAnimatorJob();
+
+ void initialize(QQuickAnimatorController *controller);
+ void updateCurrentTime(int time);
+ void writeBack();
+
+private:
+ QSGOpacityNode *m_opacityNode;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob
+{
+public:
+ QQuickUniformAnimatorJob();
+
+ void setTarget(QQuickItem *target);
+
+ void setUniform(const QByteArray &uniform) { m_uniform = uniform; }
+ QByteArray uniform() const { return m_uniform; }
+
+ void afterNodeSync();
+
+ void updateCurrentTime(int time);
+ void writeBack();
+
+private:
+ QByteArray m_uniform;
+ QQuickShaderEffectNode *m_node;
+
+ int m_uniformIndex : 8;
+ int m_uniformType : 8;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATORJOB_P_H
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 2d765dc5ee..855e99e5a9 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -49,6 +49,8 @@
#include <private/qabstractanimationjob_p.h>
#include <private/qquicktransition_p.h>
+#include <private/qquickanimatorjob_p.h>
+
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -186,14 +188,18 @@ void QQuickBehavior::write(const QVariant &value)
if (d->animation->isRunning() && value == d->targetValue)
return;
- const QVariant &currentValue = d->property.read();
d->targetValue = value;
- if (d->animationInstance && d->animationInstance->duration() != -1
+ if (d->animationInstance
+ && (d->animationInstance->duration() != -1
+ || d->animationInstance->isRenderThreadProxy())
&& !d->animationInstance->isStopped()) {
d->blockRunningChanged = true;
d->animationInstance->stop();
}
+ // Render thread animations use "stop" to synchronize the property back
+ // to the item, so we need to read the value after.
+ const QVariant &currentValue = d->property.read();
QQuickStateOperation::ActionList actions;
QQuickAction action;
@@ -205,6 +211,10 @@ void QQuickBehavior::write(const QVariant &value)
QList<QQmlProperty> after;
QAbstractAnimationJob *prev = d->animationInstance;
d->animationInstance = d->animation->transition(actions, after, QQuickAbstractAnimation::Forward);
+
+ if (d->animationInstance && d->animation->threadingModel() == QQuickAbstractAnimation::RenderThread)
+ d->animationInstance = new QQuickAnimatorProxyJob(d->animationInstance, d->animation);
+
if (prev && prev != d->animationInstance)
delete prev;
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index ead28fe496..4db3fbbad7 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -48,6 +48,8 @@
#include "qquickanimation_p_p.h"
#include "qquicktransitionmanager_p_p.h"
+#include <private/qquickanimatorjob_p.h>
+
#include "private/qparallelanimationgroupjob_p.h"
QT_BEGIN_NAMESPACE
@@ -260,8 +262,11 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
QAbstractAnimationJob *anim = 0;
for (int i = start; i != end;) {
anim = d->animations.at(i)->transition(actions, after, direction, defaultTarget);
- if (anim)
+ if (anim) {
+ if (d->animations.at(i)->threadingModel() == QQuickAbstractAnimation::RenderThread)
+ anim = new QQuickAnimatorProxyJob(anim, d->animations.at(i));
d->reversed ? group->prependAnimation(anim) : group->appendAnimation(anim);
+ }
d->reversed ? --i : ++i;
}
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index fdf8314145..ccde83ca6e 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -53,6 +53,7 @@
#include "qquickstate_p_p.h"
#include "qquicksystempalette_p.h"
#include "qquicktransition_p.h"
+#include "qquickanimator_p.h"
#include <qqmlinfo.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qquickanimationcontroller_p.h>
@@ -91,6 +92,14 @@ void QQuickUtilModule::defineModule()
qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition");
qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
+ qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class"));
+ qmlRegisterType<QQuickXAnimator>("QtQuick", 2, 2, "XAnimator");
+ qmlRegisterType<QQuickYAnimator>("QtQuick", 2, 2, "YAnimator");
+ qmlRegisterType<QQuickScaleAnimator>("QtQuick", 2, 2, "ScaleAnimator");
+ qmlRegisterType<QQuickRotationAnimator>("QtQuick", 2, 2, "RotationAnimator");
+ qmlRegisterType<QQuickOpacityAnimator>("QtQuick", 2, 2, "OpacityAnimator");
+ qmlRegisterType<QQuickUniformAnimator>("QtQuick", 2, 2, "UniformAnimator");
+
qmlRegisterType<QQuickStateOperation>();
qmlRegisterCustomType<QQuickPropertyChanges>("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser);
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index 7f77f7f702..fae1103d47 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -22,7 +22,10 @@ SOURCES += \
$$PWD/qquickimageprovider.cpp \
$$PWD/qquicksvgparser.cpp \
$$PWD/qquickvaluetypes.cpp \
- $$PWD/qquickglobal.cpp
+ $$PWD/qquickglobal.cpp \
+ $$PWD/qquickanimator.cpp \
+ $$PWD/qquickanimatorjob.cpp \
+ $$PWD/qquickanimatorcontroller.cpp
HEADERS += \
$$PWD/qquickapplication_p.h\
@@ -51,4 +54,8 @@ HEADERS += \
$$PWD/qquickpathinterpolator_p.h \
$$PWD/qquickimageprovider.h \
$$PWD/qquicksvgparser_p.h \
- $$PWD/qquickvaluetypes_p.h
+ $$PWD/qquickvaluetypes_p.h \
+ $$PWD/qquickanimator_p.h \
+ $$PWD/qquickanimator_p_p.h \
+ $$PWD/qquickanimatorjob_p.h \
+ $$PWD/qquickanimatorcontroller_p.h
diff --git a/tests/auto/quick/qquickanimators/data/Box.qml b/tests/auto/quick/qquickanimators/data/Box.qml
new file mode 100644
index 0000000000..cff3e7f929
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/Box.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Rectangle {
+ id: box
+ gradient: Gradient {
+ GradientStop { position: 0.1; color: "red" }
+ GradientStop { position: 0.9; color: "blue" }
+ }
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ antialiasing: true
+
+ property int rotationChangeCounter: 0
+ onRotationChanged: ++rotationChangeCounter;
+
+ property int scaleChangeCounter: 0
+ onScaleChanged: ++scaleChangeCounter;
+
+ property int opacityChangeCounter: 0
+ onOpacityChanged: ++opacityChangeCounter
+
+ property int xChangeCounter: 0;
+ onXChanged: ++xChangeCounter;
+
+ property int yChangeCounter: 0;
+ onYChanged: ++yChangeCounter;
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_behavior.qml b/tests/auto/quick/qquickanimators/data/tst_behavior.qml
new file mode 100644
index 0000000000..b22cc93b09
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_behavior.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "behavior"
+ when: box.scale == 2
+ function test_endresult() {
+ compare(box.scaleChangeCounter, 1);
+ compare(box.scale, 2);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1));
+ compare(image.pixel(199, 199), Qt.rgba(0, 0, 1, 1));
+ }
+ }
+
+ Box {
+ id: box
+ Behavior on scale { ScaleAnimator { id: animation; duration: 300; } }
+ }
+
+ Timer {
+ interval: 1000;
+ repeat: false
+ running: true
+ onTriggered: box.scale = 2
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml b/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml
new file mode 100644
index 0000000000..9cd28f2493
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "mixedparallel"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.rotationChangeCounter, 1);
+ compare(box.scale, 2);
+ compare(box.rotation, 180);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+ compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+
+ Box {
+ id: box
+ ParallelAnimation {
+ id: animation
+ NumberAnimation { target: box; property: "scale"; from: 1; to: 2.0; duration: 1000; }
+ RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+ running: true
+ loops: 1;
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml b/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml
new file mode 100644
index 0000000000..4c62bc8018
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "mixedsequential"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.rotationChangeCounter, 1);
+ compare(box.scale, 2);
+ compare(box.rotation, 180);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+ compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+
+ Box {
+ id: box
+ ParallelAnimation {
+ id: animation
+ NumberAnimation { target: box; property: "scale"; from: 1; to: 2.0; duration: 500; }
+ RotationAnimator { target: box; from: 0; to: 180; duration: 500; }
+ running: true
+ loops: 1;
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_nested.qml b/tests/auto/quick/qquickanimators/data/tst_nested.qml
new file mode 100644
index 0000000000..95cb70cb48
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_nested.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "nested"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.before, 2);
+ compare(box.after, 2);
+ }
+ }
+
+ Box {
+ id: box
+
+ anchors.centerIn: undefined
+
+ property int before: 0;
+ property int after: 0;
+
+ SequentialAnimation {
+ id: animation;
+ ScriptAction { script: box.before++; }
+ ParallelAnimation {
+ ScaleAnimator { target: box; from: 2.0; to: 1; duration: 500; }
+ OpacityAnimator { target: box; from: 0; to: 1; duration: 500; }
+ }
+ PauseAnimation { duration: 500 }
+ SequentialAnimation {
+ ParallelAnimation {
+ XAnimator { target: box; from: 0; to: 100; duration: 500}
+ RotationAnimator { target: box; from: 0; to: 90; duration: 500 }
+ }
+ ParallelAnimation {
+ XAnimator { target: box; from: 100; to: 0; duration: 500 }
+ RotationAnimator { target: box; from: 90; to: 0; duration: 500 }
+ }
+ }
+ ScriptAction { script: box.after++; }
+ running: true
+ loops: 2
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_on.qml b/tests/auto/quick/qquickanimators/data/tst_on.qml
new file mode 100644
index 0000000000..e48d7107f9
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_on.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "on"
+ when: !animx.running && !animy.running
+ && !anims.running && !animr.running
+ && !animo.running;
+ function test_endresult() {
+ compare(box.xChangeCounter, 1);
+ compare(box.yChangeCounter, 1);
+ compare(box.scaleChangeCounter, 1);
+ compare(box.rotationChangeCounter, 1);
+ compare(box.opacityChangeCounter, 1);
+ compare(box.x, 100);
+ compare(box.y, 100);
+ compare(box.scale, 2);
+ compare(box.rotation, 180);
+ compare(box.opacity, 0.5);
+ }
+ }
+
+ Box {
+ id: box
+ anchors.centerIn: undefined
+ XAnimator on x { id: animx; from: 0; to: 100; duration: 1000 }
+ YAnimator on y { id: animy; from: 0; to: 100; duration: 1000 }
+ ScaleAnimator on scale { id: anims; from: 1; to: 2; duration: 1000 }
+ RotationAnimator on rotation { id: animr ; from: 0; to: 180; duration: 1000 }
+ OpacityAnimator on opacity { id: animo; from: 1; to: 0.5; duration: 1000 }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_opacity.qml b/tests/auto/quick/qquickanimators/data/tst_opacity.qml
new file mode 100644
index 0000000000..a785b2b3f3
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_opacity.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "opacity"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.opacityChangeCounter, 1);
+ compare(box.opacity, 0.5);
+ var image = grabImage(root);
+ compare(image.red(50, 50), 255);
+ verify(image.green(50, 50) > 0);
+ verify(image.blue(50, 50) > 0);
+ }
+ }
+
+ Box {
+ id: box
+
+ OpacityAnimator {
+ id: animation
+ target: box
+ from: 1;
+ to: 0.5
+ duration: 1000
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_parallel.qml b/tests/auto/quick/qquickanimators/data/tst_parallel.qml
new file mode 100644
index 0000000000..3105d3c2dd
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_parallel.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "parallel"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.rotationChangeCounter, 1);
+ compare(box.scaleChangeCounter, 1);
+ compare(box.scale, 2);
+ compare(box.rotation, 180);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+ compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+
+ Box {
+ id: box
+ ParallelAnimation {
+ id: animation
+ ScaleAnimator { target: box; from: 1; to: 2.0; duration: 1000; }
+ RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_restart.qml b/tests/auto/quick/qquickanimators/data/tst_restart.qml
new file mode 100644
index 0000000000..42c7a33a8b
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_restart.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ property int restartCount: 5;
+
+ TestCase {
+ id: testcase
+ name: "restart"
+ when: root.restartCount == 0 && animation.running == false;
+ function test_endresult() {
+ compare(box.scale, 2);
+ }
+ }
+
+ Box {
+ id: box
+
+ ScaleAnimator {
+ id: animation
+ target: box;
+ from: 1;
+ to: 2.0;
+ duration: 100;
+ loops: 1
+ running: false;
+ }
+
+ Timer {
+ id: timer;
+ interval: 500
+ running: true
+ repeat: true
+ onTriggered: {
+ animation.running = true;
+ --root.restartCount;
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_rotation.qml b/tests/auto/quick/qquickanimators/data/tst_rotation.qml
new file mode 100644
index 0000000000..517cf59456
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_rotation.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "rotation"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.rotationChangeCounter, 1);
+ compare(box.rotation, 180);
+ var image = grabImage(root);
+ compare(image.pixel(50, 50), Qt.rgba(0, 0, 1));
+ }
+ }
+
+ Box {
+ id: box
+ RotationAnimator {
+ id: animation
+ target: box
+ from: 0;
+ to: 180
+ duration: 1000
+ easing.type: Easing.InOutBack
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_scale.qml b/tests/auto/quick/qquickanimators/data/tst_scale.qml
new file mode 100644
index 0000000000..6fd4668684
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_scale.qml
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "scale"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.scaleChangeCounter, 1);
+ compare(box.scale, 2);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(1, 0, 0));
+ }
+ }
+
+ Box {
+ id: box
+
+ ScaleAnimator {
+ id: animation
+ target: box
+ from: 1;
+ to: 2.0
+ duration: 1000
+ easing.type: Easing.InOutCubic
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_sequential.qml b/tests/auto/quick/qquickanimators/data/tst_sequential.qml
new file mode 100644
index 0000000000..2bb14f8acf
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_sequential.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "parallel"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.rotationChangeCounter, 1);
+ compare(box.scaleChangeCounter, 1);
+ compare(box.scale, 2);
+ compare(box.rotation, 180);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+ compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+
+ Box {
+ id: box
+ SequentialAnimation {
+ id: animation
+ ScaleAnimator { target: box; from: 1; to: 2.0; duration: 1000; }
+ RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml b/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml
new file mode 100644
index 0000000000..0211d0305d
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 300
+ height: 300
+
+ Timer {
+ id: timer;
+ running: testCase.windowShown
+ interval: 1000
+ repeat: false
+ onTriggered: triggered = true;
+ property bool triggered: false;
+ }
+
+ TestCase {
+ id: testCase
+ name: "transformorigin"
+ when: timer.triggered
+ function test_endresult() {
+
+ var image = grabImage(root);
+
+ var white = Qt.rgba(1, 1, 1);
+ var blue = Qt.rgba(0, 0, 1);
+
+
+ // topleft
+ compare(image.pixel(40, 40), white);
+ compare(image.pixel(60, 40), white);
+ compare(image.pixel(40, 60), white);
+ compare(image.pixel(60, 60), blue);
+
+ // top
+ compare(image.pixel(140, 40), white);
+ compare(image.pixel(160, 40), white);
+ compare(image.pixel(140, 60), blue);
+ compare(image.pixel(160, 60), blue);
+
+ // topright
+ compare(image.pixel(240, 40), white);
+ compare(image.pixel(260, 40), white);
+ compare(image.pixel(240, 60), blue);
+ compare(image.pixel(260, 60), white);
+
+
+ // left
+ compare(image.pixel(40, 140), white);
+ compare(image.pixel(60, 140), blue);
+ compare(image.pixel(40, 160), white);
+ compare(image.pixel(60, 160), blue);
+
+ // center
+ compare(image.pixel(140, 140), blue);
+ compare(image.pixel(160, 140), blue);
+ compare(image.pixel(140, 160), blue);
+ compare(image.pixel(160, 160), blue);
+
+ // right
+ compare(image.pixel(240, 140), blue);
+ compare(image.pixel(260, 140), white);
+ compare(image.pixel(240, 160), blue);
+ compare(image.pixel(260, 160), white);
+
+
+ // bottomleft
+ compare(image.pixel(40, 240), white);
+ compare(image.pixel(60, 240), blue);
+ compare(image.pixel(40, 260), white);
+ compare(image.pixel(60, 260), white);
+
+ // bottom
+ compare(image.pixel(140, 240), blue);
+ compare(image.pixel(160, 240), blue);
+ compare(image.pixel(140, 260), white);
+ compare(image.pixel(160, 260), white);
+
+ // bottomright
+ compare(image.pixel(240, 240), blue);
+ compare(image.pixel(260, 240), white);
+ compare(image.pixel(240, 260), white);
+ compare(image.pixel(260, 260), white);
+
+ }
+ }
+
+ property var origins: [Item.TopLeft, Item.Top, Item.TopRight,
+ Item.Left, Item.Center, Item.Right,
+ Item.BottomLeft, Item.Bottom, Item.BottomRight];
+
+ Grid {
+ anchors.fill: parent
+ rows: 3
+ columns: 3
+
+ Repeater {
+ model: 9
+ Item {
+ width: 100
+ height: 100
+ Rectangle {
+ id: box
+ color: "blue"
+ anchors.centerIn: parent
+ width: 10
+ height: 10
+ antialiasing: true;
+
+ transformOrigin: root.origins[index];
+
+ ScaleAnimator { target: box; from: 1; to: 5.5; duration: 1000; running: true; }
+ }
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_transition.qml b/tests/auto/quick/qquickanimators/data/tst_transition.qml
new file mode 100644
index 0000000000..8e21a6537e
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_transition.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "transition"
+ when: box.scale == 2
+ function test_endresult() {
+ compare(box.scaleChangeCounter, 1);
+ compare(box.scale, 2);
+ var image = grabImage(root);
+ compare(image.pixel(0, 0), Qt.rgba(1, 0, 0));
+ compare(image.pixel(199, 199), Qt.rgba(0, 0, 1));
+ }
+ }
+
+ states: [
+ State {
+ name: "one"
+ PropertyChanges { target: box; scale: 1 }
+ },
+ State {
+ name: "two"
+ PropertyChanges { target: box; scale: 2 }
+ }
+ ]
+ state: "one"
+
+ transitions: [
+ Transition {
+ ScaleAnimator { duration: 200; }
+ }
+ ]
+
+ Box {
+ id: box
+ }
+
+ Timer {
+ interval: 1000;
+ repeat: false
+ running: true
+ onTriggered: root.state = "two"
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_x.qml b/tests/auto/quick/qquickanimators/data/tst_x.qml
new file mode 100644
index 0000000000..70ecf96346
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_x.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "x"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.xChangeCounter, 1);
+ compare(box.x, 100);
+ var image = grabImage(root);
+ compare(image.pixel(100, 50), Qt.rgba(1, 0, 0));
+ compare(image.pixel(99, 50), Qt.rgba(1, 1, 1)); // outside on the left
+ }
+ }
+
+ Box {
+ id: box
+
+ anchors.centerIn: undefined
+
+ XAnimator {
+ id: animation
+ target: box
+ from: 0;
+ to: 100
+ duration: 1000
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_y.qml b/tests/auto/quick/qquickanimators/data/tst_y.qml
new file mode 100644
index 0000000000..428d42a6c3
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_y.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testCase
+ name: "y"
+ when: !animation.running
+ function test_endresult() {
+ compare(box.yChangeCounter, 1);
+ compare(box.y, 100);
+ var image = grabImage(root);
+ compare(image.pixel(50, 100), Qt.rgba(1, 0, 0));
+ compare(image.pixel(50, 99), Qt.rgba(1, 1, 1)); // outside on the left
+ }
+ }
+
+ Box {
+ id: box
+
+ anchors.centerIn: undefined
+
+ YAnimator {
+ id: animation
+ target: box
+ from: 0;
+ to: 100
+ duration: 1000
+ running: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimators/qquickanimators.pro b/tests/auto/quick/qquickanimators/qquickanimators.pro
new file mode 100644
index 0000000000..4fa0438e41
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/qquickanimators.pro
@@ -0,0 +1,14 @@
+QT += core-private gui-private qml-private
+TEMPLATE=app
+TARGET=tst_qquickanimators
+
+CONFIG += qmltestcase
+SOURCES += tst_qquickanimators.cpp
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+ data/tst_scale.qml \
+ data/Scale.qml \
+ tst_on.qml \
+ data/tst_nested.qml
diff --git a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
new file mode 100644
index 0000000000..f3f982091f
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQuickTest/quicktest.h>
+
+QUICK_TEST_MAIN(qquickanimators)