diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-11-15 15:22:27 +0000 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-11-16 14:14:17 +0000 |
commit | 91ac8d0264a3777a9d61f704001d032747e25c9f (patch) | |
tree | 1f9c8b98f952d8addb5f658a2e2f6bf322f39d81 | |
parent | 2dbe6976030b9f4c48d5325bd63a008cd89cb46d (diff) |
Split animation callback handling into its own frontend class
This keeps things consistent between the 3 mapping types:
* Regular properties
* Callbacks
* Skeletons
The ChannelMapping backend node handles all 3 frontend types.
Change-Id: I824aeb25aa69d96f20d844e7d953c68567829321
Reviewed-by: Mike Krus <mike.krus@kdab.com>
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/animation/backend/channelmapping.cpp | 12 | ||||
-rw-r--r-- | src/animation/frontend/frontend.pri | 7 | ||||
-rw-r--r-- | src/animation/frontend/qanimationcallback.h | 1 | ||||
-rw-r--r-- | src/animation/frontend/qcallbackmapping.cpp | 168 | ||||
-rw-r--r-- | src/animation/frontend/qcallbackmapping.h | 82 | ||||
-rw-r--r-- | src/animation/frontend/qcallbackmapping_p.h | 85 | ||||
-rw-r--r-- | src/animation/frontend/qchannelmapping.cpp | 60 | ||||
-rw-r--r-- | src/animation/frontend/qchannelmapping.h | 3 | ||||
-rw-r--r-- | src/animation/frontend/qchannelmapping_p.h | 4 | ||||
-rw-r--r-- | tests/auto/animation/animation.pro | 3 | ||||
-rw-r--r-- | tests/auto/animation/qcallbackmapping/qcallbackmapping.pro | 12 | ||||
-rw-r--r-- | tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp | 223 |
12 files changed, 586 insertions, 74 deletions
diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp index 25f63506b..ecae8bbae 100644 --- a/src/animation/backend/channelmapping.cpp +++ b/src/animation/backend/channelmapping.cpp @@ -36,6 +36,7 @@ #include "channelmapping_p.h" #include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/private/qcallbackmapping_p.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> #include <Qt3DAnimation/private/qskeletonmapping_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> @@ -74,8 +75,6 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt m_property = data.property; m_type = data.type; m_propertyName = data.propertyName; - m_callback = data.callback; - m_callbackFlags = data.callbackFlags; m_mappingType = ChannelMappingType; break; } @@ -89,8 +88,13 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt } case QChannelMappingCreatedChangeBase::CallbackMapping: { - // TODO: Refactor callback support out of QChannelMapping and into its own type - m_mappingType = CallbackMappingType; + const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QCallbackMappingData>>(change); + const auto &data = typedChange->data; + m_channelName = data.channelName; + m_type = data.type; + m_callback = data.callback; + m_callbackFlags = data.callbackFlags; + m_mappingType = ChannelMappingType; break; } } diff --git a/src/animation/frontend/frontend.pri b/src/animation/frontend/frontend.pri index 48b1cb6b1..baff81dd0 100644 --- a/src/animation/frontend/frontend.pri +++ b/src/animation/frontend/frontend.pri @@ -54,7 +54,9 @@ HEADERS += \ $$PWD/qchannelmappingcreatedchange_p.h \ $$PWD/qchannelmappingcreatedchange_p_p.h \ $$PWD/qskeletonmapping.h \ - $$PWD/qskeletonmapping_p.h + $$PWD/qskeletonmapping_p.h \ + $$PWD/qcallbackmapping.h \ + $$PWD/qcallbackmapping_p.h SOURCES += \ $$PWD/qanimationaspect.cpp \ @@ -86,6 +88,7 @@ SOURCES += \ $$PWD/qclock.cpp \ $$PWD/qabstractchannelmapping.cpp \ $$PWD/qchannelmappingcreatedchange.cpp \ - $$PWD/qskeletonmapping.cpp + $$PWD/qskeletonmapping.cpp \ + $$PWD/qcallbackmapping.cpp INCLUDEPATH += $$PWD diff --git a/src/animation/frontend/qanimationcallback.h b/src/animation/frontend/qanimationcallback.h index 63e094918..1fcbd657c 100644 --- a/src/animation/frontend/qanimationcallback.h +++ b/src/animation/frontend/qanimationcallback.h @@ -48,6 +48,7 @@ class QT3DANIMATIONSHARED_EXPORT QAnimationCallback { public: enum Flag { + OnOwningThread = 0x0, OnThreadPool = 0x01 }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/animation/frontend/qcallbackmapping.cpp b/src/animation/frontend/qcallbackmapping.cpp new file mode 100644 index 000000000..3fcc7cf5e --- /dev/null +++ b/src/animation/frontend/qcallbackmapping.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcallbackmapping.h" +#include "qcallbackmapping_p.h" + +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> + +#include <QtCore/qmetaobject.h> +#include <QtCore/QMetaProperty> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { + +QCallbackMappingPrivate::QCallbackMappingPrivate() + : QAbstractChannelMappingPrivate() + , m_channelName() + , m_type(static_cast<int>(QVariant::Invalid)) + , m_callback(nullptr) + , m_callbackFlags(0) +{ + m_mappingType = QChannelMappingCreatedChangeBase::CallbackMapping; +} + +/*! + \class QCallbackMapping + \inherits Qt3DCore::QAbstractChannelMapping + \inmodule Qt3DAnimation + \brief Allows to map the channels within the clip onto an invocation + of a callback object. +*/ + +QCallbackMapping::QCallbackMapping(Qt3DCore::QNode *parent) + : QAbstractChannelMapping(*new QCallbackMappingPrivate, parent) +{ +} + +QCallbackMapping::QCallbackMapping(QCallbackMappingPrivate &dd, Qt3DCore::QNode *parent) + : QAbstractChannelMapping(dd, parent) +{ +} + +QCallbackMapping::~QCallbackMapping() +{ +} + +QString QCallbackMapping::channelName() const +{ + Q_D(const QCallbackMapping); + return d->m_channelName; +} + +QAnimationCallback *QCallbackMapping::callback() const +{ + Q_D(const QCallbackMapping); + return d->m_callback; +} + +void QCallbackMapping::setChannelName(const QString &channelName) +{ + Q_D(QCallbackMapping); + if (d->m_channelName == channelName) + return; + + d->m_channelName = channelName; + emit channelNameChanged(channelName); +} + +/*! + Associates a \a callback object with this channel mapping. + + Such mappings do not have to have a target object and property name. When + the \a callback object is set, every change in the animated value will lead + to invoking the callback's + \l{QAnimationCallback::onValueChanged()}{onValueChanged()} function either + on the gui/main thread, or directly on one of the thread pool's worker + thread. This is controlled by \a flags. + + \a type specifies the type (for example, QVariant::Vector3D, + QVariant::Color, or QMetaType::Float) of the animated value. When animating + node properties this does not need to be provided separately, however it + becomes important to supply this when there is only a callback. + + \note A mapping can be associated both with a node property and a + callback. It is important however that \a type matches the type of the + property in this case. Note also that for properties of type QVariant (for + example, QParameter::value), the \a type is the type of the value stored in + the QVariant. + + \note The \a callback pointer is expected to stay valid while any + associated animators are running. + */ +void QCallbackMapping::setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags) +{ + Q_D(QCallbackMapping); + if (d->m_type != type) { + d->m_type = type; + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); + e->setPropertyName("type"); + e->setValue(QVariant(d->m_type)); + notifyObservers(e); + } + if (d->m_callback != callback) { + d->m_callback = callback; + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); + e->setPropertyName("callback"); + e->setValue(QVariant::fromValue(static_cast<void *>(d->m_callback))); + notifyObservers(e); + } + if (d->m_callbackFlags != flags) { + d->m_callbackFlags = flags; + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); + e->setPropertyName("callbackFlags"); + e->setValue(QVariant::fromValue(int(d->m_callbackFlags))); + notifyObservers(e); + } +} + +Qt3DCore::QNodeCreatedChangeBasePtr QCallbackMapping::createNodeCreationChange() const +{ + auto creationChange = QChannelMappingCreatedChangePtr<QCallbackMappingData>::create(this); + auto &data = creationChange->data; + Q_D(const QCallbackMapping); + data.channelName = d->m_channelName; + data.type = d->m_type; + data.callback = d->m_callback; + data.callbackFlags = d->m_callbackFlags; + return creationChange; +} + +} // namespace Qt3DAnimation + +QT_END_NAMESPACE diff --git a/src/animation/frontend/qcallbackmapping.h b/src/animation/frontend/qcallbackmapping.h new file mode 100644 index 000000000..c52e284ff --- /dev/null +++ b/src/animation/frontend/qcallbackmapping.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DANIMATION_QCALLBACKMAPPING_H +#define QT3DANIMATION_QCALLBACKMAPPING_H + +#include <Qt3DAnimation/qt3danimation_global.h> +#include <Qt3DAnimation/qanimationcallback.h> +#include <Qt3DAnimation/qabstractchannelmapping.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { + +class QCallbackMappingPrivate; + +class QT3DANIMATIONSHARED_EXPORT QCallbackMapping : public QAbstractChannelMapping +{ + Q_OBJECT + Q_PROPERTY(QString channelName READ channelName WRITE setChannelName NOTIFY channelNameChanged) + +public: + explicit QCallbackMapping(Qt3DCore::QNode *parent = nullptr); + ~QCallbackMapping(); + + QString channelName() const; + QAnimationCallback *callback() const; + + void setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags = QAnimationCallback::OnOwningThread); + +public Q_SLOTS: + void setChannelName(const QString &channelName); + +Q_SIGNALS: + void channelNameChanged(QString channelName); + +protected: + explicit QCallbackMapping(QCallbackMappingPrivate &dd, Qt3DCore::QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QCallbackMapping) + Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE; +}; + +} // namespace Qt3DAnimation + +QT_END_NAMESPACE + +#endif // QT3DANIMATION_QCALLBACKMAPPING_H diff --git a/src/animation/frontend/qcallbackmapping_p.h b/src/animation/frontend/qcallbackmapping_p.h new file mode 100644 index 000000000..c966ca552 --- /dev/null +++ b/src/animation/frontend/qcallbackmapping_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DANIMATION_QCALLBACKMAPPING_P_H +#define QT3DANIMATION_QCALLBACKMAPPING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DAnimation/private/qabstractchannelmapping_p.h> +#include <Qt3DAnimation/qanimationcallback.h> +#include <Qt3DAnimation/qcallbackmapping.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { + +class QCallbackMappingPrivate : public QAbstractChannelMappingPrivate +{ +public: + QCallbackMappingPrivate(); + + Q_DECLARE_PUBLIC(QCallbackMapping) + + QString m_channelName; + int m_type; + QAnimationCallback *m_callback; + QAnimationCallback::Flags m_callbackFlags; +}; + +struct QCallbackMappingData +{ + QString channelName; + int type; + QAnimationCallback *callback; + QAnimationCallback::Flags callbackFlags; +}; + +} // namespace Qt3DAnimation + + +QT_END_NAMESPACE + +#endif // QT3DANIMATION_QCALLBACKMAPPING_P_H diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp index cb7b0739f..722ce24b0 100644 --- a/src/animation/frontend/qchannelmapping.cpp +++ b/src/animation/frontend/qchannelmapping.cpp @@ -54,8 +54,6 @@ QChannelMappingPrivate::QChannelMappingPrivate() , m_property() , m_propertyName(nullptr) , m_type(static_cast<int>(QVariant::Invalid)) - , m_callback(nullptr) - , m_callbackFlags(0) { m_mappingType = QChannelMappingCreatedChangeBase::ChannelMapping; } @@ -152,12 +150,6 @@ QString QChannelMapping::property() const return d->m_property; } -QAnimationCallback *QChannelMapping::callback() const -{ - Q_D(const QChannelMapping); - return d->m_callback; -} - void QChannelMapping::setChannelName(const QString &channelName) { Q_D(QChannelMapping); @@ -200,56 +192,6 @@ void QChannelMapping::setProperty(const QString &property) d->updatePropertyNameAndType(); } -/*! - Associates a \a callback object with this channel mapping. - - Such mappings do not have to have a target object and property name. When - the \a callback object is set, every change in the animated value will lead - to invoking the callback's - \l{QAnimationCallback::onValueChanged()}{onValueChanged()} function either - on the gui/main thread, or directly on one of the thread pool's worker - thread. This is controlled by \a flags. - - \a type specifies the type (for example, QVariant::Vector3D, - QVariant::Color, or QMetaType::Float) of the animated value. When animating - node properties this does not need to be provided separately, however it - becomes important to supply this when there is only a callback. - - \note A mapping can be associated both with a node property and a - callback. It is important however that \a type matches the type of the - property in this case. Note also that for properties of type QVariant (for - example, QParameter::value), the \a type is the type of the value stored in - the QVariant. - - \note The \a callback pointer is expected to stay valid while any - associated animators are running. - */ -void QChannelMapping::setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags) -{ - Q_D(QChannelMapping); - if (d->m_type != type) { - d->m_type = type; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("type"); - e->setValue(QVariant(d->m_type)); - notifyObservers(e); - } - if (d->m_callback != callback) { - d->m_callback = callback; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("callback"); - e->setValue(QVariant::fromValue(static_cast<void *>(d->m_callback))); - notifyObservers(e); - } - if (d->m_callbackFlags != flags) { - d->m_callbackFlags = flags; - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("callbackFlags"); - e->setValue(QVariant::fromValue(int(d->m_callbackFlags))); - notifyObservers(e); - } -} - Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange() const { auto creationChange = QChannelMappingCreatedChangePtr<QChannelMappingData>::create(this); @@ -260,8 +202,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange() data.property = d->m_property; data.type = d->m_type; data.propertyName = d->m_propertyName; - data.callback = d->m_callback; - data.callbackFlags = d->m_callbackFlags; return creationChange; } diff --git a/src/animation/frontend/qchannelmapping.h b/src/animation/frontend/qchannelmapping.h index 08bda13aa..893b98e86 100644 --- a/src/animation/frontend/qchannelmapping.h +++ b/src/animation/frontend/qchannelmapping.h @@ -61,9 +61,6 @@ public: QString channelName() const; Qt3DCore::QNode *target() const; QString property() const; - QAnimationCallback *callback() const; - - void setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags); public Q_SLOTS: void setChannelName(const QString &channelName); diff --git a/src/animation/frontend/qchannelmapping_p.h b/src/animation/frontend/qchannelmapping_p.h index b9f1f950c..b7de3b821 100644 --- a/src/animation/frontend/qchannelmapping_p.h +++ b/src/animation/frontend/qchannelmapping_p.h @@ -69,8 +69,6 @@ public: QString m_property; const char *m_propertyName; int m_type; - QAnimationCallback *m_callback; - QAnimationCallback::Flags m_callbackFlags; }; struct QChannelMappingData @@ -80,8 +78,6 @@ struct QChannelMappingData QString property; int type; const char *propertyName; - QAnimationCallback *callback; - QAnimationCallback::Flags callbackFlags; }; } // namespace Qt3DAnimation diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index c97b07923..1226f9498 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -15,7 +15,8 @@ SUBDIRS += \ qmorphtarget \ qvertexblendanimation \ qclock \ - qskeletonmapping + qskeletonmapping \ + qcallbackmapping qtConfig(private_tests) { SUBDIRS += \ diff --git a/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro new file mode 100644 index 000000000..2ec002878 --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qcallbackmapping + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qcallbackmapping.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp new file mode 100644 index 000000000..6a1c8da8c --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qcallbackmapping.h> +#include <Qt3DAnimation/private/qcallbackmapping_p.h> +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class DummyCallback : public Qt3DAnimation::QAnimationCallback +{ +public: + void valueChanged(const QVariant &) override { } +}; + +class tst_QCallbackMapping : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + // THEN + QCOMPARE(mapping.channelName(), QString()); + QCOMPARE(mapping.callback(), static_cast<Qt3DAnimation::QAnimationCallback *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + { + // WHEN + QSignalSpy spy(&mapping, SIGNAL(channelNameChanged(QString))); + const QString newValue(QStringLiteral("Rotation")); + mapping.setChannelName(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mapping.setChannelName(newValue); + + // THEN + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + auto newValue = new DummyCallback(); + mapping.setCallback(QVariant::Quaternion, newValue); + + // THEN - no signals for callback + QCOMPARE(mapping.callback(), newValue); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + auto callback = new DummyCallback(); + + mapping.setChannelName(QStringLiteral("Location")); + mapping.setCallback(QVariant::Vector3D, callback); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), true); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + + // WHEN + mapping.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), false); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QCallbackMapping mapping; + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "channelName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toString(), mapping.channelName()); + + arbiter.events.clear(); + + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + auto callback = new DummyCallback(); + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 3); + auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), QVariant::Vector3D); + + change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callback"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(reinterpret_cast<DummyCallback *>(change->value().value<void *>()), callback); + + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callbackFlags"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), static_cast<int>(Qt3DAnimation::QAnimationCallback::OnThreadPool)); + + arbiter.events.clear(); + + // WHEN + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QCallbackMapping) + +#include "tst_qcallbackmapping.moc" |