aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@digia.com>2013-09-18 20:16:16 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-21 22:23:13 +0200
commita0f8be4021caa9bb5055923f0eea3bee0e345235 (patch)
treecf33dd92e8284f5692e65b1a574749d50da4a3f0 /src
parent0fc040ef70513ccaeb9e96f7ca05a3df4d6c7879 (diff)
Animators - Render thread animation system
This introduces 6 new QML types for animating state in the scene graph when the UI thread is blocked. The QObject property being animated is updated after the animation completes. It works also with the "windows" and "basic" render loops, but offer litte benefit then compared to in the "threaded" case. Change-Id: Ic19e47c898c0b8bd53e457db922b3c9c457c8147 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-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
23 files changed, 2420 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