1/****************************************************************************
2**
3** Copyright (C) 2017 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
30#include <QtTest/QTest>
31#include <Qt3DAnimation/qclipblendvalue.h>
32#include <Qt3DAnimation/qanimationcliploader.h>
33#include <Qt3DAnimation/private/qclipblendvalue_p.h>
34#include <Qt3DAnimation/private/clipblendvalue_p.h>
35#include "qbackendnodetester.h"
36
37#include <random>
38#include <algorithm>
39
40using namespace Qt3DAnimation::Animation;
41
42Q_DECLARE_METATYPE(ClipBlendValue *)
43Q_DECLARE_METATYPE(QVector<ClipFormat>)
44
45class tst_ClipBlendValue : public Qt3DCore::QBackendNodeTester
46{
47 Q_OBJECT
48public:
49 AnimationClip *createAnimationClipLoader(Handler *handler,
50 double duration)
51 {
52 auto clipId = Qt3DCore::QNodeId::createId();
53 AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(id: clipId);
54 setPeerId(backend: clip, id: clipId);
55 clip->setDuration(duration);
56 return clip;
57 }
58
59private Q_SLOTS:
60 void checkInitialState()
61 {
62 // GIVEN
63 ClipBlendValue backendClipBlendValue;
64
65 // THEN
66 QCOMPARE(backendClipBlendValue.isEnabled(), false);
67 QVERIFY(backendClipBlendValue.peerId().isNull());
68 QCOMPARE(backendClipBlendValue.clipId(), Qt3DCore::QNodeId());
69 QCOMPARE(backendClipBlendValue.blendType(), ClipBlendNode::ValueType);
70 }
71
72 void checkInitializeFromPeer()
73 {
74 // GIVEN
75 Qt3DAnimation::QClipBlendValue clipBlendValue;
76 Qt3DAnimation::QAnimationClipLoader clip;
77 clipBlendValue.setClip(&clip);
78
79 {
80 // WHEN
81 ClipBlendValue backendClipBlendValue;
82 simulateInitializationSync(frontend: &clipBlendValue, backend: &backendClipBlendValue);
83
84 // THEN
85 QCOMPARE(backendClipBlendValue.isEnabled(), true);
86 QCOMPARE(backendClipBlendValue.peerId(), clipBlendValue.id());
87 QCOMPARE(backendClipBlendValue.clipId(), clip.id());
88 }
89 {
90 // WHEN
91 ClipBlendValue backendClipBlendValue;
92 clipBlendValue.setEnabled(false);
93 simulateInitializationSync(frontend: &clipBlendValue, backend: &backendClipBlendValue);
94
95 // THEN
96 QCOMPARE(backendClipBlendValue.peerId(), clipBlendValue.id());
97 QCOMPARE(backendClipBlendValue.isEnabled(), false);
98 }
99 }
100
101 void checkSceneChangeEvents()
102 {
103 // GIVEN
104 Qt3DAnimation::QClipBlendValue clipBlendValue;
105 ClipBlendValue backendClipBlendValue;
106 simulateInitializationSync(frontend: &clipBlendValue, backend: &backendClipBlendValue);
107 {
108 // WHEN
109 const bool newValue = false;
110 clipBlendValue.setEnabled(newValue);
111 backendClipBlendValue.syncFromFrontEnd(frontEnd: &clipBlendValue, firstTime: false);
112
113 // THEN
114 QCOMPARE(backendClipBlendValue.isEnabled(), newValue);
115 }
116 {
117 // WHEN
118 Qt3DAnimation::QAnimationClipLoader newValue;
119 clipBlendValue.setClip(&newValue);
120 backendClipBlendValue.syncFromFrontEnd(frontEnd: &clipBlendValue, firstTime: false);
121
122 // THEN
123 QCOMPARE(backendClipBlendValue.clipId(), newValue.id());
124 }
125 }
126
127 void checkDependencyIds()
128 {
129 // GIVEN
130 ClipBlendValue clipNode;
131 auto clipId = Qt3DCore::QNodeId::createId();
132
133 // WHEN
134 clipNode.setClipId(clipId);
135 QVector<Qt3DCore::QNodeId> actualIds = clipNode.currentDependencyIds();
136
137 // THEN
138 QCOMPARE(actualIds.size(), 0);
139
140 // WHEN
141 auto anotherClipId = Qt3DCore::QNodeId::createId();
142 clipNode.setClipId(anotherClipId);
143 actualIds = clipNode.currentDependencyIds();
144
145 // THEN
146 QCOMPARE(actualIds.size(), 0);
147 }
148
149 void checkDuration()
150 {
151 // GIVEN
152 auto handler = new Handler();
153 const double expectedDuration = 123.5;
154 auto clip = createAnimationClipLoader(handler, duration: expectedDuration);
155 ClipBlendValue clipNode;
156 clipNode.setHandler(handler);
157 clipNode.setClipBlendNodeManager(handler->clipBlendNodeManager());
158 clipNode.setClipId(clip->peerId());
159
160 // WHEN
161 double actualDuration = clipNode.duration();
162
163 // THEN
164 QCOMPARE(actualDuration, expectedDuration);
165 }
166
167 void checkFormatIndices_data()
168 {
169 QTest::addColumn<ClipBlendValue *>(name: "blendNode");
170 QTest::addColumn<QVector<int>>(name: "indexes");
171 QTest::addColumn<QVector<Qt3DCore::QNodeId>>(name: "animatorIds");
172 QTest::addColumn<QVector<ClipFormat>>(name: "expectedClipFormat");
173
174 // Single entry
175 {
176 auto blendNode = new ClipBlendValue;
177 QVector<Qt3DCore::QNodeId> animatorIds;
178 QVector<ClipFormat> expectedClipFormat;
179
180 const auto animatorId = Qt3DCore::QNodeId::createId();
181 animatorIds.push_back(t: animatorId);
182
183 ClipFormat clipFormat;
184 clipFormat.sourceClipIndices = { 0, 1, 2 };
185 expectedClipFormat.push_back(t: clipFormat);
186
187 // Set data and indexes
188 blendNode->setClipFormat(animatorId, formatIndices: clipFormat);
189 QVector<int> indexes = QVector<int>() << 0;
190
191 QTest::newRow(dataTag: "single entry")
192 << blendNode << indexes << animatorIds << expectedClipFormat;
193 }
194
195 // Multiple entries, ordered
196 {
197 auto blendNode = new ClipBlendValue;
198 QVector<Qt3DCore::QNodeId> animatorIds;
199 QVector<ClipFormat> expectedClipFormat;
200
201 const int animatorCount = 10;
202 for (int j = 0; j < animatorCount; ++j) {
203 auto animatorId = Qt3DCore::QNodeId::createId();
204 animatorIds.push_back(t: animatorId);
205
206 ClipFormat clipFormat;
207 for (int i = 0; i < j + 5; ++i)
208 clipFormat.sourceClipIndices.push_back(t: i + j);
209 expectedClipFormat.push_back(t: clipFormat);
210
211 blendNode->setClipFormat(animatorId, formatIndices: clipFormat);
212 }
213
214 QVector<int> indexes(animatorCount);
215 std::iota(first: indexes.begin(), last: indexes.end(), value: 0);
216
217 QTest::newRow(dataTag: "multiple entries, ordered")
218 << blendNode << indexes << animatorIds << expectedClipFormat;
219 }
220
221 // Multiple entries, unordered
222 {
223 auto blendNode = new ClipBlendValue;
224 QVector<Qt3DCore::QNodeId> animatorIds;
225 QVector<ClipFormat> expectedClipFormat;
226
227 const int animatorCount = 10;
228 for (int j = 0; j < animatorCount; ++j) {
229 auto animatorId = Qt3DCore::QNodeId::createId();
230 animatorIds.push_back(t: animatorId);
231
232 ClipFormat clipFormat;
233 for (int i = 0; i < j + 5; ++i)
234 clipFormat.sourceClipIndices.push_back(t: i + j);
235 expectedClipFormat.push_back(t: clipFormat);
236
237 blendNode->setClipFormat(animatorId, formatIndices: clipFormat);
238 }
239
240 // Shuffle the animatorIds to randomise the lookups
241 QVector<int> indexes(animatorCount);
242 std::iota(first: indexes.begin(), last: indexes.end(), value: 0);
243 std::random_device rd;
244 std::mt19937 generator(rd());
245 std::shuffle(first: indexes.begin(), last: indexes.end(), g&: generator);
246
247 QTest::newRow(dataTag: "multiple entries, unordered")
248 << blendNode << indexes << animatorIds << expectedClipFormat;
249 }
250 }
251
252 void checkFormatIndices()
253 {
254 // GIVEN
255 QFETCH(ClipBlendValue *, blendNode);
256 QFETCH(QVector<int>, indexes);
257 QFETCH(QVector<Qt3DCore::QNodeId>, animatorIds);
258 QFETCH(QVector<ClipFormat>, expectedClipFormat);
259
260 for (int i = 0; i < indexes.size(); ++i) {
261 // WHEN
262 const int index = indexes[i];
263 const ClipFormat actualClipFormat = blendNode->clipFormat(animatorId: animatorIds[index]);
264
265 // THEN
266 QCOMPARE(actualClipFormat.sourceClipIndices.size(), expectedClipFormat[index].sourceClipIndices.size());
267 for (int j = 0; j < actualClipFormat.sourceClipIndices.size(); ++j)
268 QCOMPARE(actualClipFormat.sourceClipIndices[j], expectedClipFormat[index].sourceClipIndices[j]);
269 }
270
271 delete blendNode;
272 }
273};
274
275QTEST_MAIN(tst_ClipBlendValue)
276
277#include "tst_clipblendvalue.moc"
278

source code of qt3d/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp