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
30#include <QtTest/QTest>
31#include <Qt3DAnimation/qblendedclipanimator.h>
32#include <Qt3DAnimation/private/qblendedclipanimator_p.h>
33#include <Qt3DAnimation/qlerpclipblend.h>
34#include <Qt3DAnimation/qchannelmapper.h>
35#include <Qt3DCore/qnodecreatedchange.h>
36#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
37#include <QObject>
38#include <QSignalSpy>
39#include <testpostmanarbiter.h>
40
41class tst_QBlendedClipAnimator : public QObject
42{
43 Q_OBJECT
44
45private Q_SLOTS:
46
47 void initTestCase()
48 {
49 qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(typeName: "QChannelMapper *");
50 qRegisterMetaType<Qt3DAnimation::QAbstractClipBlendNode*>(typeName: "QAbstractClipBlendNode *");
51 }
52
53 void checkDefaultConstruction()
54 {
55 // GIVEN
56 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
57
58 // THEN
59 QVERIFY(blendedClipAnimator.blendTree() == nullptr);
60 QVERIFY(blendedClipAnimator.channelMapper() == nullptr);
61 QCOMPARE(blendedClipAnimator.isRunning(), false);
62 QCOMPARE(blendedClipAnimator.loopCount(), 1);
63 }
64
65 void checkPropertyChanges()
66 {
67 // GIVEN
68 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
69
70 {
71 // WHEN
72 QSignalSpy spy(&blendedClipAnimator, SIGNAL(blendTreeChanged(QAbstractClipBlendNode *)));
73 Qt3DAnimation::QLerpClipBlend newValue;
74 blendedClipAnimator.setBlendTree(&newValue);
75
76 // THEN
77 QVERIFY(spy.isValid());
78 QCOMPARE(blendedClipAnimator.blendTree(), &newValue);
79 QCOMPARE(spy.count(), 1);
80
81 // WHEN
82 spy.clear();
83 blendedClipAnimator.setBlendTree(&newValue);
84
85 // THEN
86 QCOMPARE(blendedClipAnimator.blendTree(), &newValue);
87 QCOMPARE(spy.count(), 0);
88 }
89 {
90 // WHEN
91 QSignalSpy spy(&blendedClipAnimator, SIGNAL(channelMapperChanged(QChannelMapper *)));
92 Qt3DAnimation::QChannelMapper newValue;
93 blendedClipAnimator.setChannelMapper(&newValue);
94
95 // THEN
96 QVERIFY(spy.isValid());
97 QCOMPARE(blendedClipAnimator.channelMapper(), &newValue);
98 QCOMPARE(spy.count(), 1);
99
100 // WHEN
101 spy.clear();
102 blendedClipAnimator.setChannelMapper(&newValue);
103
104 // THEN
105 QCOMPARE(blendedClipAnimator.channelMapper(), &newValue);
106 QCOMPARE(spy.count(), 0);
107 }
108 {
109 // WHEN
110 QSignalSpy spy(&blendedClipAnimator, SIGNAL(runningChanged(bool)));
111 const bool newValue = true;
112 blendedClipAnimator.setRunning(newValue);
113
114 // THEN
115 QVERIFY(spy.isValid());
116 QCOMPARE(blendedClipAnimator.isRunning(), newValue);
117 QCOMPARE(spy.count(), 1);
118
119 // WHEN
120 spy.clear();
121 blendedClipAnimator.setRunning(newValue);
122
123 // THEN
124 QCOMPARE(blendedClipAnimator.isRunning(), newValue);
125 QCOMPARE(spy.count(), 0);
126 }
127
128 {
129 // WHEN
130 QSignalSpy spy(&blendedClipAnimator, SIGNAL(loopCountChanged(int)));
131 const int newValue = 5;
132 blendedClipAnimator.setLoopCount(newValue);
133
134 // THEN
135 QVERIFY(spy.isValid());
136 QCOMPARE(blendedClipAnimator.loopCount(), newValue);
137 QCOMPARE(spy.count(), 1);
138
139 // WHEN
140 spy.clear();
141 blendedClipAnimator.setLoopCount(newValue);
142
143 // THEN
144 QCOMPARE(blendedClipAnimator.loopCount(), newValue);
145 QCOMPARE(spy.count(), 0);
146 }
147
148 {
149 // WHEN
150 QSignalSpy spy(&blendedClipAnimator, SIGNAL(normalizedTimeChanged(float)));
151 const float newValue = 0.5;
152 blendedClipAnimator.setNormalizedTime(newValue);
153
154 // THEN
155 QVERIFY(spy.isValid());
156 QCOMPARE(blendedClipAnimator.normalizedTime(), newValue);
157 QCOMPARE(spy.count(), 1);
158
159 // WHEN
160 spy.clear();
161 blendedClipAnimator.setNormalizedTime(newValue);
162
163 // THEN
164 QCOMPARE(blendedClipAnimator.normalizedTime(), newValue);
165 QCOMPARE(spy.count(), 0);
166 }
167
168 {
169 // WHEN
170 QSignalSpy spy(&blendedClipAnimator, SIGNAL(normalizedTimeChanged(float)));
171 const float newValue = -0.01f; // Invalid
172 blendedClipAnimator.setNormalizedTime(newValue);
173 const float oldValue = blendedClipAnimator.normalizedTime();
174
175 // THEN
176 QVERIFY(spy.isValid());
177 QCOMPARE(blendedClipAnimator.normalizedTime(), oldValue);
178 QCOMPARE(spy.count(), 0);
179
180 // WHEN
181 spy.clear();
182 blendedClipAnimator.setNormalizedTime(1.01f); // Invalid
183
184 // THEN
185 QCOMPARE(blendedClipAnimator.normalizedTime(), oldValue);
186 QCOMPARE(spy.count(), 0);
187 }
188 }
189
190 void checkCreationData()
191 {
192 // GIVEN
193 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
194 Qt3DAnimation::QChannelMapper channelMapper;
195 Qt3DAnimation::QLerpClipBlend blendRoot;
196
197 blendedClipAnimator.setBlendTree(&blendRoot);
198 blendedClipAnimator.setChannelMapper(&channelMapper);
199 blendedClipAnimator.setRunning(true);
200
201 // WHEN
202 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
203
204 {
205 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&blendedClipAnimator);
206 creationChanges = creationChangeGenerator.creationChanges();
207 }
208
209 // THEN
210 {
211 QCOMPARE(creationChanges.size(), 3); // 1 + mapper + blend tree root
212
213 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QBlendedClipAnimatorData>>(src: creationChanges.first());
214 const Qt3DAnimation::QBlendedClipAnimatorData cloneData = creationChangeData->data;
215
216 QCOMPARE(blendedClipAnimator.blendTree()->id(), cloneData.blendTreeRootId);
217 QCOMPARE(blendedClipAnimator.channelMapper()->id(), cloneData.mapperId);
218 QCOMPARE(blendedClipAnimator.isRunning(), cloneData.running);
219 QCOMPARE(blendedClipAnimator.id(), creationChangeData->subjectId());
220 QCOMPARE(blendedClipAnimator.isEnabled(), true);
221 QCOMPARE(blendedClipAnimator.isEnabled(), creationChangeData->isNodeEnabled());
222 QCOMPARE(blendedClipAnimator.metaObject(), creationChangeData->metaObject());
223 QCOMPARE(blendedClipAnimator.loopCount(), cloneData.loops);
224 QCOMPARE(blendedClipAnimator.normalizedTime(), cloneData.normalizedTime);
225 }
226
227 // WHEN
228 blendedClipAnimator.setEnabled(false);
229
230 {
231 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&blendedClipAnimator);
232 creationChanges = creationChangeGenerator.creationChanges();
233 }
234
235 // THEN
236 {
237 QCOMPARE(creationChanges.size(), 3); // 1 + mapper + blend tree root
238
239 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QBlendedClipAnimatorData>>(src: creationChanges.first());
240 const Qt3DAnimation::QBlendedClipAnimatorData cloneData = creationChangeData->data;
241
242 QCOMPARE(blendedClipAnimator.blendTree()->id(), cloneData.blendTreeRootId);
243 QCOMPARE(blendedClipAnimator.channelMapper()->id(), cloneData.mapperId);
244 QCOMPARE(blendedClipAnimator.isRunning(), cloneData.running);
245 QCOMPARE(blendedClipAnimator.id(), creationChangeData->subjectId());
246 QCOMPARE(blendedClipAnimator.isEnabled(), false);
247 QCOMPARE(blendedClipAnimator.isEnabled(), creationChangeData->isNodeEnabled());
248 QCOMPARE(blendedClipAnimator.metaObject(), creationChangeData->metaObject());
249 }
250 }
251
252 void checkBlendTreeUpdate()
253 {
254 // GIVEN
255 TestArbiter arbiter;
256 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
257 arbiter.setArbiterOnNode(&blendedClipAnimator);
258 Qt3DAnimation::QLerpClipBlend blendRoot;
259
260 {
261 // WHEN
262 blendedClipAnimator.setBlendTree(&blendRoot);
263
264 // THEN
265 QCOMPARE(arbiter.events.size(), 0);
266 QCOMPARE(arbiter.dirtyNodes.size(), 1);
267 QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
268
269 arbiter.dirtyNodes.clear();
270 }
271
272 {
273 // WHEN
274 blendedClipAnimator.setBlendTree(&blendRoot);
275
276 // THEN
277 QCOMPARE(arbiter.events.size(), 0);
278 QCOMPARE(arbiter.dirtyNodes.size(), 0);
279 }
280
281 }
282
283 void checkBlendTreeBookkeeping()
284 {
285 // GIVEN
286 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
287
288 {
289 // WHEN
290 Qt3DAnimation::QLerpClipBlend blendRoot;
291 blendedClipAnimator.setBlendTree(&blendRoot);
292
293 QCOMPARE(blendedClipAnimator.blendTree(), &blendRoot);
294 }
295
296 // THEN -> should not crash
297 QVERIFY(blendedClipAnimator.blendTree() == nullptr);
298 }
299
300 void checkChannelMapperUpdate()
301 {
302 // GIVEN
303 TestArbiter arbiter;
304 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
305 arbiter.setArbiterOnNode(&blendedClipAnimator);
306
307 Qt3DAnimation::QChannelMapper channelMapper;
308 {
309 // WHEN
310 blendedClipAnimator.setChannelMapper(&channelMapper);
311
312 // THEN
313 QCOMPARE(arbiter.events.size(), 0);
314 QCOMPARE(arbiter.dirtyNodes.size(), 1);
315 QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
316
317 arbiter.dirtyNodes.clear();
318 }
319
320 {
321 // WHEN
322 blendedClipAnimator.setChannelMapper(&channelMapper);
323
324 // THEN
325 QCOMPARE(arbiter.events.size(), 0);
326 QCOMPARE(arbiter.dirtyNodes.size(), 0);
327 }
328
329 }
330
331 void checkChannelMapperBookkeeping()
332 {
333 // GIVEN
334 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
335
336 {
337 // WHEN
338 Qt3DAnimation::QChannelMapper channelMapper;
339 blendedClipAnimator.setChannelMapper(&channelMapper);
340
341 QCOMPARE(blendedClipAnimator.channelMapper(), &channelMapper);
342 }
343
344 // THEN -> should not crash
345 QVERIFY(blendedClipAnimator.channelMapper() == nullptr);
346 }
347
348 void checkRunningUpdate()
349 {
350 // GIVEN
351 TestArbiter arbiter;
352 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
353 arbiter.setArbiterOnNode(&blendedClipAnimator);
354
355 {
356 // WHEN
357 blendedClipAnimator.setRunning(true);
358
359 // THEN
360 QCOMPARE(arbiter.events.size(), 0);
361 QCOMPARE(arbiter.dirtyNodes.size(), 1);
362 QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
363
364 arbiter.dirtyNodes.clear();
365 }
366
367 {
368 // WHEN
369 blendedClipAnimator.setRunning(true);
370
371 // THEN
372 QCOMPARE(arbiter.events.size(), 0);
373 QCOMPARE(arbiter.dirtyNodes.size(), 0);
374 }
375
376 }
377
378 void checkLoopsUpdate()
379 {
380 // GIVEN
381 TestArbiter arbiter;
382 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
383 arbiter.setArbiterOnNode(&blendedClipAnimator);
384
385 {
386 // WHEN
387 blendedClipAnimator.setLoopCount(1584);
388
389 // THEN
390 QCOMPARE(arbiter.events.size(), 0);
391 QCOMPARE(arbiter.dirtyNodes.size(), 1);
392 QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
393
394 arbiter.dirtyNodes.clear();
395 }
396
397 {
398 // WHEN
399 blendedClipAnimator.setLoopCount(1584);
400
401 // THEN
402 QCOMPARE(arbiter.events.size(), 0);
403 QCOMPARE(arbiter.dirtyNodes.size(), 0);
404 }
405
406 }
407
408 void checkNormalizedTimeUpdate()
409 {
410 // GIVEN
411 TestArbiter arbiter;
412 Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
413 arbiter.setArbiterOnNode(&blendedClipAnimator);
414
415 {
416 // WHEN
417 blendedClipAnimator.setNormalizedTime(0.5f);
418
419 // THEN
420 QCOMPARE(arbiter.events.size(), 0);
421 QCOMPARE(arbiter.dirtyNodes.size(), 1);
422 QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
423
424 arbiter.dirtyNodes.clear();
425 }
426
427 {
428 // WHEN
429 blendedClipAnimator.setNormalizedTime(0.5f);
430
431 // THEN
432 QCOMPARE(arbiter.events.size(), 0);
433 QCOMPARE(arbiter.dirtyNodes.size(), 0);
434 }
435
436 }
437};
438
439QTEST_MAIN(tst_QBlendedClipAnimator)
440
441#include "tst_qblendedclipanimator.moc"
442

source code of qt3d/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp