1/****************************************************************************
2**
3** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
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// TODO Remove in Qt6
30#include <QtCore/qcompilerdetection.h>
31QT_WARNING_DISABLE_DEPRECATED
32
33#include <QtTest/QTest>
34#include <Qt3DRender/qmesh.h>
35#include <Qt3DRender/private/qmesh_p.h>
36#include <QObject>
37#include <QSignalSpy>
38#include <Qt3DCore/qpropertyupdatedchange.h>
39#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
40#include <Qt3DCore/private/qscene_p.h>
41#include <Qt3DCore/qnodecreatedchange.h>
42#include "testpostmanarbiter.h"
43
44class MyQMesh : public Qt3DRender::QMesh
45{
46 Q_OBJECT
47public:
48 explicit MyQMesh(Qt3DCore::QNode *parent = nullptr)
49 : Qt3DRender::QMesh(parent)
50 {}
51
52 void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) final
53 {
54 Qt3DRender::QMesh::sceneChangeEvent(change);
55 }
56};
57
58class tst_QMesh : public QObject
59{
60 Q_OBJECT
61
62private Q_SLOTS:
63
64 void checkDefaultConstruction()
65 {
66 // GIVEN
67 Qt3DRender::QMesh mesh;
68
69 // THEN
70 QCOMPARE(mesh.source(), QUrl());
71 QCOMPARE(mesh.meshName(), QString());
72 QCOMPARE(mesh.status(), Qt3DRender::QMesh::None);
73 }
74
75 void checkPropertyChanges()
76 {
77 // GIVEN
78 Qt3DRender::QMesh mesh;
79
80 {
81 // WHEN
82 QSignalSpy spy(&mesh, SIGNAL(sourceChanged(QUrl)));
83 const QUrl newValue(QStringLiteral("qrc:/mesh.obj"));
84 mesh.setSource(newValue);
85
86 // THEN
87 QVERIFY(spy.isValid());
88 QCOMPARE(mesh.source(), newValue);
89 QCOMPARE(spy.count(), 1);
90
91 // WHEN
92 spy.clear();
93 mesh.setSource(newValue);
94
95 // THEN
96 QCOMPARE(mesh.source(), newValue);
97 QCOMPARE(spy.count(), 0);
98 }
99 {
100 // WHEN
101 QSignalSpy spy(&mesh, SIGNAL(meshNameChanged(QString)));
102 const QString newValue = QStringLiteral("MainBody");
103 mesh.setMeshName(newValue);
104
105 // THEN
106 QVERIFY(spy.isValid());
107 QCOMPARE(mesh.meshName(), newValue);
108 QCOMPARE(spy.count(), 1);
109
110 // WHEN
111 spy.clear();
112 mesh.setMeshName(newValue);
113
114 // THEN
115 QCOMPARE(mesh.meshName(), newValue);
116 QCOMPARE(spy.count(), 0);
117 }
118 }
119
120 void checkCreationData()
121 {
122 // GIVEN
123 Qt3DRender::QMesh mesh;
124
125 mesh.setSource(QUrl(QStringLiteral("http://someRemoteURL.com")));
126 mesh.setMeshName(QStringLiteral("RearPropeller"));
127
128 // WHEN
129 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
130
131 {
132 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mesh);
133 creationChanges = creationChangeGenerator.creationChanges();
134 }
135
136 // THEN
137 {
138 QCOMPARE(creationChanges.size(), 1);
139
140 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QGeometryRendererData>>(src: creationChanges.first());
141 const Qt3DRender::QGeometryRendererData cloneData = creationChangeData->data;
142
143 // Geometry factory shouldn't be null
144 QVERIFY(cloneData.geometryFactory != nullptr);
145 QCOMPARE(mesh.id(), creationChangeData->subjectId());
146 QCOMPARE(mesh.isEnabled(), true);
147 QCOMPARE(mesh.isEnabled(), creationChangeData->isNodeEnabled());
148 QCOMPARE(mesh.metaObject(), creationChangeData->metaObject());
149 }
150
151 // WHEN
152 mesh.setEnabled(false);
153
154 {
155 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mesh);
156 creationChanges = creationChangeGenerator.creationChanges();
157 }
158
159 // THEN
160 {
161 QCOMPARE(creationChanges.size(), 1);
162
163 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QGeometryRendererData>>(src: creationChanges.first());
164
165 QCOMPARE(mesh.id(), creationChangeData->subjectId());
166 QCOMPARE(mesh.isEnabled(), false);
167 QCOMPARE(mesh.isEnabled(), creationChangeData->isNodeEnabled());
168 QCOMPARE(mesh.metaObject(), creationChangeData->metaObject());
169 }
170 }
171
172 void checkSourceUpdate()
173 {
174 // GIVEN
175 TestArbiter arbiter;
176 Qt3DRender::QMesh mesh;
177 arbiter.setArbiterOnNode(&mesh);
178
179 Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef);
180 Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine);
181 Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(q: &mesh);
182 meshd->setScene(scene);
183 QCoreApplication::processEvents();
184 arbiter.events.clear();
185
186 {
187 // WHEN
188 mesh.setSource(QUrl(QStringLiteral("qrc:/toyplane.obj")));
189 QCoreApplication::processEvents();
190
191 // THEN
192 QCOMPARE(arbiter.dirtyNodes.size(), 1);
193 QCOMPARE(arbiter.dirtyNodes.front(), &mesh);
194
195 arbiter.dirtyNodes.clear();
196 }
197
198 {
199 // WHEN
200 mesh.setSource(QStringLiteral("qrc:/toyplane.obj"));
201 QCoreApplication::processEvents();
202
203 // THEN
204 QCOMPARE(arbiter.dirtyNodes.size(), 0);
205 }
206
207 }
208
209 void checkMeshNameUpdate()
210 {
211 // GIVEN
212 TestArbiter arbiter;
213 Qt3DRender::QMesh mesh;
214 arbiter.setArbiterOnNode(&mesh);
215
216 Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef);
217 Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine);
218 Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(q: &mesh);
219 meshd->setScene(scene);
220 QCoreApplication::processEvents();
221 arbiter.events.clear();
222
223 {
224 // WHEN
225 mesh.setMeshName(QStringLiteral("Phil"));
226 QCoreApplication::processEvents();
227
228 // THEN
229 QCOMPARE(arbiter.dirtyNodes.size(), 1);
230 QCOMPARE(arbiter.dirtyNodes.front(), &mesh);
231
232 arbiter.dirtyNodes.clear();
233 }
234
235 {
236 // WHEN
237 mesh.setMeshName(QStringLiteral("Phil"));
238 QCoreApplication::processEvents();
239
240 // THEN
241 QCOMPARE(arbiter.dirtyNodes.size(), 0);
242 }
243
244 }
245
246 void checkGeometryFactoryIsAccessibleEvenWithNoScene() // QTBUG-65506
247 {
248 // GIVEN
249 Qt3DRender::QMesh mesh;
250
251 // WHEN
252 mesh.setSource(QUrl(QStringLiteral("some_path")));
253
254 // THEN
255 QVERIFY(!mesh.geometryFactory().isNull());
256 }
257};
258
259QTEST_MAIN(tst_QMesh)
260
261#include "tst_qmesh.moc"
262

source code of qt3d/tests/auto/render/qmesh/tst_qmesh.cpp