1/****************************************************************************
2**
3** Copyright (C) 2017 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 <Qt3DCore/qjoint.h>
31#include <Qt3DCore/private/qjoint_p.h>
32#include <Qt3DCore/qnodecreatedchange.h>
33#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
34#include <QObject>
35#include <QSignalSpy>
36#include <testpostmanarbiter.h>
37
38using namespace Qt3DCore;
39
40class tst_QJoint : public QObject
41{
42 Q_OBJECT
43
44private Q_SLOTS:
45 void checkDefaultConstruction()
46 {
47 // GIVEN
48 QJoint joint;
49
50 // THEN
51 QCOMPARE(joint.scale(), QVector3D(1.0f, 1.0f, 1.0f));
52 QCOMPARE(joint.rotation(), QQuaternion());
53 QCOMPARE(joint.translation(), QVector3D(0.0f, 0.0f, 0.0f));
54 QCOMPARE(joint.inverseBindMatrix(), QMatrix4x4());
55 QCOMPARE(joint.rotationX(), 0.0f);
56 QCOMPARE(joint.rotationY(), 0.0f);
57 QCOMPARE(joint.rotationZ(), 0.0f);
58 }
59
60 void checkPropertyChanges()
61 {
62 // GIVEN
63 QJoint joint;
64
65 {
66 // WHEN
67 joint.setToIdentity();
68 QSignalSpy spy(&joint, SIGNAL(scaleChanged(QVector3D)));
69 const QVector3D newValue(2.5f, 2.0f, 1.3f);
70 joint.setScale(newValue);
71
72 // THEN
73 QVERIFY(spy.isValid());
74 QCOMPARE(joint.scale(), newValue);
75 QCOMPARE(spy.count(), 1);
76
77 // WHEN
78 spy.clear();
79 joint.setScale(newValue);
80
81 // THEN
82 QCOMPARE(joint.scale(), newValue);
83 QCOMPARE(spy.count(), 0);
84 }
85
86 {
87 // WHEN
88 joint.setToIdentity();
89 QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion)));
90 const auto newValue = QQuaternion::fromAxisAndAngle(x: 0.0f, y: 1.0f, z: 0.0f, angle: 45.0f);
91 joint.setRotation(newValue);
92
93 // THEN
94 QVERIFY(spy.isValid());
95 QCOMPARE(joint.rotation(), newValue);
96 QCOMPARE(spy.count(), 1);
97
98 // WHEN
99 spy.clear();
100 joint.setRotation(newValue);
101
102 // THEN
103 QCOMPARE(joint.rotation(), newValue);
104 QCOMPARE(spy.count(), 0);
105 }
106
107 {
108 // WHEN
109 joint.setToIdentity();
110 QSignalSpy spy(&joint, SIGNAL(translationChanged(QVector3D)));
111 const QVector3D newValue(1.0f, 2.0f, 3.0f);
112 joint.setTranslation(newValue);
113
114 // THEN
115 QVERIFY(spy.isValid());
116 QCOMPARE(joint.translation(), newValue);
117 QCOMPARE(spy.count(), 1);
118
119 // WHEN
120 spy.clear();
121 joint.setTranslation(newValue);
122
123 // THEN
124 QCOMPARE(joint.translation(), newValue);
125 QCOMPARE(spy.count(), 0);
126 }
127
128 {
129 // WHEN
130 joint.setToIdentity();
131 QSignalSpy spy(&joint, SIGNAL(inverseBindMatrixChanged(QMatrix4x4)));
132 QMatrix4x4 newValue;
133 newValue.scale(factor: 3.5f);
134 joint.setInverseBindMatrix(newValue);
135
136 // THEN
137 QVERIFY(spy.isValid());
138 QCOMPARE(joint.inverseBindMatrix(), newValue);
139 QCOMPARE(spy.count(), 1);
140
141 // WHEN
142 spy.clear();
143 joint.setInverseBindMatrix(newValue);
144
145 // THEN
146 QCOMPARE(joint.inverseBindMatrix(), newValue);
147 QCOMPARE(spy.count(), 0);
148 }
149
150 {
151 // WHEN
152 joint.setToIdentity();
153 QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion)));
154 QSignalSpy spyEuler(&joint, SIGNAL(rotationXChanged(float)));
155 const auto newValue = 45.0f;
156 const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(pitch: newValue, yaw: 0.0f, roll: 0.0f);
157 joint.setRotationX(newValue);
158
159 // THEN
160 QVERIFY(spy.isValid());
161 QVERIFY(spyEuler.isValid());
162 QCOMPARE(joint.rotationX(), newValue);
163 QCOMPARE(joint.rotation(), newValueAsQuaternion);
164 QCOMPARE(spy.count(), 1);
165 QCOMPARE(spyEuler.count(), 1);
166
167 // WHEN
168 spy.clear();
169 spyEuler.clear();
170 joint.setRotationX(newValue);
171
172 // THEN
173 QCOMPARE(joint.rotationX(), newValue);
174 QCOMPARE(joint.rotation(), newValueAsQuaternion);
175 QCOMPARE(spy.count(), 0);
176 QCOMPARE(spyEuler.count(), 0);
177
178 joint.setRotationX(0.0f);
179 }
180
181 {
182 // WHEN
183 joint.setToIdentity();
184 QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion)));
185 QSignalSpy spyEuler(&joint, SIGNAL(rotationYChanged(float)));
186 const auto newValue = 45.0f;
187 const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(pitch: 0.0f, yaw: newValue, roll: 0.0f);
188 joint.setRotationY(newValue);
189
190 // THEN
191 QVERIFY(spy.isValid());
192 QVERIFY(spyEuler.isValid());
193 QCOMPARE(joint.rotationY(), newValue);
194 QCOMPARE(joint.rotation(), newValueAsQuaternion);
195 QCOMPARE(spy.count(), 1);
196 QCOMPARE(spyEuler.count(), 1);
197
198 // WHEN
199 spy.clear();
200 spyEuler.clear();
201 joint.setRotationY(newValue);
202
203 // THEN
204 QCOMPARE(joint.rotationY(), newValue);
205 QCOMPARE(joint.rotation(), newValueAsQuaternion);
206 QCOMPARE(spy.count(), 0);
207 QCOMPARE(spyEuler.count(), 0);
208
209 joint.setRotationY(0.0f);
210 }
211
212 {
213 // WHEN
214 joint.setToIdentity();
215 QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion)));
216 QSignalSpy spyEuler(&joint, SIGNAL(rotationZChanged(float)));
217 const auto newValue = 45.0f;
218 const auto newValueAsQuaternion = QQuaternion::fromEulerAngles(pitch: 0.0f, yaw: 0.0f, roll: newValue);
219 joint.setRotationZ(newValue);
220
221 // THEN
222 QVERIFY(spy.isValid());
223 QVERIFY(spyEuler.isValid());
224 QCOMPARE(joint.rotationZ(), newValue);
225 QCOMPARE(joint.rotation(), newValueAsQuaternion);
226 QCOMPARE(spy.count(), 1);
227 QCOMPARE(spyEuler.count(), 1);
228
229 // WHEN
230 spy.clear();
231 spyEuler.clear();
232 joint.setRotationZ(newValue);
233
234 // THEN
235 QCOMPARE(joint.rotationZ(), newValue);
236 QCOMPARE(joint.rotation(), newValueAsQuaternion);
237 QCOMPARE(spy.count(), 0);
238 QCOMPARE(spyEuler.count(), 0);
239
240 joint.setRotationZ(0.0f);
241 }
242 }
243
244 void checkCreationData()
245 {
246 // GIVEN
247 QJoint joint;
248
249 joint.setScale(QVector3D(3.5f, 2.0f, 1.3f));
250 joint.setRotation(QQuaternion::fromAxisAndAngle(x: 0.0f, y: 1.0f, z: 0.0f, angle: 30.0f));
251 joint.setTranslation(QVector3D(3.0f, 2.0f, 1.0f));
252 QMatrix4x4 ibm;
253 ibm.scale(factor: 5.2f);
254 joint.setInverseBindMatrix(ibm);
255
256 // WHEN
257 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
258
259 {
260 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&joint);
261 creationChanges = creationChangeGenerator.creationChanges();
262 }
263
264 // THEN
265 {
266 QCOMPARE(creationChanges.size(), 1);
267
268 const auto creationChangeData
269 = qSharedPointerCast<QNodeCreatedChange<QJointData>>(src: creationChanges.first());
270 const QJointData data = creationChangeData->data;
271
272 QCOMPARE(joint.id(), creationChangeData->subjectId());
273 QCOMPARE(joint.isEnabled(), true);
274 QCOMPARE(joint.isEnabled(), creationChangeData->isNodeEnabled());
275 QCOMPARE(joint.metaObject(), creationChangeData->metaObject());
276 QCOMPARE(joint.scale(), data.scale);
277 QCOMPARE(joint.rotation(), data.rotation);
278 QCOMPARE(joint.translation(), data.translation);
279 QCOMPARE(joint.inverseBindMatrix(), data.inverseBindMatrix);
280 }
281
282 // WHEN
283 joint.setEnabled(false);
284
285 {
286 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&joint);
287 creationChanges = creationChangeGenerator.creationChanges();
288 }
289
290 // THEN
291 {
292 QCOMPARE(creationChanges.size(), 1);
293
294 const auto creationChangeData
295 = qSharedPointerCast<QNodeCreatedChange<QJointData>>(src: creationChanges.first());
296 const QJointData data = creationChangeData->data;
297
298 QCOMPARE(joint.id(), creationChangeData->subjectId());
299 QCOMPARE(joint.isEnabled(), false);
300 QCOMPARE(joint.isEnabled(), creationChangeData->isNodeEnabled());
301 QCOMPARE(joint.metaObject(), creationChangeData->metaObject());
302 QCOMPARE(joint.scale(), data.scale);
303 QCOMPARE(joint.rotation(), data.rotation);
304 QCOMPARE(joint.translation(), data.translation);
305 QCOMPARE(joint.inverseBindMatrix(), data.inverseBindMatrix);
306 }
307 }
308
309 void checkPropertyUpdateChanges()
310 {
311 // GIVEN
312 TestArbiter arbiter;
313 QJoint joint;
314 arbiter.setArbiterOnNode(&joint);
315
316 {
317 // WHEN
318 joint.setScale(QVector3D(2.0f, 1.0f, 3.0f));
319
320 // THEN
321 QCOMPARE(arbiter.dirtyNodes.size(), 1);
322 QCOMPARE(arbiter.dirtyNodes.front(), &joint);
323
324 arbiter.dirtyNodes.clear();
325
326 // WHEN
327 joint.setScale(QVector3D(2.0f, 1.0f, 3.0f));
328
329 // THEN
330 QCOMPARE(arbiter.dirtyNodes.size(), 0);
331 }
332
333 {
334 // WHEN
335 const auto newValue = QQuaternion::fromAxisAndAngle(x: 1.0f, y: 1.0f, z: 1.0f, angle: 45.0f);
336 joint.setRotation(newValue);
337
338 // THEN
339 QCOMPARE(arbiter.dirtyNodes.size(), 1);
340 QCOMPARE(arbiter.dirtyNodes.front(), &joint);
341
342 arbiter.dirtyNodes.clear();
343
344 // WHEN
345 joint.setRotation(newValue);
346
347 // THEN
348 QCOMPARE(arbiter.dirtyNodes.size(), 0);
349 }
350
351 {
352 // WHEN
353 const QVector3D newValue(1.0f, 2.0f, 3.0f);
354 joint.setTranslation(newValue);
355
356 // THEN
357 QCOMPARE(arbiter.dirtyNodes.size(), 1);
358 QCOMPARE(arbiter.dirtyNodes.front(), &joint);
359
360 arbiter.dirtyNodes.clear();
361
362 // WHEN
363 joint.setTranslation(newValue);
364
365 // THEN
366 QCOMPARE(arbiter.dirtyNodes.size(), 0);
367 }
368
369 {
370 // WHEN
371 QMatrix4x4 newValue;
372 newValue.rotate(angle: 90.0f, x: 1.0f, y: 0.0f, z: 0.0f);
373 joint.setInverseBindMatrix(newValue);
374
375 // THEN
376 QCOMPARE(arbiter.dirtyNodes.size(), 1);
377 QCOMPARE(arbiter.dirtyNodes.front(), &joint);
378
379 arbiter.dirtyNodes.clear();
380
381 // WHEN
382 joint.setInverseBindMatrix(newValue);
383
384 // THEN
385 QCOMPARE(arbiter.dirtyNodes.size(), 0);
386 }
387 }
388};
389
390QTEST_MAIN(tst_QJoint)
391
392#include "tst_qjoint.moc"
393

source code of qt3d/tests/auto/core/qjoint/tst_qjoint.cpp