summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-06-28 11:39:25 +0100
committerSean Harmer <sean.harmer@kdab.com>2017-08-07 13:56:45 +0000
commitc402164bd09f4ab06db6173f490a036b60f83084 (patch)
tree815210c79346094ff3586be70dcf3e0fa5f7f703 /tests
parent71f0a11f0adbdf226f0821e2b79abaa370360748 (diff)
Add QSkeleton and QSkeletonLoader
They both inherit from QAbstractSkeleton which exists purely to provide a type for setting skeletons on the upcoming QArmature component. The classes relate in the same way as QAbstractAnimationClip, QAnimationClip and QAnimationClipLoader. The skeleton provides the joint hierarchy that can be animated and then used to skin a mesh via the upcoming QArmature component. Change-Id: I4be8ce3f1d6cbca4af08c5829b33172a2f951b11 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/core/core.pro4
-rw-r--r--tests/auto/core/qskeleton/qskeleton.pro11
-rw-r--r--tests/auto/core/qskeleton/tst_qskeleton.cpp169
-rw-r--r--tests/auto/core/qskeletonloader/qskeletonloader.pro12
-rw-r--r--tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp201
5 files changed, 396 insertions, 1 deletions
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
index 02af273aa..5cfc3e62d 100644
--- a/tests/auto/core/core.pro
+++ b/tests/auto/core/core.pro
@@ -13,7 +13,9 @@ SUBDIRS = \
qchangearbiter \
qscene \
qservicelocator \
- qjoint
+ qjoint \
+ qskeletonloader \
+ qskeleton
qtConfig(private_tests) {
SUBDIRS += \
diff --git a/tests/auto/core/qskeleton/qskeleton.pro b/tests/auto/core/qskeleton/qskeleton.pro
new file mode 100644
index 000000000..3bbb48a3c
--- /dev/null
+++ b/tests/auto/core/qskeleton/qskeleton.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_qskeleton
+
+QT += core-private 3dcore 3dcore-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qskeleton.cpp
+
+include(../common/common.pri)
diff --git a/tests/auto/core/qskeleton/tst_qskeleton.cpp b/tests/auto/core/qskeleton/tst_qskeleton.cpp
new file mode 100644
index 000000000..3d1758716
--- /dev/null
+++ b/tests/auto/core/qskeleton/tst_qskeleton.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DCore/qskeleton.h>
+#include <Qt3DCore/private/qskeleton_p.h>
+#include <Qt3DCore/qjoint.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qpropertynodeaddedchange.h>
+#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+
+#include "testpostmanarbiter.h"
+
+using namespace Qt3DCore;
+
+class tst_QSkeleton: public QObject
+{
+ Q_OBJECT
+public:
+ tst_QSkeleton()
+ {
+ qRegisterMetaType<Qt3DCore::QJoint*>();
+ }
+
+private Q_SLOTS:
+
+ void checkCreationChange_data()
+ {
+ QTest::addColumn<QSkeleton *>("skeleton");
+
+ QSkeleton *defaultConstructed = new QSkeleton();
+ QTest::newRow("defaultConstructed") << defaultConstructed;
+
+ QSkeleton *skeletonWithOneJoint = new QSkeleton();
+ skeletonWithOneJoint->setRootJoint(new QJoint());
+ QTest::newRow("skeletonWithOneJoint") << skeletonWithOneJoint;
+ }
+
+ void checkCreationChange()
+ {
+ // GIVEN
+ QFETCH(QSkeleton *, skeleton);
+
+ // WHEN
+ QNodeCreatedChangeGenerator creationChangeGenerator(skeleton);
+ QVector<QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges();
+
+ const int jointCount = skeleton->rootJoint() ? 1 : 0;
+
+ // THEN
+ QCOMPARE(creationChanges.size(), 1 + jointCount);
+
+ const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonData>>(creationChanges.first());
+ const QSkeletonData &data = creationChangeData->data;
+
+ // THEN
+ QCOMPARE(skeleton->id(), creationChangeData->subjectId());
+ QCOMPARE(skeleton->isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(skeleton->metaObject(), creationChangeData->metaObject());
+ if (skeleton->rootJoint()) {
+ QCOMPARE(skeleton->rootJoint()->id(), data.rootJointId);
+ }
+ }
+
+ void checkPropertyUpdates()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ QScopedPointer<QSkeleton> skeleton(new QSkeleton());
+ arbiter.setArbiterOnNode(skeleton.data());
+
+ // WHEN
+ QJoint *joint = new QJoint(skeleton.data());
+ QCoreApplication::processEvents();
+ arbiter.events.clear();
+
+ skeleton->setRootJoint(joint);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "rootJoint");
+ QCOMPARE(change->value().value<QNodeId>(), joint->id());
+ QCOMPARE(change->type(), PropertyUpdated);
+
+ arbiter.events.clear();
+
+ // WHEN
+ skeleton->setRootJoint(nullptr);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "rootJoint");
+ QCOMPARE(change->value().value<QNodeId>(), QNodeId());
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ void checkRootJointBookkeeping()
+ {
+ // GIVEN
+ QScopedPointer<QSkeleton> skeleton(new QSkeleton);
+ {
+ // WHEN
+ QJoint joint;
+ skeleton->setRootJoint(&joint);
+
+ // THEN
+ QCOMPARE(joint.parent(), skeleton.data());
+ QCOMPARE(skeleton->rootJoint(), &joint);
+ }
+ // THEN (Should not crash and parameter be unset)
+ QVERIFY(skeleton->rootJoint() == nullptr);
+
+ {
+ // WHEN
+ QSkeleton someOtherSkeleton;
+ QScopedPointer<QJoint> joint(new QJoint(&someOtherSkeleton));
+ skeleton->setRootJoint(joint.data());
+
+ // THEN
+ QCOMPARE(joint->parent(), &someOtherSkeleton);
+ QCOMPARE(skeleton->rootJoint(), joint.data());
+
+ // WHEN
+ skeleton.reset();
+ joint.reset();
+
+ // THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper)
+ }
+ }
+};
+
+QTEST_MAIN(tst_QSkeleton)
+
+#include "tst_qskeleton.moc"
diff --git a/tests/auto/core/qskeletonloader/qskeletonloader.pro b/tests/auto/core/qskeletonloader/qskeletonloader.pro
new file mode 100644
index 000000000..6172906c2
--- /dev/null
+++ b/tests/auto/core/qskeletonloader/qskeletonloader.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qskeletonloader
+
+QT += 3dcore 3dcore-private testlib
+
+CONFIG += testcase
+
+SOURCES += \
+ tst_qskeletonloader.cpp
+
+include(../common/common.pri)
diff --git a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
new file mode 100644
index 000000000..db643fc43
--- /dev/null
+++ b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <Qt3DCore/qskeletonloader.h>
+#include <Qt3DCore/private/qskeletonloader_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <testpostmanarbiter.h>
+
+using namespace Qt3DCore;
+
+class tst_QSkeletonLoader : public QSkeletonLoader
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ QSkeletonLoader skeleton;
+
+ // THEN
+ QCOMPARE(skeleton.source(), QUrl());
+ QCOMPARE(skeleton.status(), QSkeletonLoader::NotReady);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ QSkeletonLoader skeleton;
+
+ {
+ // WHEN
+ QSignalSpy spy(&skeleton, SIGNAL(sourceChanged(QUrl)));
+ const QUrl newValue(QStringLiteral("qrc:/zergling.skel"));
+ skeleton.setSource(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(skeleton.source(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ skeleton.setSource(newValue);
+
+ // THEN
+ QCOMPARE(skeleton.source(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ QSkeletonLoader skeleton;
+
+ skeleton.setSource(QUrl(QStringLiteral("http://someRemoteURL.com/dem-bones.skel")));
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ QNodeCreatedChangeGenerator creationChangeGenerator(&skeleton);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonLoaderData>>(creationChanges.first());
+ const QSkeletonLoaderData data = creationChangeData->data;
+
+ QCOMPARE(skeleton.id(), creationChangeData->subjectId());
+ QCOMPARE(skeleton.isEnabled(), true);
+ QCOMPARE(skeleton.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(skeleton.metaObject(), creationChangeData->metaObject());
+ QCOMPARE(skeleton.source(), data.source);
+ }
+
+ // WHEN
+ skeleton.setEnabled(false);
+
+ {
+ QNodeCreatedChangeGenerator creationChangeGenerator(&skeleton);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<QNodeCreatedChange<QSkeletonLoaderData>>(creationChanges.first());
+
+ QCOMPARE(skeleton.id(), creationChangeData->subjectId());
+ QCOMPARE(skeleton.isEnabled(), false);
+ QCOMPARE(skeleton.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(skeleton.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkSourceUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ QSkeletonLoader skeleton;
+ arbiter.setArbiterOnNode(&skeleton);
+
+ {
+ // WHEN
+ skeleton.setSource(QUrl(QStringLiteral("qrc:/hydralisk.skel")));
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "source");
+ QCOMPARE(change->type(), PropertyUpdated);
+
+ arbiter.events.clear();
+ }
+
+ {
+ // WHEN
+ skeleton.setSource(QStringLiteral("qrc:/hydralisk.skel"));
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ }
+
+ void checkStatusPropertyUpdate()
+ {
+ // GIVEN
+ qRegisterMetaType<Qt3DCore::QSkeletonLoader::Status>("Status");
+ TestArbiter arbiter;
+ arbiter.setArbiterOnNode(this);
+ QSignalSpy spy(this, SIGNAL(statusChanged(Status)));
+ const QSkeletonLoader::Status newStatus = QSkeletonLoader::Error;
+
+ // THEN
+ QVERIFY(spy.isValid());
+
+ // WHEN
+ QPropertyUpdatedChangePtr valueChange(new QPropertyUpdatedChange(QNodeId()));
+ valueChange->setPropertyName("status");
+ valueChange->setValue(QVariant::fromValue(newStatus));
+ sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(status(), newStatus);
+
+ // WHEN
+ spy.clear();
+ sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(status(), newStatus);
+ }
+};
+
+QTEST_MAIN(tst_QSkeletonLoader)
+
+#include "tst_qskeletonloader.moc"