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>
This commit is contained in:
Gunnar Sletta 2013-09-18 20:16:16 +02:00 committed by The Qt Project
parent 0fc040ef70
commit a0f8be4021
41 changed files with 3804 additions and 22 deletions

View File

@ -277,6 +277,8 @@ QAbstractAnimationJob::QAbstractAnimationJob()
, m_isGroup(false)
, m_disableUserControl(false)
, m_hasCurrentTimeChangeListeners(false)
, m_isRenderThreadJob(false)
, m_isRenderThreadProxy(false)
{
}

View File

@ -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;

View File

@ -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]
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -79,6 +79,8 @@ public:
static QSGRenderLoop *instance();
static void setInstance(QSGRenderLoop *instance);
static bool useConsistentTiming();
virtual bool interleaveIncubation() const { return false; }
Q_SIGNALS:

View File

@ -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 {

View File

@ -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
{

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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
}
}
}

View File

@ -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 }
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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; }
}
}
}
}
}

View File

@ -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"
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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)