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 <Qt3DAnimation/qanimationcliploader.h> |
31 | #include <Qt3DAnimation/qclipanimator.h> |
32 | #include <Qt3DAnimation/qchannelmapper.h> |
33 | #include <Qt3DAnimation/qchannelmapping.h> |
34 | #include <Qt3DAnimation/private/clipanimator_p.h> |
35 | #include <Qt3DAnimation/private/channelmapper_p.h> |
36 | #include <Qt3DAnimation/private/channelmapping_p.h> |
37 | #include <Qt3DAnimation/private/findrunningclipanimatorsjob_p.h> |
38 | #include <Qt3DAnimation/private/handler_p.h> |
39 | #include <Qt3DAnimation/private/managers_p.h> |
40 | #include <Qt3DCore/private/qnode_p.h> |
41 | #include <Qt3DCore/private/qscene_p.h> |
42 | #include <Qt3DCore/private/qbackendnode_p.h> |
43 | #include <qbackendnodetester.h> |
44 | #include <testpostmanarbiter.h> |
45 | |
46 | using namespace Qt3DAnimation::Animation; |
47 | |
48 | Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) |
49 | Q_DECLARE_METATYPE(QVector<Qt3DAnimation::Animation::HClipAnimator>) |
50 | |
51 | typedef QHash<ClipAnimator*, QVector<Qt3DAnimation::Animation::MappingData>> MappingDataResults; |
52 | Q_DECLARE_METATYPE(MappingDataResults) |
53 | |
54 | class tst_FindRunningClipAnimatorsJob: public Qt3DCore::QBackendNodeTester |
55 | { |
56 | Q_OBJECT |
57 | public: |
58 | ChannelMapping *createChannelMapping(Handler *handler, |
59 | const QString &channelName, |
60 | const Qt3DCore::QNodeId targetId, |
61 | const char *propertyName, |
62 | int type, |
63 | int componentCount) |
64 | { |
65 | auto channelMappingId = Qt3DCore::QNodeId::createId(); |
66 | ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(id: channelMappingId); |
67 | setPeerId(backend: channelMapping, id: channelMappingId); |
68 | channelMapping->setHandler(handler); |
69 | channelMapping->setTargetId(targetId); |
70 | channelMapping->setPropertyName(propertyName); |
71 | channelMapping->setChannelName(channelName); |
72 | channelMapping->setType(type); |
73 | channelMapping->setComponentCount(componentCount); |
74 | channelMapping->setMappingType(ChannelMapping::ChannelMappingType); |
75 | return channelMapping; |
76 | } |
77 | |
78 | ChannelMapper *createChannelMapper(Handler *handler, |
79 | const QVector<Qt3DCore::QNodeId> &mappingIds) |
80 | { |
81 | auto channelMapperId = Qt3DCore::QNodeId::createId(); |
82 | ChannelMapper *channelMapper = handler->channelMapperManager()->getOrCreateResource(id: channelMapperId); |
83 | setPeerId(backend: channelMapper, id: channelMapperId); |
84 | channelMapper->setHandler(handler); |
85 | channelMapper->setMappingIds(mappingIds); |
86 | return channelMapper; |
87 | } |
88 | |
89 | AnimationClip *createAnimationClipLoader(Handler *handler, |
90 | const QUrl &source) |
91 | { |
92 | auto clipId = Qt3DCore::QNodeId::createId(); |
93 | AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(id: clipId); |
94 | setPeerId(backend: clip, id: clipId); |
95 | clip->setHandler(handler); |
96 | clip->setDataType(AnimationClip::File); |
97 | clip->setSource(source); |
98 | clip->loadAnimation(); |
99 | return clip; |
100 | } |
101 | |
102 | ClipAnimator *createClipAnimator(Handler *handler, |
103 | qint64 globalStartTimeNS, |
104 | int loops) |
105 | { |
106 | auto animatorId = Qt3DCore::QNodeId::createId(); |
107 | ClipAnimator *animator = handler->clipAnimatorManager()->getOrCreateResource(id: animatorId); |
108 | setPeerId(backend: animator, id: animatorId); |
109 | animator->setHandler(handler); |
110 | animator->setStartTime(globalStartTimeNS); |
111 | animator->setLoops(loops); |
112 | return animator; |
113 | } |
114 | |
115 | private Q_SLOTS: |
116 | void checkJob_data() |
117 | { |
118 | QTest::addColumn<Handler *>(name: "handler" ); |
119 | QTest::addColumn<QVector<HClipAnimator>>(name: "dirtyClipAnimators" ); |
120 | QTest::addColumn<MappingDataResults>(name: "expectedResults" ); |
121 | |
122 | |
123 | { |
124 | Handler *handler; |
125 | AnimationClip *clip; |
126 | ClipAnimator *animator; |
127 | QVector<HClipAnimator> dirtyClipAnimators; |
128 | ChannelMapper *channelMapper; |
129 | MappingDataResults expectedResults; |
130 | handler = new Handler(); |
131 | clip = createAnimationClipLoader(handler, source: QUrl("qrc:/clip1.json" )); |
132 | |
133 | const qint64 globalStartTimeNS = 0; |
134 | const int loops = 1; |
135 | animator = createClipAnimator(handler, globalStartTimeNS, loops); |
136 | animator->setClipId(clip->peerId()); |
137 | dirtyClipAnimators = (QVector<HClipAnimator>() |
138 | << handler->clipAnimatorManager()->getOrAcquireHandle(id: animator->peerId())); |
139 | |
140 | auto channelMapping = createChannelMapping(handler, |
141 | channelName: QLatin1String("Location" ), |
142 | targetId: Qt3DCore::QNodeId::createId(), |
143 | propertyName: "translation" , |
144 | type: static_cast<int>(QVariant::Vector3D), |
145 | componentCount: 3); |
146 | QVector<ChannelMapping *> channelMappings; |
147 | channelMappings.push_back(t: channelMapping); |
148 | |
149 | channelMapper = createChannelMapper(handler, mappingIds: QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); |
150 | animator->setMapperId(channelMapper->peerId()); |
151 | animator->setRunning(true); // Has to be marked as running for the job to process it |
152 | animator->setEnabled(true); // Has to be marked as enabled for the job to process it |
153 | |
154 | const ComponentIndices locationIndices = { 0, 1, 2 }; |
155 | MappingData expectedMapping; |
156 | expectedMapping.targetId = channelMapping->targetId(); |
157 | expectedMapping.propertyName = channelMapping->propertyName(); |
158 | expectedMapping.type = channelMapping->type(); |
159 | expectedMapping.channelIndices = locationIndices; |
160 | expectedResults.insert(akey: animator, avalue: QVector<MappingData>() << expectedMapping); |
161 | |
162 | QTest::newRow(dataTag: "single mapping" ) |
163 | << handler |
164 | << dirtyClipAnimators |
165 | << expectedResults; |
166 | } |
167 | |
168 | { |
169 | Handler *handler; |
170 | AnimationClip *clip; |
171 | ClipAnimator *animator; |
172 | QVector<HClipAnimator> dirtyClipAnimators; |
173 | ChannelMapper *channelMapper; |
174 | MappingDataResults expectedResults; |
175 | handler = new Handler(); |
176 | clip = createAnimationClipLoader(handler, source: QUrl("qrc:/clip1.json" )); |
177 | |
178 | const qint64 globalStartTimeNS = 0; |
179 | const int loops = 1; |
180 | animator = createClipAnimator(handler, globalStartTimeNS, loops); |
181 | animator->setClipId(clip->peerId()); |
182 | dirtyClipAnimators = (QVector<HClipAnimator>() |
183 | << handler->clipAnimatorManager()->getOrAcquireHandle(id: animator->peerId())); |
184 | |
185 | auto channelMapping = createChannelMapping(handler, |
186 | channelName: QLatin1String("Location" ), |
187 | targetId: Qt3DCore::QNodeId::createId(), |
188 | propertyName: "translation" , |
189 | type: static_cast<int>(QVariant::Vector3D), |
190 | componentCount: 3); |
191 | QVector<ChannelMapping *> channelMappings; |
192 | channelMappings.push_back(t: channelMapping); |
193 | |
194 | channelMapper = createChannelMapper(handler, mappingIds: QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); |
195 | animator->setMapperId(channelMapper->peerId()); |
196 | animator->setRunning(true); // Has to be marked as running for the job to process it |
197 | animator->setEnabled(false); // Has to be marked as enabled for the job to process it |
198 | |
199 | QTest::newRow(dataTag: "disabled animator" ) |
200 | << handler |
201 | << dirtyClipAnimators |
202 | << expectedResults; |
203 | } |
204 | } |
205 | |
206 | void checkJob() |
207 | { |
208 | // GIVEN |
209 | QFETCH(Handler *, handler); |
210 | QFETCH(QVector<HClipAnimator>, dirtyClipAnimators); |
211 | QFETCH(MappingDataResults, expectedResults); |
212 | FindRunningClipAnimatorsJob job; |
213 | |
214 | // WHEN |
215 | job.setHandler(handler); |
216 | job.setDirtyClipAnimators(dirtyClipAnimators); |
217 | job.run(); |
218 | |
219 | // THEN - check the resulting MappingData on the animator matches the expected results |
220 | for (const auto &dirtyClipAnimator : dirtyClipAnimators) { |
221 | const auto animator = handler->clipAnimatorManager()->data(handle: dirtyClipAnimator); |
222 | const QVector<MappingData> actualMappingData = animator->mappingData(); |
223 | const QVector<MappingData> expectedMappingData = expectedResults[animator]; |
224 | |
225 | QCOMPARE(expectedMappingData.size(), actualMappingData.size()); |
226 | for (int i = 0; i < actualMappingData.size(); ++i) { |
227 | QCOMPARE(expectedMappingData[i].targetId, actualMappingData[i].targetId); |
228 | QCOMPARE(expectedMappingData[i].type, actualMappingData[i].type); |
229 | QVERIFY(qstrcmp(expectedMappingData[i].propertyName, actualMappingData[i].propertyName) == 0); |
230 | QCOMPARE(expectedMappingData[i].channelIndices.size(), actualMappingData[i].channelIndices.size()); |
231 | |
232 | for (int j = 0; j < actualMappingData[i].channelIndices.size(); ++j) { |
233 | QCOMPARE(expectedMappingData[i].channelIndices[j], actualMappingData[i].channelIndices[j]); |
234 | } |
235 | } |
236 | } |
237 | } |
238 | }; |
239 | |
240 | QTEST_APPLESS_MAIN(tst_FindRunningClipAnimatorsJob) |
241 | |
242 | #include "tst_findrunningclipanimatorsjob.moc" |
243 | |