summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial.cpp3
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp3
-rw-r--r--src/input/backend/abstractactioninput.cpp58
-rw-r--r--src/input/backend/abstractactioninput_p.h81
-rw-r--r--src/input/backend/actioninput.cpp32
-rw-r--r--src/input/backend/actioninput_p.h6
-rw-r--r--src/input/backend/backend.pri2
-rw-r--r--src/input/backend/inputchord.cpp40
-rw-r--r--src/input/backend/inputchord_p.h10
-rw-r--r--src/input/backend/inputhandler.cpp10
-rw-r--r--src/input/backend/inputhandler_p.h4
-rw-r--r--src/input/backend/inputsequence.cpp41
-rw-r--r--src/input/backend/inputsequence_p.h14
-rw-r--r--src/input/backend/updateaxisactionjob.cpp62
-rw-r--r--src/input/frontend/qinputaspect.cpp1
-rw-r--r--src/render/frontend/qrenderaspect.cpp1
-rw-r--r--src/render/io/qsceneloader.cpp9
-rw-r--r--src/render/io/qsceneloader_p.h3
-rw-r--r--src/render/io/scene.cpp10
-rw-r--r--src/render/io/scene_p.h2
-rw-r--r--src/render/io/scenemanager.cpp7
-rw-r--r--src/render/jobs/loadscenejob.cpp23
-rw-r--r--src/render/jobs/loadtexturedatajob.cpp3
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/extras/extras.pro4
-rw-r--r--tests/auto/extras/qcuboidgeometry/qcuboidgeometry.pro (renamed from tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro)3
-rw-r--r--tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp (renamed from tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp)0
-rw-r--r--tests/auto/input/abstractaxisinput/abstractaxisinput.pro1
-rw-r--r--tests/auto/input/actioninput/actioninput.pro11
-rw-r--r--tests/auto/input/actioninput/tst_actioninput.cpp179
-rw-r--r--tests/auto/input/analogaxisinput/analogaxisinput.pro1
-rw-r--r--tests/auto/input/buttonaxisinput/buttonaxisinput.pro1
-rw-r--r--tests/auto/input/commons/commons.pri3
-rw-r--r--tests/auto/input/commons/testdevice.h107
-rw-r--r--tests/auto/input/input.pro5
-rw-r--r--tests/auto/input/inputchord/inputchord.pro11
-rw-r--r--tests/auto/input/inputchord/tst_inputchord.cpp281
-rw-r--r--tests/auto/input/inputsequence/inputsequence.pro11
-rw-r--r--tests/auto/input/inputsequence/tst_inputsequence.cpp400
-rw-r--r--tests/auto/input/keyboardhandler/keyboardhandler.pro1
-rw-r--r--tests/auto/render/qcameralens/qcameralens.pro12
-rw-r--r--tests/auto/render/qcameralens/tst_qcameralens.cpp717
-rw-r--r--tests/auto/render/qcomputecommand/qcomputecommand.pro12
-rw-r--r--tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp282
-rw-r--r--tests/auto/render/qrendertargetoutput/qrendertargetoutput.pro12
-rw-r--r--tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp407
-rw-r--r--tests/auto/render/qsceneloader/tst_qsceneloader.cpp68
-rw-r--r--tests/auto/render/render.pro6
-rw-r--r--tests/auto/render/sceneloader/tst_sceneloader.cpp22
49 files changed, 2869 insertions, 116 deletions
diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.cpp b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
index 01d67a477..c38756c98 100644
--- a/src/extras/defaults/qnormaldiffusemapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
@@ -86,8 +86,9 @@ QNormalDiffuseMapMaterialPrivate::QNormalDiffuseMapMaterialPrivate()
m_diffuseTexture->setMaximumAnisotropy(16.0f);
m_normalTexture->setMagnificationFilter(QAbstractTexture::Linear);
- m_normalTexture->setMinificationFilter(QAbstractTexture::Linear);
+ m_normalTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
m_normalTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_normalTexture->setGenerateMipMaps(true);
m_normalTexture->setMaximumAnisotropy(16.0f);
}
diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
index 6d54b9535..3c26fde5a 100644
--- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
@@ -87,8 +87,9 @@ QNormalDiffuseSpecularMapMaterialPrivate::QNormalDiffuseSpecularMapMaterialPriva
m_diffuseTexture->setMaximumAnisotropy(16.0f);
m_normalTexture->setMagnificationFilter(QAbstractTexture::Linear);
- m_normalTexture->setMinificationFilter(QAbstractTexture::Linear);
+ m_normalTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear);
m_normalTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat));
+ m_normalTexture->setGenerateMipMaps(true);
m_normalTexture->setMaximumAnisotropy(16.0f);
m_specularTexture->setMagnificationFilter(QAbstractTexture::Linear);
diff --git a/src/input/backend/abstractactioninput.cpp b/src/input/backend/abstractactioninput.cpp
new file mode 100644
index 000000000..1d4366554
--- /dev/null
+++ b/src/input/backend/abstractactioninput.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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: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 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 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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractactioninput_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DInput {
+
+namespace Input {
+
+AbstractActionInput::AbstractActionInput()
+ : Qt3DCore::QBackendNode()
+{
+}
+
+} // namespace Input
+
+} // namespace Qt3DInput
+
+QT_END_NAMESPACE
+
diff --git a/src/input/backend/abstractactioninput_p.h b/src/input/backend/abstractactioninput_p.h
new file mode 100644
index 000000000..267d276c7
--- /dev/null
+++ b/src/input/backend/abstractactioninput_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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: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 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 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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DINPUT_INPUT_ABSTRACTACTIONINPUT_H
+#define QT3DINPUT_INPUT_ABSTRACTACTIONINPUT_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 <Qt3DCore/qbackendnode.h>
+#include <Qt3DCore/qnodeid.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DInput {
+
+namespace Input {
+
+class InputHandler;
+
+class Q_AUTOTEST_EXPORT AbstractActionInput : public Qt3DCore::QBackendNode
+{
+public:
+ AbstractActionInput();
+
+ inline static qint64 milliToNano(qint64 milli) { return milli * 1000000; }
+
+ virtual bool process(InputHandler *inputHandler, qint64 currentTime) = 0;
+};
+
+} // namespace Input
+
+} // namespace Qt3DInput
+
+QT_END_NAMESPACE
+
+#endif // QT3DINPUT_INPUT_ABSTRACTACTIONINPUT_H
diff --git a/src/input/backend/actioninput.cpp b/src/input/backend/actioninput.cpp
index b4cdd77ca..c22d20730 100644
--- a/src/input/backend/actioninput.cpp
+++ b/src/input/backend/actioninput.cpp
@@ -41,6 +41,8 @@
#include <Qt3DInput/qactioninput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/private/qactioninput_p.h>
+#include <Qt3DInput/private/qinputdeviceintegration_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -50,7 +52,7 @@ namespace Qt3DInput {
namespace Input {
ActionInput::ActionInput()
- : Qt3DCore::QBackendNode()
+ : AbstractActionInput()
, m_buttons(0)
{
}
@@ -65,7 +67,7 @@ void ActionInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &
void ActionInput::cleanup()
{
- QBackendNode::setEnabled(false);
+ setEnabled(false);
m_sourceDevice = Qt3DCore::QNodeId();
m_buttons.clear();
}
@@ -80,7 +82,31 @@ void ActionInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_buttons = propertyChange->value().value<QVector<int>>();
}
}
- QBackendNode::sceneChangeEvent(e);
+ AbstractActionInput::sceneChangeEvent(e);
+}
+
+bool ActionInput::process(InputHandler *inputHandler, qint64 currentTime)
+{
+ Q_UNUSED(currentTime);
+
+ QAbstractPhysicalDeviceBackendNode *physicalDeviceBackend = nullptr;
+
+ const auto integrations = inputHandler->inputDeviceIntegrations();
+ for (QInputDeviceIntegration *integration : integrations) {
+ physicalDeviceBackend = integration->physicalDevice(sourceDevice());
+ if (physicalDeviceBackend)
+ break;
+ }
+
+ if (!physicalDeviceBackend)
+ return false;
+
+ for (int button : qAsConst(m_buttons)) {
+ if (physicalDeviceBackend->isButtonPressed(button))
+ return true;
+ }
+
+ return false;
}
} // namespace Input
diff --git a/src/input/backend/actioninput_p.h b/src/input/backend/actioninput_p.h
index c3e80ba63..da99c985e 100644
--- a/src/input/backend/actioninput_p.h
+++ b/src/input/backend/actioninput_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +60,7 @@ namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT ActionInput : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT ActionInput : public AbstractActionInput
{
public:
ActionInput();
@@ -70,6 +70,8 @@ public:
inline Qt3DCore::QNodeId sourceDevice() const { return m_sourceDevice; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ bool process(InputHandler *inputHandler, qint64 currentTime) Q_DECL_OVERRIDE;
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
diff --git a/src/input/backend/backend.pri b/src/input/backend/backend.pri
index 74ee7f3b6..5c22f0e50 100644
--- a/src/input/backend/backend.pri
+++ b/src/input/backend/backend.pri
@@ -11,6 +11,7 @@ HEADERS += \
$$PWD/mousedevice_p.h \
$$PWD/mouseeventdispatcherjob_p.h \
$$PWD/mouseeventfilter_p.h \
+ $$PWD/abstractactioninput_p.h \
$$PWD/abstractaxisinput_p.h \
$$PWD/actioninput_p.h \
$$PWD/axis_p.h \
@@ -43,6 +44,7 @@ SOURCES += \
$$PWD/mousedevice.cpp \
$$PWD/mouseeventfilter.cpp \
$$PWD/mouseeventdispatcherjob.cpp \
+ $$PWD/abstractactioninput.cpp \
$$PWD/abstractaxisinput.cpp \
$$PWD/actioninput.cpp \
$$PWD/axis.cpp \
diff --git a/src/input/backend/inputchord.cpp b/src/input/backend/inputchord.cpp
index 7ecd611a8..a37bb8ea4 100644
--- a/src/input/backend/inputchord.cpp
+++ b/src/input/backend/inputchord.cpp
@@ -40,6 +40,7 @@
#include "inputchord_p.h"
#include <Qt3DInput/qinputchord.h>
#include <Qt3DInput/private/qinputchord_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
@@ -51,7 +52,7 @@ namespace Qt3DInput {
namespace Input {
InputChord::InputChord()
- : Qt3DCore::QBackendNode()
+ : AbstractActionInput()
, m_chords()
, m_inputsToTrigger()
, m_timeout(0)
@@ -64,12 +65,13 @@ void InputChord::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &c
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputChordData>>(change);
const QInputChordData &data = typedChange->data;
m_chords = data.chordIds;
- m_timeout = data.timeout;
+ m_timeout = milliToNano(data.timeout);
+ m_inputsToTrigger = m_chords;
}
void InputChord::cleanup()
{
- QBackendNode::setEnabled(false);
+ setEnabled(false);
m_timeout = 0;
m_startTime = 0;
m_chords.clear();
@@ -104,7 +106,7 @@ void InputChord::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
case Qt3DCore::PropertyUpdated: {
const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
if (change->propertyName() == QByteArrayLiteral("timeout"))
- m_timeout = change->value().toInt();
+ m_timeout = milliToNano(change->value().toInt());
break;
}
@@ -129,7 +131,35 @@ void InputChord::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
default:
break;
}
- QBackendNode::sceneChangeEvent(e);
+ AbstractActionInput::sceneChangeEvent(e);
+}
+
+bool InputChord::process(InputHandler *inputHandler, qint64 currentTime)
+{
+ const qint64 startTime = m_startTime;
+ bool triggered = false;
+ int activeInputs = 0;
+ for (const Qt3DCore::QNodeId &actionInputId : qAsConst(m_chords)) {
+ AbstractActionInput *actionInput = inputHandler->lookupActionInput(actionInputId);
+ if (actionInput && actionInput->process(inputHandler, currentTime)) {
+ triggered |= actionTriggered(actionInputId);
+ activeInputs++;
+ if (startTime == 0)
+ m_startTime = currentTime;
+ }
+ }
+
+ if (startTime != 0) {
+ // Check if we are still inside the time limit for the chord
+ if ((currentTime - startTime) > m_timeout) {
+ reset();
+ if (activeInputs > 0)
+ m_startTime = startTime;
+ return false;
+ }
+ }
+
+ return triggered;
}
} // namespace Input
diff --git a/src/input/backend/inputchord_p.h b/src/input/backend/inputchord_p.h
index db197df3c..7f51f5d96 100644
--- a/src/input/backend/inputchord_p.h
+++ b/src/input/backend/inputchord_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -60,26 +60,28 @@ namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT InputChord : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT InputChord : public AbstractActionInput
{
public:
InputChord();
void cleanup();
inline QVector<Qt3DCore::QNodeId> chords() const { return m_chords; }
- inline int timeout() const { return m_timeout; }
+ inline qint64 timeout() const { return m_timeout; }
inline qint64 startTime() const { return m_startTime; }
void setStartTime(qint64 time);
void reset();
bool actionTriggered(Qt3DCore::QNodeId input);
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ bool process(InputHandler *inputHandler, qint64 currentTime) Q_DECL_OVERRIDE;
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
QVector<Qt3DCore::QNodeId> m_chords;
QVector<Qt3DCore::QNodeId> m_inputsToTrigger;
- int m_timeout;
+ qint64 m_timeout;
qint64 m_startTime;
};
diff --git a/src/input/backend/inputhandler.cpp b/src/input/backend/inputhandler.cpp
index a26ebce61..82b017b1c 100644
--- a/src/input/backend/inputhandler.cpp
+++ b/src/input/backend/inputhandler.cpp
@@ -309,6 +309,16 @@ void InputHandler::updateEventSource()
}
}
+AbstractActionInput *InputHandler::lookupActionInput(Qt3DCore::QNodeId id) const
+{
+ AbstractActionInput *input = nullptr;
+ if ((input = actionInputManager()->lookupResource(id)) != nullptr)
+ return input;
+ if ((input = inputSequenceManager()->lookupResource(id)) != nullptr)
+ return input;
+ return inputChordManager()->lookupResource(id); // nullptr if not found
+}
+
} // namespace Input
} // namespace Qt3DInput
diff --git a/src/input/backend/inputhandler_p.h b/src/input/backend/inputhandler_p.h
index 72078b54c..2cfb56e3f 100644
--- a/src/input/backend/inputhandler_p.h
+++ b/src/input/backend/inputhandler_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QEventFilterService;
+class QNodeId;
}
namespace Qt3DInput {
@@ -69,6 +70,7 @@ class QInputDeviceIntegration;
namespace Input {
+class AbstractActionInput;
class KeyboardInputManager;
class KeyboardDeviceManager;
class KeyboardEventFilter;
@@ -144,6 +146,8 @@ public:
void updateEventSource();
+ AbstractActionInput *lookupActionInput(Qt3DCore::QNodeId id) const;
+
private:
KeyboardDeviceManager *m_keyboardDeviceManager;
KeyboardInputManager *m_keyboardInputManager;
diff --git a/src/input/backend/inputsequence.cpp b/src/input/backend/inputsequence.cpp
index aae88f9a1..378a7d33d 100644
--- a/src/input/backend/inputsequence.cpp
+++ b/src/input/backend/inputsequence.cpp
@@ -41,6 +41,7 @@
#include <Qt3DInput/qinputsequence.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/private/qinputsequence_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
@@ -53,7 +54,7 @@ namespace Qt3DInput {
namespace Input {
InputSequence::InputSequence()
- : Qt3DCore::QBackendNode()
+ : AbstractActionInput()
, m_sequences()
, m_inputsToTrigger()
, m_timeout(0)
@@ -68,13 +69,14 @@ void InputSequence::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputSequenceData>>(change);
const QInputSequenceData &data = typedChange->data;
m_sequences = data.sequenceIds;
- m_timeout = data.timeout;
- m_buttonInterval = data.buttonInterval;
+ m_timeout = milliToNano(data.timeout);
+ m_buttonInterval = milliToNano(data.buttonInterval);
+ m_inputsToTrigger = m_sequences;
}
void InputSequence::cleanup()
{
- QBackendNode::setEnabled(false);
+ setEnabled(false);
m_timeout = 0;
m_buttonInterval = 0;
m_startTime = 0;
@@ -99,6 +101,9 @@ void InputSequence::reset()
bool InputSequence::actionTriggered(Qt3DCore::QNodeId input, const qint64 currentTime)
{
+ if (input != m_inputsToTrigger.first())
+ return false;
+
// Save the last input
m_lastInputId = input;
// Return false if we've spent too much time in between two sequences
@@ -126,9 +131,9 @@ void InputSequence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
case Qt3DCore::PropertyUpdated: {
const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
if (change->propertyName() == QByteArrayLiteral("timeout")) {
- m_timeout = change->value().toInt();
+ m_timeout = milliToNano(change->value().toInt());
} else if (change->propertyName() == QByteArrayLiteral("buttonInterval")) {
- m_buttonInterval = change->value().toInt();
+ m_buttonInterval = milliToNano(change->value().toInt());
}
break;
}
@@ -154,7 +159,29 @@ void InputSequence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
default:
break;
}
- QBackendNode::sceneChangeEvent(e);
+ AbstractActionInput::sceneChangeEvent(e);
+}
+
+bool InputSequence::process(InputHandler *inputHandler, qint64 currentTime)
+{
+ if (m_startTime != 0) {
+ // Check if we are still inside the time limit for the sequence
+ if ((currentTime - m_startTime) > m_timeout) {
+ reset();
+ return false;
+ }
+ }
+
+ bool triggered = false;
+ for (const Qt3DCore::QNodeId &actionInputId : qAsConst(m_sequences)) {
+ AbstractActionInput *actionInput = inputHandler->lookupActionInput(actionInputId);
+ if (actionInput && actionInput->process(inputHandler, currentTime)) {
+ triggered |= actionTriggered(actionInputId, currentTime);
+ if (m_startTime == 0)
+ m_startTime = currentTime;
+ }
+ }
+ return triggered;
}
} // namespace Input
diff --git a/src/input/backend/inputsequence_p.h b/src/input/backend/inputsequence_p.h
index a76457f4e..28cb1c0e1 100644
--- a/src/input/backend/inputsequence_p.h
+++ b/src/input/backend/inputsequence_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/abstractactioninput_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -60,15 +60,15 @@ namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT InputSequence : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT InputSequence : public AbstractActionInput
{
public:
InputSequence();
void cleanup();
inline QVector<Qt3DCore::QNodeId> sequences() const { return m_sequences; }
- inline int timeout() const { return m_timeout; }
- inline int buttonInterval() const { return m_buttonInterval; }
+ inline qint64 timeout() const { return m_timeout; }
+ inline qint64 buttonInterval() const { return m_buttonInterval; }
inline qint64 startTime() const { return m_startTime; }
void setStartTime(qint64 time);
bool sequenceTriggered() const;
@@ -76,13 +76,15 @@ public:
bool actionTriggered(Qt3DCore::QNodeId input, const qint64 currentTime);
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ bool process(InputHandler *inputHandler, qint64 currentTime) Q_DECL_OVERRIDE;
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
QVector<Qt3DCore::QNodeId> m_sequences;
QVector<Qt3DCore::QNodeId> m_inputsToTrigger;
- int m_timeout;
- int m_buttonInterval;
+ qint64 m_timeout;
+ qint64 m_buttonInterval;
qint64 m_startTime;
qint64 m_lastInputTime;
Qt3DCore::QNodeId m_lastInputId;
diff --git a/src/input/backend/updateaxisactionjob.cpp b/src/input/backend/updateaxisactionjob.cpp
index 3a1bfb465..0cbd325c9 100644
--- a/src/input/backend/updateaxisactionjob.cpp
+++ b/src/input/backend/updateaxisactionjob.cpp
@@ -101,65 +101,9 @@ void UpdateAxisActionJob::updateAction(LogicalDevice *device)
bool UpdateAxisActionJob::processActionInput(const Qt3DCore::QNodeId actionInputId)
{
-
- if (m_handler->actionInputManager()->lookupResource(actionInputId)) {
- ActionInput *actionInput = m_handler->actionInputManager()->lookupResource(actionInputId);
- QAbstractPhysicalDeviceBackendNode *physicalDeviceBackend = nullptr;
-
- const auto integrations = m_handler->inputDeviceIntegrations();
- for (QInputDeviceIntegration *integration : integrations) {
- if ((physicalDeviceBackend = integration->physicalDevice(actionInput->sourceDevice())) != nullptr)
- break;
- }
-
- if (physicalDeviceBackend != nullptr) {
- // Update the value
- return anyOfRequiredButtonsPressed(actionInput->buttons(), physicalDeviceBackend);
- }
- } else if (m_handler->inputSequenceManager()->lookupResource(actionInputId)) {
- InputSequence *inputSequence = m_handler->inputSequenceManager()->lookupResource(actionInputId);
- const qint64 startTime = inputSequence->startTime();
- if (startTime != 0) {
- // Check if we are still inside the time limit for the chord
- if ((m_currentTime - startTime) > inputSequence->timeout()) {
- inputSequence->reset();
- return false;
- }
- }
- bool actionTriggered = false;
- const auto actionInputIds = inputSequence->sequences();
- for (const Qt3DCore::QNodeId actionInputId : actionInputIds) {
- if (processActionInput(actionInputId)){
- actionTriggered |= inputSequence->actionTriggered(actionInputId, m_currentTime);
- // Set the start time if it wasn't set before
- if (startTime == 0)
- inputSequence->setStartTime(m_currentTime);
- }
- }
- return actionTriggered;
- } else if (m_handler->inputChordManager()->lookupResource(actionInputId)) {
- InputChord *inputChord = m_handler->inputChordManager()->lookupResource(actionInputId);
- const qint64 startTime = inputChord->startTime();
- if (startTime != 0) {
- // Check if we are still inside the time limit for the chord
- if ((m_currentTime - startTime) > inputChord->timeout()) {
- inputChord->reset();
- return false;
- }
- }
- bool actionTriggered = false;
- const auto actionInputIds = inputChord->chords();
- for (const Qt3DCore::QNodeId actionInputId : actionInputIds) {
- if (processActionInput(actionInputId)){
- actionTriggered |= inputChord->actionTriggered(actionInputId);
- if (startTime == 0)
- inputChord->setStartTime(m_currentTime);
- }
- }
- return actionTriggered;
- }
- //Should Never reach this point
- return false;
+ AbstractActionInput *actionInput = m_handler->lookupActionInput(actionInputId);
+ Q_ASSERT(actionInput);
+ return actionInput->process(m_handler, m_currentTime);
}
void UpdateAxisActionJob::updateAxis(LogicalDevice *device)
diff --git a/src/input/frontend/qinputaspect.cpp b/src/input/frontend/qinputaspect.cpp
index d544bed70..342998556 100644
--- a/src/input/frontend/qinputaspect.cpp
+++ b/src/input/frontend/qinputaspect.cpp
@@ -214,7 +214,6 @@ QStringList QInputAspect::availablePhysicalDevices() const
*/
QVector<QAspectJobPtr> QInputAspect::jobsToExecute(qint64 time)
{
- Q_UNUSED(time);
Q_D(QInputAspect);
QVector<QAspectJobPtr> jobs;
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 5a8195b64..f6d26fb22 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -174,6 +174,7 @@ void QRenderAspectPrivate::registerBackendTypes()
qRegisterMetaType<Qt3DRender::QBuffer*>();
qRegisterMetaType<Qt3DRender::QEffect*>();
+ qRegisterMetaType<Qt3DRender::QFrameGraphNode *>();
q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers));
q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer, m_nodeManagers->transformManager()));
diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp
index 2d0c3311c..69bd8528b 100644
--- a/src/render/io/qsceneloader.cpp
+++ b/src/render/io/qsceneloader.cpp
@@ -53,7 +53,7 @@ namespace Qt3DRender {
QSceneLoaderPrivate::QSceneLoaderPrivate()
: QComponentPrivate()
- , m_status(QSceneLoader::Loading)
+ , m_status(QSceneLoader::None)
, m_subTreeRoot(nullptr)
{
m_shareable = false;
@@ -178,9 +178,8 @@ void QSceneLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
subTreeRoot->setParent(parentEntity);
d->m_subTreeRoot = subTreeRoot;
}
-
- // Update status property
- setStatus(subTreeRoot ? QSceneLoader::Ready : QSceneLoader::Error);
+ } else if (e->propertyName() == QByteArrayLiteral("status")) {
+ setStatus(e->value().value<QSceneLoader::Status>());
}
}
}
@@ -230,7 +229,9 @@ void QSceneLoader::setStatus(QSceneLoader::Status status)
Q_D(QSceneLoader);
if (d->m_status != status) {
d->m_status = status;
+ const bool wasBlocked = blockNotifications(true);
emit statusChanged(status);
+ blockNotifications(wasBlocked);
}
}
diff --git a/src/render/io/qsceneloader_p.h b/src/render/io/qsceneloader_p.h
index 740e9dce8..b002957b2 100644
--- a/src/render/io/qsceneloader_p.h
+++ b/src/render/io/qsceneloader_p.h
@@ -53,6 +53,7 @@
#include <private/qcomponent_p.h>
#include <Qt3DRender/qsceneloader.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +61,7 @@ namespace Qt3DRender {
class QSceneIOHandler;
-class QSceneLoaderPrivate : public Qt3DCore::QComponentPrivate
+class QT3DRENDERSHARED_PRIVATE_EXPORT QSceneLoaderPrivate : public Qt3DCore::QComponentPrivate
{
public:
QSceneLoaderPrivate();
diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp
index bfb5e4571..cf1ca4736 100644
--- a/src/render/io/scene.cpp
+++ b/src/render/io/scene.cpp
@@ -65,6 +65,16 @@ void Scene::cleanup()
m_source.clear();
}
+void Scene::setStatus(QSceneLoader::Status status)
+{
+ // Send the new subtree to the frontend or notify failure
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("status");
+ e->setValue(QVariant::fromValue(status));
+ notifyObservers(e);
+}
+
void Scene::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
{
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSceneLoaderData>>(change);
diff --git a/src/render/io/scene_p.h b/src/render/io/scene_p.h
index fc3494489..42e3121c9 100644
--- a/src/render/io/scene_p.h
+++ b/src/render/io/scene_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DRender/private/backendnode_p.h>
+#include <Qt3DRender/qsceneloader.h>
#include <QtGlobal>
#include <QUrl>
@@ -77,6 +78,7 @@ public:
void setSceneManager(SceneManager *manager);
void cleanup();
+ void setStatus(QSceneLoader::Status status);
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
diff --git a/src/render/io/scenemanager.cpp b/src/render/io/scenemanager.cpp
index b46616689..d59391a87 100644
--- a/src/render/io/scenemanager.cpp
+++ b/src/render/io/scenemanager.cpp
@@ -61,14 +61,13 @@ void SceneManager::addSceneData(const QUrl &source, Qt3DCore::QNodeId sceneUuid)
if (!m_pendingJobs.isEmpty())
newJob->addDependency(m_pendingJobs.last());
- m_pendingJobs.append(newJob);
+ m_pendingJobs.push_back(newJob);
}
QVector<LoadSceneJobPtr> SceneManager::pendingSceneLoaderJobs()
{
- QVector<LoadSceneJobPtr> copy = m_pendingJobs;
- m_pendingJobs.clear();
- return copy;
+ // Explicitly use std::move to clear the m_pendingJobs vector
+ return std::move(m_pendingJobs);
}
} // namespace Render
diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp
index 758e0b135..3111e1ba3 100644
--- a/src/render/jobs/loadscenejob.cpp
+++ b/src/render/jobs/loadscenejob.cpp
@@ -44,6 +44,7 @@
#include <Qt3DCore/qentity.h>
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/qsceneiohandler_p.h>
+#include <Qt3DRender/qsceneloader.h>
QT_BEGIN_NAMESPACE
@@ -64,29 +65,41 @@ void LoadSceneJob::run()
// Iterate scene IO handlers until we find one that can handle this file type
Qt3DCore::QEntity *sceneSubTree = nullptr;
+ Scene *scene = m_managers->sceneManager()->lookupResource(m_sceneComponent);
+ Q_ASSERT(scene);
+
+ // Reset status
+ scene->setStatus(QSceneLoader::None);
+
// Perform the loading only if the source wasn't explicitly set to empty
if (!m_source.isEmpty()) {
for (QSceneIOHandler *sceneIOHandler : qAsConst(m_sceneIOHandlers)) {
if (!sceneIOHandler->isFileTypeSupported(m_source))
continue;
+ // If the file type is supported -> enter Loading status
+ scene->setStatus(QSceneLoader::Loading);
+
// File type is supported, try to load it
sceneIOHandler->setSource(m_source);
Qt3DCore::QEntity *sub = sceneIOHandler->scene();
if (sub) {
sceneSubTree = sub;
+ // Successfully built a subtree
+ scene->setStatus(QSceneLoader::Ready);
break;
+ } else {
+ // Tree wasn't build so something went wrong obviously
+ scene->setStatus(QSceneLoader::Error);
}
}
}
- // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree
- // to the QCoreApplication thread which is where the frontend object tree lives.
- Scene *scene = m_managers->sceneManager()->lookupResource(m_sceneComponent);
// If the sceneSubTree is null it will trigger the frontend to unload
// any subtree it may hold
- if (scene)
- scene->setSceneSubtree(sceneSubTree);
+ // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree
+ // to the QCoreApplication thread which is where the frontend object tree lives.
+ scene->setSceneSubtree(sceneSubTree);
}
} // namespace Render
diff --git a/src/render/jobs/loadtexturedatajob.cpp b/src/render/jobs/loadtexturedatajob.cpp
index e68717062..b8663e4a7 100644
--- a/src/render/jobs/loadtexturedatajob.cpp
+++ b/src/render/jobs/loadtexturedatajob.cpp
@@ -204,7 +204,8 @@ void LoadTextureDataJob::run()
// Set the textureDataHandle on the texture image
// Note: this internally updates the DNA of the TextureImage
texImg->setTextureDataHandle(textureDataHandle);
- texImg->updateDNA(::qHash(QTextureImageDataPrivate::get(data)->m_data));
+ if (data)
+ texImg->updateDNA(::qHash(QTextureImageDataPrivate::get(data)->m_data));
}
}
// Tell the renderer to reload/upload to GPU the TextureImage for the Texture
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 7d19ad26d..e5745a99e 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -5,6 +5,7 @@ SUBDIRS = \
render \
quick3d \
cmake \
- input
+ input \
+ extras
installed_cmake.depends = cmake
diff --git a/tests/auto/extras/extras.pro b/tests/auto/extras/extras.pro
new file mode 100644
index 000000000..3bba4d37b
--- /dev/null
+++ b/tests/auto/extras/extras.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ qcuboidgeometry
diff --git a/tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro b/tests/auto/extras/qcuboidgeometry/qcuboidgeometry.pro
index 2599b5fe6..7208f1c7b 100644
--- a/tests/auto/render/qcuboidgeometry/qcuboidgeometry.pro
+++ b/tests/auto/extras/qcuboidgeometry/qcuboidgeometry.pro
@@ -8,6 +8,3 @@ CONFIG += testcase
SOURCES += \
tst_qcuboidgeometry.cpp
-
-include(../../core/common/common.pri)
-include(../commons/commons.pri)
diff --git a/tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp b/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp
index ddd9eed22..ddd9eed22 100644
--- a/tests/auto/render/qcuboidgeometry/tst_qcuboidgeometry.cpp
+++ b/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp
diff --git a/tests/auto/input/abstractaxisinput/abstractaxisinput.pro b/tests/auto/input/abstractaxisinput/abstractaxisinput.pro
index 3f9c521de..574b9af9e 100644
--- a/tests/auto/input/abstractaxisinput/abstractaxisinput.pro
+++ b/tests/auto/input/abstractaxisinput/abstractaxisinput.pro
@@ -8,5 +8,4 @@ CONFIG += testcase
SOURCES += tst_abstractaxisinput.cpp
-include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/input/actioninput/actioninput.pro b/tests/auto/input/actioninput/actioninput.pro
new file mode 100644
index 000000000..1091f2b76
--- /dev/null
+++ b/tests/auto/input/actioninput/actioninput.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_actioninput
+
+QT += core-private 3dcore 3dcore-private 3dinput 3dinput-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_actioninput.cpp
+
+include(../commons/commons.pri)
diff --git a/tests/auto/input/actioninput/tst_actioninput.cpp b/tests/auto/input/actioninput/tst_actioninput.cpp
new file mode 100644
index 000000000..2db4cf760
--- /dev/null
+++ b/tests/auto/input/actioninput/tst_actioninput.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 <qbackendnodetester.h>
+#include "testdevice.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DInput/private/actioninput_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/QActionInput>
+
+class tst_ActionInput : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void shouldMirrorPeerProperties()
+ {
+ // GIVEN
+ Qt3DInput::Input::ActionInput backendActionInput;
+ Qt3DInput::QActionInput actionInput;
+ TestDevice sourceDevice;
+
+ actionInput.setButtons(QVector<int>() << (1 << 8));
+ actionInput.setSourceDevice(&sourceDevice);
+
+ // WHEN
+ simulateInitialization(&actionInput, &backendActionInput);
+
+ // THEN
+ QCOMPARE(backendActionInput.peerId(), actionInput.id());
+ QCOMPARE(backendActionInput.isEnabled(), actionInput.isEnabled());
+ QCOMPARE(backendActionInput.buttons(), actionInput.buttons());
+ QCOMPARE(backendActionInput.sourceDevice(), sourceDevice.id());
+ }
+
+ void shouldHaveInitialAndCleanedUpStates()
+ {
+ // GIVEN
+ Qt3DInput::Input::ActionInput backendActionInput;
+
+ // THEN
+ QVERIFY(backendActionInput.peerId().isNull());
+ QVERIFY(backendActionInput.buttons().isEmpty());
+ QCOMPARE(backendActionInput.isEnabled(), false);
+ QCOMPARE(backendActionInput.sourceDevice(), Qt3DCore::QNodeId());
+
+ // GIVEN
+ Qt3DInput::QActionInput actionInput;
+ TestDevice sourceDevice;
+
+ actionInput.setButtons(QVector<int>() << (1 << 8));
+ actionInput.setSourceDevice(&sourceDevice);
+
+ // WHEN
+ simulateInitialization(&actionInput, &backendActionInput);
+ backendActionInput.cleanup();
+
+ // THEN
+ QVERIFY(backendActionInput.buttons().isEmpty());
+ QCOMPARE(backendActionInput.isEnabled(), false);
+ QCOMPARE(backendActionInput.sourceDevice(), Qt3DCore::QNodeId());
+ }
+
+ void shouldHandlePropertyChanges()
+ {
+ // GIVEN
+ Qt3DInput::Input::ActionInput backendActionInput;
+
+ // WHEN
+ Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setValue(QVariant::fromValue(QVector<int>() << 64));
+ updateChange->setPropertyName("buttons");
+ backendActionInput.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendActionInput.buttons(), QVector<int>() << 64);
+
+ // WHEN
+ updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setPropertyName("enabled");
+ updateChange->setValue(true);
+ backendActionInput.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendActionInput.isEnabled(), true);
+
+ // WHEN
+ TestDevice device;
+ updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setPropertyName("sourceDevice");
+ updateChange->setValue(QVariant::fromValue(device.id()));
+ backendActionInput.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendActionInput.sourceDevice(), device.id());
+ }
+
+ void shouldDealWithKeyPresses()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ Qt3DInput::Input::ActionInput backendActionInput;
+ Qt3DInput::QActionInput actionInput;
+ actionInput.setButtons(QVector<int>() << Qt::Key_Space << Qt::Key_Return);
+ actionInput.setSourceDevice(device);
+ simulateInitialization(&actionInput, &backendActionInput);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, true);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Space, true);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Return, true);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Space, false);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, false);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Return, false);
+
+ // THEN
+ QCOMPARE(backendActionInput.process(&handler, 1000000000), false);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_ActionInput)
+
+#include "tst_actioninput.moc"
diff --git a/tests/auto/input/analogaxisinput/analogaxisinput.pro b/tests/auto/input/analogaxisinput/analogaxisinput.pro
index 7bd0a9865..16d237bf9 100644
--- a/tests/auto/input/analogaxisinput/analogaxisinput.pro
+++ b/tests/auto/input/analogaxisinput/analogaxisinput.pro
@@ -8,5 +8,4 @@ CONFIG += testcase
SOURCES += tst_analogaxisinput.cpp
-include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/input/buttonaxisinput/buttonaxisinput.pro b/tests/auto/input/buttonaxisinput/buttonaxisinput.pro
index f012ca1d3..1aa492aa4 100644
--- a/tests/auto/input/buttonaxisinput/buttonaxisinput.pro
+++ b/tests/auto/input/buttonaxisinput/buttonaxisinput.pro
@@ -8,5 +8,4 @@ CONFIG += testcase
SOURCES += tst_buttonaxisinput.cpp
-include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/input/commons/commons.pri b/tests/auto/input/commons/commons.pri
index cc65e8a41..ccc14075b 100644
--- a/tests/auto/input/commons/commons.pri
+++ b/tests/auto/input/commons/commons.pri
@@ -1,3 +1,6 @@
HEADERS += $$PWD/testdevice.h
INCLUDEPATH += $$PWD
+
+include(../../core/common/common.pri)
+
diff --git a/tests/auto/input/commons/testdevice.h b/tests/auto/input/commons/testdevice.h
index c58835a38..c6fc4995b 100644
--- a/tests/auto/input/commons/testdevice.h
+++ b/tests/auto/input/commons/testdevice.h
@@ -28,6 +28,9 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DInput/QAbstractPhysicalDevice>
+#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
+#include <Qt3DInput/private/qinputdeviceintegration_p.h>
+#include <qbackendnodetester.h>
class TestDevice : public Qt3DInput::QAbstractPhysicalDevice
{
@@ -43,4 +46,108 @@ public:
QStringList buttonNames() const Q_DECL_FINAL { return QStringList(); }
int axisIdentifier(const QString &name) const Q_DECL_FINAL { Q_UNUSED(name) return 0; }
int buttonIdentifier(const QString &name) const Q_DECL_FINAL { Q_UNUSED(name) return 0; }
+
+private:
+ friend class TestDeviceBackendNode;
+};
+
+class TestDeviceBackendNode : public Qt3DInput::QAbstractPhysicalDeviceBackendNode
+{
+public:
+ explicit TestDeviceBackendNode(TestDevice *device)
+ : Qt3DInput::QAbstractPhysicalDeviceBackendNode(ReadOnly)
+ {
+ Qt3DCore::QBackendNodeTester().simulateInitialization(device, this);
+ }
+
+ float axisValue(int axisIdentifier) const Q_DECL_FINAL
+ {
+ return m_axisValues.value(axisIdentifier);
+ }
+
+ void setAxisValue(int axisIdentifier, float value)
+ {
+ m_axisValues.insert(axisIdentifier, value);
+ }
+
+ bool isButtonPressed(int buttonIdentifier) const Q_DECL_FINAL
+ {
+ return m_buttonStates.value(buttonIdentifier);
+ }
+
+ void setButtonPressed(int buttonIdentifier, bool pressed)
+ {
+ m_buttonStates.insert(buttonIdentifier, pressed);
+ }
+
+private:
+ QHash<int, float> m_axisValues;
+ QHash<int, bool> m_buttonStates;
+};
+
+class TestDeviceIntegration : public Qt3DInput::QInputDeviceIntegration
+{
+ Q_OBJECT
+public:
+ explicit TestDeviceIntegration(QObject *parent = nullptr)
+ : Qt3DInput::QInputDeviceIntegration(parent),
+ m_devicesParent(new Qt3DCore::QNode)
+ {
+ }
+
+ ~TestDeviceIntegration()
+ {
+ qDeleteAll(m_deviceBackendNodes);
+ }
+
+ QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time) Q_DECL_FINAL
+ {
+ Q_UNUSED(time);
+ return QVector<Qt3DCore::QAspectJobPtr>();
+ }
+
+ TestDevice *createPhysicalDevice(const QString &name) Q_DECL_FINAL
+ {
+ Q_ASSERT(!deviceNames().contains(name));
+ auto device = new TestDevice(m_devicesParent.data()); // Avoids unwanted reparenting
+ device->setObjectName(name);
+ m_devices.append(device);
+ m_deviceBackendNodes.append(new TestDeviceBackendNode(device));
+ return device;
+ }
+
+ QVector<Qt3DCore::QNodeId> physicalDevices() const Q_DECL_FINAL
+ {
+ QVector<Qt3DCore::QNodeId> ids;
+ std::transform(m_devices.constBegin(), m_devices.constEnd(),
+ std::back_inserter(ids),
+ [] (TestDevice *device) { return device->id(); });
+ return ids;
+ }
+
+ TestDeviceBackendNode *physicalDevice(Qt3DCore::QNodeId id) const Q_DECL_FINAL
+ {
+ auto it = std::find_if(m_deviceBackendNodes.constBegin(), m_deviceBackendNodes.constEnd(),
+ [id] (TestDeviceBackendNode *node) { return node->peerId() == id; });
+ if (it == m_deviceBackendNodes.constEnd())
+ return nullptr;
+ else
+ return *it;
+ }
+
+ QStringList deviceNames() const Q_DECL_FINAL
+ {
+ QStringList names;
+ std::transform(m_devices.constBegin(), m_devices.constEnd(),
+ std::back_inserter(names),
+ [] (TestDevice *device) { return device->objectName(); });
+ return names;
+ }
+
+private:
+ void onInitialize() Q_DECL_FINAL {}
+
+ QScopedPointer<Qt3DCore::QNode> m_devicesParent;
+ QVector<TestDevice*> m_devices;
+ QVector<TestDeviceBackendNode*> m_deviceBackendNodes;
};
diff --git a/tests/auto/input/input.pro b/tests/auto/input/input.pro
index fa447730d..05668c036 100644
--- a/tests/auto/input/input.pro
+++ b/tests/auto/input/input.pro
@@ -13,8 +13,11 @@ qtConfig(private_tests) {
axis \
action \
abstractaxisinput \
+ actioninput \
analogaxisinput \
buttonaxisinput \
keyboardhandler \
- qaxisaccumulator
+ qaxisaccumulator \
+ inputsequence \
+ inputchord
}
diff --git a/tests/auto/input/inputchord/inputchord.pro b/tests/auto/input/inputchord/inputchord.pro
new file mode 100644
index 000000000..09bbbb3ec
--- /dev/null
+++ b/tests/auto/input/inputchord/inputchord.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_inputchord
+
+QT += core-private 3dcore 3dcore-private 3dinput 3dinput-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_inputchord.cpp
+
+include(../commons/commons.pri)
diff --git a/tests/auto/input/inputchord/tst_inputchord.cpp b/tests/auto/input/inputchord/tst_inputchord.cpp
new file mode 100644
index 000000000..a840d7dee
--- /dev/null
+++ b/tests/auto/input/inputchord/tst_inputchord.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 <qbackendnodetester.h>
+#include "testdevice.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DCore/QPropertyNodeAddedChange>
+#include <Qt3DCore/QPropertyNodeRemovedChange>
+#include <Qt3DInput/private/actioninput_p.h>
+#include <Qt3DInput/private/inputchord_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/QActionInput>
+#include <Qt3DInput/QInputChord>
+
+class tst_InputChord : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void shouldMirrorPeerProperties()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputChord backendInputChord;
+ Qt3DInput::QInputChord inputChord;
+ Qt3DInput::QActionInput actionInput;
+
+ inputChord.setTimeout(250);
+ inputChord.addChord(&actionInput);
+
+ // WHEN
+ simulateInitialization(&inputChord, &backendInputChord);
+
+ // THEN
+ QCOMPARE(backendInputChord.peerId(), inputChord.id());
+ QCOMPARE(backendInputChord.isEnabled(), inputChord.isEnabled());
+ QCOMPARE(backendInputChord.timeout(), inputChord.timeout() * 1000000);
+ QCOMPARE(backendInputChord.chords().size(), inputChord.chords().size());
+
+ const int inputsCount = backendInputChord.chords().size();
+ if (inputsCount > 0) {
+ for (int i = 0; i < inputsCount; ++i)
+ QCOMPARE(backendInputChord.chords().at(i), inputChord.chords().at(i)->id());
+ }
+ }
+
+ void shouldHaveInitialAndCleanedUpStates()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputChord backendInputChord;
+
+ // THEN
+ QVERIFY(backendInputChord.peerId().isNull());
+ QCOMPARE(backendInputChord.isEnabled(), false);
+ QCOMPARE(backendInputChord.timeout(), 0);
+ QCOMPARE(backendInputChord.chords().size(), 0);
+
+ // GIVEN
+ Qt3DInput::QInputChord inputChord;
+ Qt3DInput::QActionInput actionInput;
+
+ inputChord.setTimeout(250);
+ inputChord.addChord(&actionInput);
+
+ // WHEN
+ simulateInitialization(&inputChord, &backendInputChord);
+ backendInputChord.cleanup();
+
+ // THEN
+ QCOMPARE(backendInputChord.isEnabled(), false);
+ QCOMPARE(backendInputChord.timeout(), 0);
+ QCOMPARE(backendInputChord.chords().size(), 0);
+ }
+
+ void shouldHandlePropertyChanges()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputChord backendInputChord;
+
+ // WHEN
+ Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setValue(250);
+ updateChange->setPropertyName("timeout");
+ backendInputChord.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendInputChord.timeout(), 250000000);
+
+ // WHEN
+ updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setPropertyName("enabled");
+ updateChange->setValue(true);
+ backendInputChord.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendInputChord.isEnabled(), true);
+
+ // WHEN
+ Qt3DInput::QActionInput input;
+ const Qt3DCore::QNodeId inputId = input.id();
+ const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
+ nodeAddedChange->setPropertyName("chord");
+ backendInputChord.sceneChangeEvent(nodeAddedChange);
+
+ // THEN
+ QCOMPARE(backendInputChord.chords().size(), 1);
+ QCOMPARE(backendInputChord.chords().first(), inputId);
+
+ // WHEN
+ const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
+ nodeRemovedChange->setPropertyName("chord");
+ backendInputChord.sceneChangeEvent(nodeRemovedChange);
+
+ // THEN
+ QCOMPARE(backendInputChord.chords().size(), 0);
+ }
+
+ void shouldActivateWhenAllArePressed()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ auto firstInput = new Qt3DInput::QActionInput;
+ firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_W);
+ firstInput->setSourceDevice(device);
+ auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
+ simulateInitialization(firstInput, backendFirstInput);
+
+ auto secondInput = new Qt3DInput::QActionInput;
+ secondInput->setButtons(QVector<int>() << Qt::Key_A << Qt::Key_S);
+ secondInput->setSourceDevice(device);
+ auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
+ simulateInitialization(secondInput, backendSecondInput);
+
+ Qt3DInput::Input::InputChord backendInputChord;
+ Qt3DInput::QInputChord inputChord;
+ inputChord.setTimeout(300);
+ inputChord.addChord(firstInput);
+ inputChord.addChord(secondInput);
+ simulateInitialization(&inputChord, &backendInputChord);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1000000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, false);
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1100000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_A, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1200000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1300000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_W, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1400000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_W, false);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1500000000), true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1600000000), true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1700000000), true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1800000000), true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1900000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 2000000000), false);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 2100000000), false);
+ }
+
+ void shouldRespectChordTimeout()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ auto firstInput = new Qt3DInput::QActionInput;
+ firstInput->setButtons(QVector<int>() << Qt::Key_Q);
+ firstInput->setSourceDevice(device);
+ auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
+ simulateInitialization(firstInput, backendFirstInput);
+
+ auto secondInput = new Qt3DInput::QActionInput;
+ secondInput->setButtons(QVector<int>() << Qt::Key_W);
+ secondInput->setSourceDevice(device);
+ auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
+ simulateInitialization(secondInput, backendSecondInput);
+
+ Qt3DInput::Input::InputChord backendInputChord;
+ Qt3DInput::QInputChord inputChord;
+ inputChord.setTimeout(300);
+ inputChord.addChord(firstInput);
+ inputChord.addChord(secondInput);
+ simulateInitialization(&inputChord, &backendInputChord);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1000000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_W, true);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1400000000), false); // Too late
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1600000000), false);
+
+ // THEN
+ QCOMPARE(backendInputChord.process(&handler, 1800000000), false);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_InputChord)
+
+#include "tst_inputchord.moc"
diff --git a/tests/auto/input/inputsequence/inputsequence.pro b/tests/auto/input/inputsequence/inputsequence.pro
new file mode 100644
index 000000000..1fdb21f5b
--- /dev/null
+++ b/tests/auto/input/inputsequence/inputsequence.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_inputsequence
+
+QT += core-private 3dcore 3dcore-private 3dinput 3dinput-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_inputsequence.cpp
+
+include(../commons/commons.pri)
diff --git a/tests/auto/input/inputsequence/tst_inputsequence.cpp b/tests/auto/input/inputsequence/tst_inputsequence.cpp
new file mode 100644
index 000000000..6b4a39b68
--- /dev/null
+++ b/tests/auto/input/inputsequence/tst_inputsequence.cpp
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 <qbackendnodetester.h>
+#include "testdevice.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DCore/QPropertyNodeAddedChange>
+#include <Qt3DCore/QPropertyNodeRemovedChange>
+#include <Qt3DInput/private/actioninput_p.h>
+#include <Qt3DInput/private/inputhandler_p.h>
+#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/inputsequence_p.h>
+#include <Qt3DInput/QActionInput>
+#include <Qt3DInput/QInputSequence>
+
+class tst_InputSequence : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void shouldMirrorPeerProperties()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputSequence backendInputSequence;
+ Qt3DInput::QInputSequence inputSequence;
+ Qt3DInput::QActionInput actionInput;
+
+ inputSequence.setTimeout(250);
+ inputSequence.setButtonInterval(100);
+ inputSequence.addSequence(&actionInput);
+
+ // WHEN
+ simulateInitialization(&inputSequence, &backendInputSequence);
+
+ // THEN
+ QCOMPARE(backendInputSequence.peerId(), inputSequence.id());
+ QCOMPARE(backendInputSequence.isEnabled(), inputSequence.isEnabled());
+ QCOMPARE(backendInputSequence.timeout(), inputSequence.timeout() * 1000000);
+ QCOMPARE(backendInputSequence.buttonInterval(), inputSequence.buttonInterval() * 1000000);
+ QCOMPARE(backendInputSequence.sequences().size(), inputSequence.sequences().size());
+
+ const int inputsCount = backendInputSequence.sequences().size();
+ if (inputsCount > 0) {
+ for (int i = 0; i < inputsCount; ++i)
+ QCOMPARE(backendInputSequence.sequences().at(i), inputSequence.sequences().at(i)->id());
+ }
+ }
+
+ void shouldHaveInitialAndCleanedUpStates()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputSequence backendInputSequence;
+
+ // THEN
+ QVERIFY(backendInputSequence.peerId().isNull());
+ QCOMPARE(backendInputSequence.isEnabled(), false);
+ QCOMPARE(backendInputSequence.timeout(), 0);
+ QCOMPARE(backendInputSequence.buttonInterval(), 0);
+ QCOMPARE(backendInputSequence.sequences().size(), 0);
+
+ // GIVEN
+ Qt3DInput::QInputSequence inputSequence;
+ Qt3DInput::QActionInput actionInput;
+
+ inputSequence.setTimeout(250);
+ inputSequence.setButtonInterval(100);
+ inputSequence.addSequence(&actionInput);
+
+ // WHEN
+ simulateInitialization(&inputSequence, &backendInputSequence);
+ backendInputSequence.cleanup();
+
+ // THEN
+ QCOMPARE(backendInputSequence.isEnabled(), false);
+ QCOMPARE(backendInputSequence.timeout(), 0);
+ QCOMPARE(backendInputSequence.buttonInterval(), 0);
+ QCOMPARE(backendInputSequence.sequences().size(), 0);
+ }
+
+ void shouldHandlePropertyChanges()
+ {
+ // GIVEN
+ Qt3DInput::Input::InputSequence backendInputSequence;
+
+ // WHEN
+ Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setValue(250);
+ updateChange->setPropertyName("timeout");
+ backendInputSequence.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendInputSequence.timeout(), 250000000);
+
+ // WHEN
+ updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setValue(150);
+ updateChange->setPropertyName("buttonInterval");
+ backendInputSequence.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendInputSequence.buttonInterval(), 150000000);
+
+ // WHEN
+ updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ updateChange->setPropertyName("enabled");
+ updateChange->setValue(true);
+ backendInputSequence.sceneChangeEvent(updateChange);
+
+ // THEN
+ QCOMPARE(backendInputSequence.isEnabled(), true);
+
+ // WHEN
+ Qt3DInput::QActionInput input;
+ const Qt3DCore::QNodeId inputId = input.id();
+ const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
+ nodeAddedChange->setPropertyName("sequence");
+ backendInputSequence.sceneChangeEvent(nodeAddedChange);
+
+ // THEN
+ QCOMPARE(backendInputSequence.sequences().size(), 1);
+ QCOMPARE(backendInputSequence.sequences().first(), inputId);
+
+ // WHEN
+ const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
+ nodeRemovedChange->setPropertyName("sequence");
+ backendInputSequence.sceneChangeEvent(nodeRemovedChange);
+
+ // THEN
+ QCOMPARE(backendInputSequence.sequences().size(), 0);
+ }
+
+ void shouldActivateWhenSequenceIsConsumedInOrderOnly()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ auto firstInput = new Qt3DInput::QActionInput;
+ firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
+ firstInput->setSourceDevice(device);
+ auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
+ simulateInitialization(firstInput, backendFirstInput);
+
+ auto secondInput = new Qt3DInput::QActionInput;
+ secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
+ secondInput->setSourceDevice(device);
+ auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
+ simulateInitialization(secondInput, backendSecondInput);
+
+ auto thirdInput = new Qt3DInput::QActionInput;
+ thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
+ thirdInput->setSourceDevice(device);
+ auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
+ simulateInitialization(thirdInput, backendThirdInput);
+
+ Qt3DInput::Input::InputSequence backendInputSequence;
+ Qt3DInput::QInputSequence inputSequence;
+ inputSequence.setButtonInterval(150);
+ inputSequence.setTimeout(450);
+ inputSequence.addSequence(firstInput);
+ inputSequence.addSequence(secondInput);
+ inputSequence.addSequence(thirdInput);
+ simulateInitialization(&inputSequence, &backendInputSequence);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1000000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Up, false);
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1100000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1200000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, false);
+ deviceBackend->setButtonPressed(Qt::Key_E, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1300000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_E, false);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1400000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1500000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1600000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, false);
+ deviceBackend->setButtonPressed(Qt::Key_E, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1700000000), true);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_E, false);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1800000000), false);
+
+
+ // Now out of order
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1900000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, false);
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 2000000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+ deviceBackend->setButtonPressed(Qt::Key_D, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 2100000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_D, false);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 22000000000), false);
+ }
+
+ void shouldRespectSequenceTimeout()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ auto firstInput = new Qt3DInput::QActionInput;
+ firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
+ firstInput->setSourceDevice(device);
+ auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
+ simulateInitialization(firstInput, backendFirstInput);
+
+ auto secondInput = new Qt3DInput::QActionInput;
+ secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
+ secondInput->setSourceDevice(device);
+ auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
+ simulateInitialization(secondInput, backendSecondInput);
+
+ auto thirdInput = new Qt3DInput::QActionInput;
+ thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
+ thirdInput->setSourceDevice(device);
+ auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
+ simulateInitialization(thirdInput, backendThirdInput);
+
+ Qt3DInput::Input::InputSequence backendInputSequence;
+ Qt3DInput::QInputSequence inputSequence;
+ inputSequence.setButtonInterval(250);
+ inputSequence.setTimeout(450);
+ inputSequence.addSequence(firstInput);
+ inputSequence.addSequence(secondInput);
+ inputSequence.addSequence(thirdInput);
+ simulateInitialization(&inputSequence, &backendInputSequence);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1100000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1300000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, false);
+ deviceBackend->setButtonPressed(Qt::Key_E, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1600000000), false); // Too late
+ }
+
+ void shouldRespectSequenceButtonInterval()
+ {
+ // GIVEN
+ TestDeviceIntegration deviceIntegration;
+ TestDevice *device = deviceIntegration.createPhysicalDevice("keyboard");
+ TestDeviceBackendNode *deviceBackend = deviceIntegration.physicalDevice(device->id());
+ Qt3DInput::Input::InputHandler handler;
+ handler.addInputDeviceIntegration(&deviceIntegration);
+
+ auto firstInput = new Qt3DInput::QActionInput;
+ firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
+ firstInput->setSourceDevice(device);
+ auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
+ simulateInitialization(firstInput, backendFirstInput);
+
+ auto secondInput = new Qt3DInput::QActionInput;
+ secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
+ secondInput->setSourceDevice(device);
+ auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
+ simulateInitialization(secondInput, backendSecondInput);
+
+ auto thirdInput = new Qt3DInput::QActionInput;
+ thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
+ thirdInput->setSourceDevice(device);
+ auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
+ simulateInitialization(thirdInput, backendThirdInput);
+
+ Qt3DInput::Input::InputSequence backendInputSequence;
+ Qt3DInput::QInputSequence inputSequence;
+ inputSequence.setButtonInterval(100);
+ inputSequence.setTimeout(450);
+ inputSequence.addSequence(firstInput);
+ inputSequence.addSequence(secondInput);
+ inputSequence.addSequence(thirdInput);
+ simulateInitialization(&inputSequence, &backendInputSequence);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1100000000), false);
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_Q, false);
+ deviceBackend->setButtonPressed(Qt::Key_S, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1250000000), false); // Too late
+
+ // WHEN
+ deviceBackend->setButtonPressed(Qt::Key_S, false);
+ deviceBackend->setButtonPressed(Qt::Key_E, true);
+
+ // THEN
+ QCOMPARE(backendInputSequence.process(&handler, 1300000000), false);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_InputSequence)
+
+#include "tst_inputsequence.moc"
diff --git a/tests/auto/input/keyboardhandler/keyboardhandler.pro b/tests/auto/input/keyboardhandler/keyboardhandler.pro
index f3f7b6c63..2e28c5045 100644
--- a/tests/auto/input/keyboardhandler/keyboardhandler.pro
+++ b/tests/auto/input/keyboardhandler/keyboardhandler.pro
@@ -8,5 +8,4 @@ CONFIG += testcase
SOURCES += tst_keyboardhandler.cpp
-include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/render/qcameralens/qcameralens.pro b/tests/auto/render/qcameralens/qcameralens.pro
new file mode 100644
index 000000000..0f517d5ef
--- /dev/null
+++ b/tests/auto/render/qcameralens/qcameralens.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qcameralens
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qcameralens.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/qcameralens/tst_qcameralens.cpp b/tests/auto/render/qcameralens/tst_qcameralens.cpp
new file mode 100644
index 000000000..aab43d553
--- /dev/null
+++ b/tests/auto/render/qcameralens/tst_qcameralens.cpp
@@ -0,0 +1,717 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
+** 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 <Qt3DRender/qcameralens.h>
+#include <Qt3DRender/private/qcameralens_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include "testpostmanarbiter.h"
+
+class tst_QCameraLens : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<Qt3DRender::QCameraLens::ProjectionType>("QCameraLens::ProjectionType");
+ }
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ // THEN
+ QCOMPARE(cameraLens.projectionType(), Qt3DRender::QCameraLens::PerspectiveProjection);
+ QCOMPARE(cameraLens.nearPlane(), 0.1f);
+ QCOMPARE(cameraLens.farPlane(), 1024.0f);
+ QCOMPARE(cameraLens.fieldOfView(), 25.0f);
+ QCOMPARE(cameraLens.aspectRatio(), 1.0f);
+ QCOMPARE(cameraLens.left(), -0.5f);
+ QCOMPARE(cameraLens.right(), 0.5f);
+ QCOMPARE(cameraLens.bottom(), -0.5f);
+ QCOMPARE(cameraLens.top(), 0.5f);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)));
+ const Qt3DRender::QCameraLens::ProjectionType newValue = Qt3DRender::QCameraLens::OrthographicProjection;
+ cameraLens.setProjectionType(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.projectionType(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setProjectionType(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.projectionType(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(nearPlaneChanged(float)));
+ const float newValue = 10.0f;
+ cameraLens.setNearPlane(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.nearPlane(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setNearPlane(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.nearPlane(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(farPlaneChanged(float)));
+ const float newValue = 1.0f;
+ cameraLens.setFarPlane(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.farPlane(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setFarPlane(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.farPlane(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(fieldOfViewChanged(float)));
+ const float newValue = 5.0f;
+ cameraLens.setFieldOfView(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.fieldOfView(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setFieldOfView(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.fieldOfView(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(aspectRatioChanged(float)));
+ const float newValue = 4.0f / 3.0f;
+ cameraLens.setAspectRatio(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.aspectRatio(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setAspectRatio(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.aspectRatio(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(leftChanged(float)));
+ const float newValue = 0.0f;
+ cameraLens.setLeft(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.left(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setLeft(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.left(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(rightChanged(float)));
+ const float newValue = 1.0f;
+ cameraLens.setRight(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.right(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setRight(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.right(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(bottomChanged(float)));
+ const float newValue = 2.0f;
+ cameraLens.setBottom(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.bottom(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setBottom(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.bottom(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(topChanged(float)));
+ const float newValue = -2.0f;
+ cameraLens.setTop(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.top(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setTop(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.top(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(projectionMatrixChanged(QMatrix4x4)));
+ QMatrix4x4 newValue;
+ newValue.translate(5.0f, 2.0f, 4.3f);
+ cameraLens.setProjectionMatrix(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(cameraLens.projectionMatrix(), newValue);
+ QCOMPARE(cameraLens.projectionType(), Qt3DRender::QCameraLens::CustomProjection);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ cameraLens.setProjectionMatrix(newValue);
+
+ // THEN
+ QCOMPARE(cameraLens.projectionMatrix(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ }
+
+ void checkSetOrthographicProjection()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(projectionMatrixChanged(QMatrix4x4)));
+ cameraLens.setOrthographicProjection(-1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 50.0f);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 8); // Triggered for each property being set + 1
+ QCOMPARE(cameraLens.projectionType(), Qt3DRender::QCameraLens::OrthographicProjection);
+ QCOMPARE(cameraLens.nearPlane(), 0.5f);
+ QCOMPARE(cameraLens.farPlane(), 50.0f);
+ QCOMPARE(cameraLens.left(), -1.0f);
+ QCOMPARE(cameraLens.right(), 1.0f);
+ QCOMPARE(cameraLens.bottom(), -1.0f);
+ QCOMPARE(cameraLens.top(), 1.0f);
+ }
+ }
+
+ void checkSetPerspectiveProjection()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(projectionMatrixChanged(QMatrix4x4)));
+ cameraLens.setPerspectiveProjection(20.0f, 16.0f / 9.0f, 0.5f, 50.0f);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 5); // Triggered for each property being set (- projectionTye which is the default value) + 1
+ QCOMPARE(cameraLens.projectionType(), Qt3DRender::QCameraLens::PerspectiveProjection);
+ QCOMPARE(cameraLens.nearPlane(), 0.5f);
+ QCOMPARE(cameraLens.farPlane(), 50.0f);
+ QCOMPARE(cameraLens.fieldOfView(), 20.0f);
+ QCOMPARE(cameraLens.aspectRatio(), 16.0f / 9.0f);
+ }
+ }
+
+ void checkSetFrustumProjection()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ {
+ // WHEN
+ QSignalSpy spy(&cameraLens, SIGNAL(projectionMatrixChanged(QMatrix4x4)));
+ cameraLens.setFrustumProjection(-1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 50.0f);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 8); // Triggered for each property being set + 1
+ QCOMPARE(cameraLens.projectionType(), Qt3DRender::QCameraLens::FrustumProjection);
+ QCOMPARE(cameraLens.nearPlane(), 0.5f);
+ QCOMPARE(cameraLens.farPlane(), 50.0f);
+ QCOMPARE(cameraLens.left(), -1.0f);
+ QCOMPARE(cameraLens.right(), 1.0f);
+ QCOMPARE(cameraLens.bottom(), -1.0f);
+ QCOMPARE(cameraLens.top(), 1.0f);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DRender::QCameraLens cameraLens;
+
+ cameraLens.setNearPlane(0.5);
+ cameraLens.setFarPlane(1005.0f);
+ cameraLens.setFieldOfView(35.0f);
+ cameraLens.setAspectRatio(16.0f/9.0f);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&cameraLens);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QCameraLensData>>(creationChanges.first());
+ const Qt3DRender::QCameraLensData cloneData = creationChangeData->data;
+
+ QCOMPARE(cameraLens.projectionMatrix(), cloneData.projectionMatrix);
+ QCOMPARE(cameraLens.id(), creationChangeData->subjectId());
+ QCOMPARE(cameraLens.isEnabled(), true);
+ QCOMPARE(cameraLens.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(cameraLens.metaObject(), creationChangeData->metaObject());
+ }
+
+ // WHEN
+ cameraLens.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&cameraLens);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QCameraLensData>>(creationChanges.first());
+ const Qt3DRender::QCameraLensData cloneData = creationChangeData->data;
+
+ QCOMPARE(cameraLens.projectionMatrix(), cloneData.projectionMatrix);
+ QCOMPARE(cameraLens.id(), creationChangeData->subjectId());
+ QCOMPARE(cameraLens.isEnabled(), false);
+ QCOMPARE(cameraLens.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(cameraLens.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkProjectionTypeUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setProjectionType(Qt3DRender::QCameraLens::FrustumProjection);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setProjectionType(Qt3DRender::QCameraLens::FrustumProjection);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkNearPlaneUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setNearPlane(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setNearPlane(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkFarPlaneUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setFarPlane(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setFarPlane(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkFieldOfViewUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setFieldOfView(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setFieldOfView(5.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkAspectRatioUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setAspectRatio(9.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setAspectRatio(9.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkLeftUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setLeft(0.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setLeft(0.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkRightUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setRight(24.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setRight(24.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkBottomUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setBottom(-12.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setBottom(-12.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkTopUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ {
+ // WHEN
+ cameraLens.setTop(12.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setTop(12.0f);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkProjectionMatrixUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QCameraLens cameraLens;
+ arbiter.setArbiterOnNode(&cameraLens);
+
+ QMatrix4x4 m;
+ m.translate(-5.0f, 5.0f, 25.0f);
+
+ {
+ // WHEN
+ cameraLens.setProjectionMatrix(m);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "projectionMatrix");
+ QCOMPARE(change->value().value<QMatrix4x4>(), m);
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ cameraLens.setProjectionMatrix(m);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+};
+
+QTEST_MAIN(tst_QCameraLens)
+
+#include "tst_qcameralens.moc"
diff --git a/tests/auto/render/qcomputecommand/qcomputecommand.pro b/tests/auto/render/qcomputecommand/qcomputecommand.pro
new file mode 100644
index 000000000..92c971c51
--- /dev/null
+++ b/tests/auto/render/qcomputecommand/qcomputecommand.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qcomputecommand
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qcomputecommand.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp b/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp
new file mode 100644
index 000000000..94609c129
--- /dev/null
+++ b/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
+** 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 <Qt3DRender/qcomputecommand.h>
+#include <Qt3DRender/private/qcomputecommand_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include "testpostmanarbiter.h"
+
+class tst_QComputeCommand : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QComputeCommand computeCommand;
+
+ // THEN
+ QCOMPARE(computeCommand.workGroupX(), 1);
+ QCOMPARE(computeCommand.workGroupY(), 1);
+ QCOMPARE(computeCommand.workGroupZ(), 1);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DRender::QComputeCommand computeCommand;
+
+ {
+ // WHEN
+ QSignalSpy spy(&computeCommand, SIGNAL(workGroupXChanged()));
+ const int newValue = 128;
+ computeCommand.setWorkGroupX(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(computeCommand.workGroupX(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ computeCommand.setWorkGroupX(newValue);
+
+ // THEN
+ QCOMPARE(computeCommand.workGroupX(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&computeCommand, SIGNAL(workGroupYChanged()));
+ const int newValue = 256;
+ computeCommand.setWorkGroupY(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(computeCommand.workGroupY(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ computeCommand.setWorkGroupY(newValue);
+
+ // THEN
+ QCOMPARE(computeCommand.workGroupY(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&computeCommand, SIGNAL(workGroupZChanged()));
+ const int newValue = 512;
+ computeCommand.setWorkGroupZ(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(computeCommand.workGroupZ(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ computeCommand.setWorkGroupZ(newValue);
+
+ // THEN
+ QCOMPARE(computeCommand.workGroupZ(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DRender::QComputeCommand computeCommand;
+
+ computeCommand.setWorkGroupX(128);
+ computeCommand.setWorkGroupY(512);
+ computeCommand.setWorkGroupZ(1024);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&computeCommand);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QComputeCommandData>>(creationChanges.first());
+ const Qt3DRender::QComputeCommandData cloneData = creationChangeData->data;
+
+ QCOMPARE(computeCommand.workGroupX(), cloneData.workGroupX);
+ QCOMPARE(computeCommand.workGroupY(), cloneData.workGroupY);
+ QCOMPARE(computeCommand.workGroupZ(), cloneData.workGroupZ);
+ QCOMPARE(computeCommand.id(), creationChangeData->subjectId());
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(computeCommand.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(computeCommand.metaObject(), creationChangeData->metaObject());
+ }
+
+ // WHEN
+ computeCommand.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&computeCommand);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QComputeCommandData>>(creationChanges.first());
+ const Qt3DRender::QComputeCommandData cloneData = creationChangeData->data;
+
+ QCOMPARE(computeCommand.workGroupX(), cloneData.workGroupX);
+ QCOMPARE(computeCommand.workGroupY(), cloneData.workGroupY);
+ QCOMPARE(computeCommand.workGroupZ(), cloneData.workGroupZ);
+ QCOMPARE(computeCommand.id(), creationChangeData->subjectId());
+ QCOMPARE(computeCommand.isEnabled(), false);
+ QCOMPARE(computeCommand.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(computeCommand.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkWorkGroupXUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QComputeCommand computeCommand;
+ arbiter.setArbiterOnNode(&computeCommand);
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupX(256);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "workGroupX");
+ QCOMPARE(change->value().value<int>(), computeCommand.workGroupX());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupX(256);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkWorkGroupYUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QComputeCommand computeCommand;
+ arbiter.setArbiterOnNode(&computeCommand);
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupY(512);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "workGroupY");
+ QCOMPARE(change->value().value<int>(), computeCommand.workGroupY());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupY(512);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkWorkGroupZUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QComputeCommand computeCommand;
+ arbiter.setArbiterOnNode(&computeCommand);
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupZ(64);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "workGroupZ");
+ QCOMPARE(change->value().value<int>(), computeCommand.workGroupZ());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ computeCommand.setWorkGroupZ(64);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+};
+
+QTEST_MAIN(tst_QComputeCommand)
+
+#include "tst_qcomputecommand.moc"
diff --git a/tests/auto/render/qrendertargetoutput/qrendertargetoutput.pro b/tests/auto/render/qrendertargetoutput/qrendertargetoutput.pro
new file mode 100644
index 000000000..e42f4fc22
--- /dev/null
+++ b/tests/auto/render/qrendertargetoutput/qrendertargetoutput.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qrendertargetoutput
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qrendertargetoutput.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp b/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp
new file mode 100644
index 000000000..c847095dc
--- /dev/null
+++ b/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
+** 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 <QObject>
+#include <QMetaObject>
+#include <Qt3DRender/qrendertargetoutput.h>
+#include <Qt3DRender/private/qrendertargetoutput_p.h>
+#include <Qt3DRender/qabstracttexture.h>
+#include <Qt3DRender/qtexture.h>
+#include <QSignalSpy>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include "testpostmanarbiter.h"
+
+class tst_QRenderTargetOutput : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<Qt3DRender::QRenderTargetOutput::AttachmentPoint>("AttachmentPoint");
+ qRegisterMetaType<Qt3DRender::QAbstractTexture::CubeMapFace>("QAbstractTexture::CubeMapFace");
+ }
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+
+ // THEN
+ QCOMPARE(renderTargetOutput.attachmentPoint(), Qt3DRender::QRenderTargetOutput::Color0);
+ QVERIFY(renderTargetOutput.texture() == nullptr);
+ QCOMPARE(renderTargetOutput.mipLevel(), 0);
+ QCOMPARE(renderTargetOutput.layer(), 0);
+ QCOMPARE(renderTargetOutput.face(), Qt3DRender::QAbstractTexture::CubeMapNegativeX);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+
+ {
+ // WHEN
+ QSignalSpy spy(&renderTargetOutput, SIGNAL(attachmentPointChanged(AttachmentPoint)));
+ const Qt3DRender::QRenderTargetOutput::AttachmentPoint newValue = Qt3DRender::QRenderTargetOutput::Color15;
+ renderTargetOutput.setAttachmentPoint(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(renderTargetOutput.attachmentPoint(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ renderTargetOutput.setAttachmentPoint(newValue);
+
+ // THEN
+ QCOMPARE(renderTargetOutput.attachmentPoint(), newValue);
+ QCOMPARE(spy.count(), 0);
+
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&renderTargetOutput, SIGNAL(textureChanged(QAbstractTexture *)));
+ Qt3DRender::QTexture3D newValue;
+ renderTargetOutput.setTexture(&newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(renderTargetOutput.texture(), &newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ renderTargetOutput.setTexture(&newValue);
+
+ // THEN
+ QCOMPARE(renderTargetOutput.texture(), &newValue);
+ QCOMPARE(spy.count(), 0);
+
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&renderTargetOutput, SIGNAL(mipLevelChanged(int)));
+ const int newValue = 5;
+ renderTargetOutput.setMipLevel(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(renderTargetOutput.mipLevel(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ renderTargetOutput.setMipLevel(newValue);
+
+ // THEN
+ QCOMPARE(renderTargetOutput.mipLevel(), newValue);
+ QCOMPARE(spy.count(), 0);
+
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&renderTargetOutput, SIGNAL(layerChanged(int)));
+ const int newValue = 300;
+ renderTargetOutput.setLayer(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(renderTargetOutput.layer(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ renderTargetOutput.setLayer(newValue);
+
+ // THEN
+ QCOMPARE(renderTargetOutput.layer(), newValue);
+ QCOMPARE(spy.count(), 0);
+
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&renderTargetOutput, SIGNAL(faceChanged(QAbstractTexture::CubeMapFace)));
+ const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeZ;
+ renderTargetOutput.setFace(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(renderTargetOutput.face(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ renderTargetOutput.setFace(newValue);
+
+ // THEN
+ QCOMPARE(renderTargetOutput.face(), newValue);
+ QCOMPARE(spy.count(), 0);
+
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+
+ renderTargetOutput.setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color5);
+ renderTargetOutput.setMipLevel(10);
+ renderTargetOutput.setLayer(2);
+ renderTargetOutput.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeY);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&renderTargetOutput);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QRenderTargetOutputData>>(creationChanges.first());
+ const Qt3DRender::QRenderTargetOutputData cloneData = creationChangeData->data;
+
+ QCOMPARE(renderTargetOutput.attachmentPoint(), cloneData.attachmentPoint);
+ QCOMPARE(Qt3DCore::QNodeId(), cloneData.textureId);
+ QCOMPARE(renderTargetOutput.mipLevel(), cloneData.mipLevel);
+ QCOMPARE(renderTargetOutput.layer(), cloneData.layer);
+ QCOMPARE(renderTargetOutput.face(), cloneData.face);
+ QCOMPARE(renderTargetOutput.id(), creationChangeData->subjectId());
+ QCOMPARE(renderTargetOutput.isEnabled(), true);
+ QCOMPARE(renderTargetOutput.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(renderTargetOutput.metaObject(), creationChangeData->metaObject());
+ }
+
+ // WHEN
+ renderTargetOutput.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&renderTargetOutput);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QRenderTargetOutputData>>(creationChanges.first());
+ const Qt3DRender::QRenderTargetOutputData cloneData = creationChangeData->data;
+
+ QCOMPARE(renderTargetOutput.attachmentPoint(), cloneData.attachmentPoint);
+ QCOMPARE(Qt3DCore::QNodeId(), cloneData.textureId);
+ QCOMPARE(renderTargetOutput.mipLevel(), cloneData.mipLevel);
+ QCOMPARE(renderTargetOutput.layer(), cloneData.layer);
+ QCOMPARE(renderTargetOutput.face(), cloneData.face);
+ QCOMPARE(renderTargetOutput.id(), creationChangeData->subjectId());
+ QCOMPARE(renderTargetOutput.isEnabled(), false);
+ QCOMPARE(renderTargetOutput.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(renderTargetOutput.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkAttachmentPointUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+ arbiter.setArbiterOnNode(&renderTargetOutput);
+
+ {
+ // WHEN
+ renderTargetOutput.setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "attachmentPoint");
+ QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), renderTargetOutput.attachmentPoint());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ renderTargetOutput.setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkTextureUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+ Qt3DRender::QTexture3D texture;
+ arbiter.setArbiterOnNode(&renderTargetOutput);
+
+ {
+ // WHEN
+ renderTargetOutput.setTexture(&texture);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "texture");
+ QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), renderTargetOutput.texture()->id());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ renderTargetOutput.setTexture(&texture);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkMipLevelUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+ arbiter.setArbiterOnNode(&renderTargetOutput);
+
+ {
+ // WHEN
+ renderTargetOutput.setMipLevel(6);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "mipLevel");
+ QCOMPARE(change->value().value<int>(), renderTargetOutput.mipLevel());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ renderTargetOutput.setMipLevel(6);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkLayerUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+ arbiter.setArbiterOnNode(&renderTargetOutput);
+
+ {
+ // WHEN
+ renderTargetOutput.setLayer(8);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "layer");
+ QCOMPARE(change->value().value<int>(), renderTargetOutput.layer());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ renderTargetOutput.setLayer(8);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkFaceUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QRenderTargetOutput renderTargetOutput;
+ arbiter.setArbiterOnNode(&renderTargetOutput);
+
+ {
+ // WHEN
+ renderTargetOutput.setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveY);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "face");
+ QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::CubeMapFace>(), renderTargetOutput.face());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ renderTargetOutput.setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveY);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+};
+
+QTEST_MAIN(tst_QRenderTargetOutput)
+
+#include "tst_qrendertargetoutput.moc"
diff --git a/tests/auto/render/qsceneloader/tst_qsceneloader.cpp b/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
index 1d434f5d3..dd3babb06 100644
--- a/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
+++ b/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
@@ -27,12 +27,15 @@
****************************************************************************/
#include <QtTest/QTest>
+#include <Qt3DCore/qentity.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DRender/qsceneloader.h>
#include <Qt3DRender/private/qsceneloader_p.h>
+#include <QSignalSpy>
#include "testpostmanarbiter.h"
@@ -42,6 +45,17 @@ class tst_QSceneLoader: public QObject
private Q_SLOTS:
+ void checkInitialState()
+ {
+ // GIVEN
+ Qt3DRender::QSceneLoader sceneLoader;
+
+ // THEN
+ QCOMPARE(sceneLoader.status(), Qt3DRender::QSceneLoader::None);
+ QVERIFY(sceneLoader.source().isEmpty());
+ QVERIFY(static_cast<Qt3DRender::QSceneLoaderPrivate *>(Qt3DCore::QNodePrivate::get(&sceneLoader))->m_subTreeRoot == nullptr);
+ }
+
void checkCreationData()
{
// GIVEN
@@ -98,7 +112,7 @@ private Q_SLOTS:
}
}
- void checkPropertyUpdates()
+ void checkSourcePropertyUpdate()
{
// GIVEN
TestArbiter arbiter;
@@ -118,6 +132,58 @@ private Q_SLOTS:
arbiter.events.clear();
}
+
+ void checkStatusPropertyUpdate()
+ {
+ // GIVEN
+ qRegisterMetaType<Qt3DRender::QSceneLoader::Status>("Status");
+ TestArbiter arbiter;
+ QScopedPointer<Qt3DRender::QSceneLoader> sceneLoader(new Qt3DRender::QSceneLoader());
+ arbiter.setArbiterOnNode(sceneLoader.data());
+ QSignalSpy spy(sceneLoader.data(), SIGNAL(statusChanged(Status)));
+
+
+ // WHEN
+ const Qt3DRender::QSceneLoader::Status newStatus = Qt3DRender::QSceneLoader::Ready;
+ sceneLoader->setStatus(newStatus);
+
+ // THEN
+ QVERIFY(arbiter.events.empty());
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DCore::QScene scene;
+ Qt3DCore::QEntity rootEntity;
+ QScopedPointer<Qt3DRender::QSceneLoader> sceneLoader(new Qt3DRender::QSceneLoader());
+ Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(sceneLoader.data())->setScene(&scene);
+ rootEntity.addComponent(sceneLoader.data());
+
+ // WHEN
+ Qt3DCore::QEntity backendCreatedSubtree;
+ Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ valueChange->setPropertyName("scene");
+ valueChange->setValue(QVariant::fromValue(&backendCreatedSubtree));
+ sceneLoader->sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(static_cast<Qt3DRender::QSceneLoaderPrivate *>(Qt3DCore::QNodePrivate::get(sceneLoader.data()))->m_subTreeRoot, &backendCreatedSubtree);
+
+ // WHEN
+ const Qt3DRender::QSceneLoader::Status newStatus = Qt3DRender::QSceneLoader::Ready;
+ valueChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ valueChange->setPropertyName("status");
+ valueChange->setValue(QVariant::fromValue(newStatus));
+ sceneLoader->sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(sceneLoader->status(), newStatus);
+ }
};
QTEST_MAIN(tst_QSceneLoader)
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 7f62f609c..36eda8afb 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -53,7 +53,9 @@ qtConfig(private_tests) {
qgraphicsapifilter \
qrendersurfaceselector \
sortpolicy \
- qcuboidgeometry \
sceneloader \
- qsceneloader
+ qsceneloader \
+ qrendertargetoutput \
+ qcameralens \
+ qcomputecommand
}
diff --git a/tests/auto/render/sceneloader/tst_sceneloader.cpp b/tests/auto/render/sceneloader/tst_sceneloader.cpp
index 7d31590d9..05f4f08b6 100644
--- a/tests/auto/render/sceneloader/tst_sceneloader.cpp
+++ b/tests/auto/render/sceneloader/tst_sceneloader.cpp
@@ -149,6 +149,28 @@ private Q_SLOTS:
arbiter.events.clear();
}
+
+ void checkStatusTransmission()
+ {
+ // GIVEN
+ TestRenderer renderer;
+ TestArbiter arbiter;
+ Qt3DRender::Render::Scene sceneLoader;
+
+ Qt3DCore::QBackendNodePrivate::get(&sceneLoader)->setArbiter(&arbiter);
+ sceneLoader.setRenderer(&renderer);
+
+ // WHEN
+ sceneLoader.setStatus(Qt3DRender::QSceneLoader::Ready);
+
+ // THEN
+ Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(arbiter.events.count(), 1);
+ QCOMPARE(change->propertyName(), "status");
+ QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Ready);
+
+ arbiter.events.clear();
+ }
};
// Note: setSceneSubtree needs a QCoreApplication