1/****************************************************************************
2**
3** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QTest>
30#include <QtTest/QSignalSpy>
31#include <Qt3DCore/private/qnode_p.h>
32#include <Qt3DCore/private/qscene_p.h>
33#include <Qt3DCore/qpropertyupdatedchange.h>
34#include <Qt3DCore/qpropertynodeaddedchange.h>
35#include <Qt3DCore/qpropertynoderemovedchange.h>
36#include <Qt3DRender/QRayCaster>
37#include <Qt3DRender/QLayer>
38
39#include "testpostmanarbiter.h"
40
41class MyRayCaster : public Qt3DRender::QRayCaster
42{
43 Q_OBJECT
44public:
45 MyRayCaster(Qt3DCore::QNode *parent = nullptr)
46 : Qt3DRender::QRayCaster(parent)
47 {
48 qRegisterMetaType<Qt3DRender::QAbstractRayCaster::Hits>(typeName: "Hits");
49 }
50
51 void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) final
52 {
53 Qt3DRender::QRayCaster::sceneChangeEvent(change);
54 }
55
56private:
57 friend class tst_RayCaster;
58};
59
60// We need to call QNode::clone which is protected
61// So we sublcass QNode instead of QObject
62class tst_QRayCaster : public Qt3DCore::QNode
63{
64 Q_OBJECT
65public:
66 tst_QRayCaster()
67 {
68 }
69
70 ~tst_QRayCaster()
71 {
72 QMetaObject::invokeMethod(obj: this, member: "_q_cleanup", type: Qt::DirectConnection);
73 }
74
75private Q_SLOTS:
76
77 void checkState()
78 {
79 // GIVEN
80 QScopedPointer<Qt3DRender::QRayCaster> rayCaster(new Qt3DRender::QRayCaster());
81
82 QVERIFY(!rayCaster->isEnabled());
83 QVERIFY(rayCaster->direction().length() > 0.f);
84 QCOMPARE(rayCaster->runMode(), Qt3DRender::QAbstractRayCaster::SingleShot);
85
86 // WHEN
87 rayCaster->trigger();
88
89 // THEN
90 QVERIFY(rayCaster->isEnabled());
91
92 // WHEN
93 rayCaster->setEnabled(false);
94 rayCaster->trigger(origin: QVector3D(1., 2., 3.), direction: QVector3D(1., 0., 0.), length: 10.f);
95
96 // THEN
97 QVERIFY(rayCaster->isEnabled());
98 QCOMPARE(rayCaster->origin(), QVector3D(1., 2., 3.));
99 QCOMPARE(rayCaster->direction(), QVector3D(1., 0., 0.));
100 QCOMPARE(rayCaster->length(), 10.f);
101 }
102
103 void checkPropertyUpdates()
104 {
105 // GIVEN
106 TestArbiter arbiter;
107 QScopedPointer<Qt3DRender::QRayCaster> rayCaster(new Qt3DRender::QRayCaster());
108 arbiter.setArbiterOnNode(rayCaster.data());
109
110 // WHEN
111 rayCaster->setOrigin({1., 1., 1.});
112 QCoreApplication::processEvents();
113
114 // THEN
115 QCOMPARE(arbiter.events.size(), 0);
116 QCOMPARE(arbiter.dirtyNodes.size(), 1);
117 QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
118
119 arbiter.dirtyNodes.clear();
120
121 // WHEN
122 auto layer = new Qt3DRender::QLayer(rayCaster.data());
123 QCoreApplication::processEvents();
124 rayCaster->addLayer(layer);
125 QCoreApplication::processEvents();
126
127 // THEN
128 QCOMPARE(arbiter.events.size(), 0);
129 QCOMPARE(arbiter.dirtyNodes.size(), 1);
130 QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
131
132 arbiter.dirtyNodes.clear();
133 arbiter.events.clear();
134
135 // WHEN
136 layer = new Qt3DRender::QLayer(rayCaster.data());
137 QCoreApplication::processEvents();
138 rayCaster->addLayer(layer);
139 QCoreApplication::processEvents();
140
141 // THEN
142 QCOMPARE(arbiter.events.size(), 0);
143 QCOMPARE(arbiter.dirtyNodes.size(), 1);
144 QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
145
146 arbiter.dirtyNodes.clear();
147 arbiter.events.clear();
148
149 // WHEN
150 layer = rayCaster->layers().at(i: 0);
151 rayCaster->removeLayer(layer);
152 QCoreApplication::processEvents();
153
154 // THEN
155 QCOMPARE(arbiter.events.size(), 0);
156 QCOMPARE(arbiter.dirtyNodes.size(), 1);
157 QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
158
159 arbiter.dirtyNodes.clear();
160 arbiter.events.clear();
161 }
162
163 void checkLayerBookkeeping()
164 {
165 // GIVEN
166 QScopedPointer<Qt3DRender::QRayCaster> rayCaster(new Qt3DRender::QRayCaster);
167 {
168 // WHEN
169 Qt3DRender::QLayer layer;
170 rayCaster->addLayer(layer: &layer);
171
172 // THEN
173 QCOMPARE(layer.parent(), rayCaster.data());
174 QCOMPARE(rayCaster->layers().size(), 1);
175 }
176 // THEN (Should not crash and parameter be unset)
177 QVERIFY(rayCaster->layers().empty());
178
179 {
180 // WHEN
181 Qt3DRender::QRayCaster someOtherRayCaster;
182 QScopedPointer<Qt3DRender::QLayer> layer(new Qt3DRender::QLayer(&someOtherRayCaster));
183 rayCaster->addLayer(layer: layer.data());
184
185 // THEN
186 QCOMPARE(layer->parent(), &someOtherRayCaster);
187 QCOMPARE(rayCaster->layers().size(), 1);
188
189 // WHEN
190 rayCaster.reset();
191 layer.reset();
192
193 // THEN Should not crash when the layer is destroyed (tests for failed removal of destruction helper)
194 }
195 }
196
197 void checkBackendUpdates_data()
198 {
199 QTest::addColumn<QByteArray>(name: "signalPrototype");
200 QTest::addColumn<QByteArray>(name: "propertyName");
201
202 QTest::newRow(dataTag: "hits")
203 << QByteArray(SIGNAL(hitsChanged(const Hits &)))
204 << QByteArrayLiteral("hits");
205 }
206};
207
208QTEST_MAIN(tst_QRayCaster)
209
210#include "tst_qraycaster.moc"
211

source code of qt3d/tests/auto/render/qraycaster/tst_qraycaster.cpp