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/qskeleton.h>
32#include <Qt3DAnimation/private/skeleton_p.h>
33#include <Qt3DAnimation/private/handler_p.h>
34#include <Qt3DCore/private/qscene_p.h>
35#include <Qt3DCore/private/qbackendnode_p.h>
36#include <qbackendnodetester.h>
37#include <testpostmanarbiter.h>
38
39using namespace Qt3DCore;
40using namespace Qt3DAnimation;
41using namespace Qt3DAnimation::Animation;
42
43Q_DECLARE_METATYPE(Skeleton*)
44
45class tst_Skeleton : public QBackendNodeTester
46{
47 Q_OBJECT
48
49private Q_SLOTS:
50 void checkPeerPropertyMirroring()
51 {
52 // GIVEN
53 Handler handler;
54 Skeleton backendSkeleton;
55 backendSkeleton.setHandler(&handler);
56 QSkeleton skeleton;
57 auto rootJoint = new QJoint();
58 rootJoint->setName(QLatin1String("rootJoint"));
59 auto childJoint = new QJoint();
60 childJoint->setName(QLatin1String("childJoint"));
61 rootJoint->addChildJoint(joint: childJoint);
62 skeleton.setRootJoint(rootJoint);
63
64 // WHEN
65 simulateInitializationSync(frontend: &skeleton, backend: &backendSkeleton);
66
67 // THEN - nothing mirrored from frontend
68 QCOMPARE(backendSkeleton.peerId(), skeleton.id());
69 QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled());
70 QCOMPARE(backendSkeleton.jointNames().size(), 0);
71 QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0);
72 }
73
74 void checkJointName()
75 {
76 // GIVEN
77 Skeleton backendSkeleton;
78 const QVector<QString> jointNames = { QLatin1String("rootJoint"),
79 QLatin1String("child1Joint"),
80 QLatin1String("child2Joint") };
81
82 // WHEN
83 backendSkeleton.setJointNames(jointNames);
84
85 // THEN
86 const int jointNameCount = jointNames.size();
87 for (int i = 0; i < jointNameCount; ++i) {
88 QCOMPARE(jointNames[i], backendSkeleton.jointName(i));
89 }
90 }
91
92 void checkInitialAndCleanedUpState()
93 {
94 // GIVEN
95 Handler handler;
96 Skeleton backendSkeleton;
97 backendSkeleton.setHandler(&handler);
98
99 // THEN
100 QVERIFY(backendSkeleton.peerId().isNull());
101 QCOMPARE(backendSkeleton.isEnabled(), false);
102 QCOMPARE(backendSkeleton.jointNames().size(), 0);
103 QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0);
104
105 // GIVEN
106 const QVector<QString> names = (QVector<QString>()
107 << QLatin1String("root")
108 << QLatin1String("child1")
109 << QLatin1String("child2"));
110 const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt());
111
112 // WHEN
113 backendSkeleton.setJointNames(names);
114 backendSkeleton.setJointLocalPoses(localPoses);
115 backendSkeleton.cleanup();
116
117 // THEN
118 QCOMPARE(backendSkeleton.isEnabled(), false);
119 QCOMPARE(backendSkeleton.jointNames().size(), 0);
120 QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0);
121 }
122
123 void checkPropertyChanges()
124 {
125 // GIVEN
126 Handler handler;
127 Skeleton backendSkeleton;
128 backendSkeleton.setHandler(&handler);
129 QSkeleton skeleton;
130 simulateInitializationSync(frontend: &skeleton, backend: &backendSkeleton);
131
132 // WHEN
133 skeleton.setEnabled(false);
134 backendSkeleton.syncFromFrontEnd(frontEnd: &skeleton, firstTime: false);
135
136 // THEN
137 QCOMPARE(backendSkeleton.isEnabled(), false);
138 }
139
140 void checkJointTransforms_data()
141 {
142 QTest::addColumn<Skeleton*>(name: "skeleton");
143 QTest::addColumn<QVector<Sqt>>(name: "jointTransforms");
144
145 const int count = 5;
146 auto skeleton = new Skeleton;
147 skeleton->setJointCount(count);
148 QVector<Sqt> jointTransforms;
149 jointTransforms.reserve(asize: count);
150 for (int i = 0; i < count; ++i) {
151 const float f = float(i);
152 Sqt transform;
153 transform.scale = QVector3D(f, f, f);
154 transform.rotation = QQuaternion(f, 1.0f, 0.0f, 0.0f).normalized();
155 transform.translation = QVector3D(1.0 * f, 2.0 * f, 3.0 * f);
156 skeleton->setJointScale(jointIndex: i, scale: transform.scale);
157 skeleton->setJointRotation(jointIndex: i, rotation: transform.rotation);
158 skeleton->setJointTranslation(jointIndex: i, translation: transform.translation);
159 jointTransforms.push_back(t: transform);
160 }
161
162 QTest::newRow(dataTag: "5 joints") << skeleton << jointTransforms;
163 }
164
165 void checkJointTransforms()
166 {
167 // GIVEN
168 QFETCH(Skeleton*, skeleton);
169 QFETCH(QVector<Sqt>, jointTransforms);
170
171 const int count = skeleton->jointCount();
172 for (int i = 0; i < count; ++i) {
173 // WHEN
174 const QVector3D s = skeleton->jointScale(jointIndex: i);
175
176 // THEN
177 QCOMPARE(s, jointTransforms[i].scale);
178
179 // WHEN
180 const QQuaternion q = skeleton->jointRotation(jointIndex: i);
181
182 // THEN
183 QCOMPARE(q, jointTransforms[i].rotation);
184
185 // WHEN
186 const QVector3D t = skeleton->jointTranslation(jointIndex: i);
187
188 // THEN
189 QCOMPARE(t, jointTransforms[i].translation);
190 }
191
192 // Cleanup
193 delete skeleton;
194 }
195};
196
197QTEST_APPLESS_MAIN(tst_Skeleton)
198
199#include "tst_skeleton.moc"
200

source code of qt3d/tests/auto/animation/skeleton/tst_skeleton.cpp