summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/core/transforms/qabstractskeleton.cpp92
-rw-r--r--src/core/transforms/qabstractskeleton.h70
-rw-r--r--src/core/transforms/qabstractskeleton_p.h73
-rw-r--r--src/core/transforms/qskeleton.cpp150
-rw-r--r--src/core/transforms/qskeleton.h79
-rw-r--r--src/core/transforms/qskeleton_p.h81
-rw-r--r--src/core/transforms/qskeletonloader.cpp202
-rw-r--r--src/core/transforms/qskeletonloader.h95
-rw-r--r--src/core/transforms/qskeletonloader_p.h83
-rw-r--r--src/core/transforms/transforms.pri13
-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
15 files changed, 1332 insertions, 3 deletions
diff --git a/src/core/transforms/qabstractskeleton.cpp b/src/core/transforms/qabstractskeleton.cpp
new file mode 100644
index 000000000..5a92233d9
--- /dev/null
+++ b/src/core/transforms/qabstractskeleton.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractskeleton.h"
+#include "qabstractskeleton_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QAbstractSkeletonPrivate::QAbstractSkeletonPrivate()
+ : Qt3DCore::QNodePrivate()
+{
+}
+
+/*!
+ \qmltype AbstractSkeleton
+ \inqmlmodule Qt3D.Core
+ \inherits Node
+ \instantiates Qt3DCore::QAbstractSkeleton
+ \since 5.10
+ \brief A skeleton contains the joints for a skinned mesh
+
+ Do not use this class directly. You should use SkeletonLoader if loading
+ skeleton data from a file (most likely) or Skeleton if creating the
+ skeleton and skinned mesh data yourself (mainly for people creating
+ editors or tooling).
+*/
+
+/*!
+ \class Qt3DCore::QAbstractSkeleton
+ \inmodule Qt3DCore
+ \inherits Qt3DCore::QNode
+ \since 5.10
+ \brief A skeleton contains the joints for a skinned mesh
+
+ Do not use this class directly. You should use QSkeletonLoader if loading
+ skeleton data from a file (most likely) or QSkeleton if creating the
+ skeleton and skinned mesh data yourself (mainly for people creating
+ editors or tooling).
+*/
+
+/*! \internal */
+QAbstractSkeleton::QAbstractSkeleton(QAbstractSkeletonPrivate &dd, Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(dd, parent)
+{
+}
+
+/*! \internal */
+QAbstractSkeleton::~QAbstractSkeleton()
+{
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
diff --git a/src/core/transforms/qabstractskeleton.h b/src/core/transforms/qabstractskeleton.h
new file mode 100644
index 000000000..3dbf37bed
--- /dev/null
+++ b/src/core/transforms/qabstractskeleton.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QABSTRACTSKELETON_H
+#define QT3DCORE_QABSTRACTSKELETON_H
+
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/qt3dcore_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QAbstractSkeletonPrivate;
+
+class QT3DCORESHARED_EXPORT QAbstractSkeleton : public Qt3DCore::QNode
+{
+ Q_OBJECT
+
+public:
+ ~QAbstractSkeleton();
+
+protected:
+ QAbstractSkeleton(QAbstractSkeletonPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractSkeleton)
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QABSTRACTSKELETON_H
diff --git a/src/core/transforms/qabstractskeleton_p.h b/src/core/transforms/qabstractskeleton_p.h
new file mode 100644
index 000000000..fa2af34d7
--- /dev/null
+++ b/src/core/transforms/qabstractskeleton_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QABSTRACTSKELETON_P_H
+#define QT3DCORE_QABSTRACTSKELETON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QAbstractSkeletonPrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ QAbstractSkeletonPrivate();
+
+ Q_DECLARE_PUBLIC(QAbstractSkeleton)
+};
+
+} // namespace Qt3DCore
+
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QABSTRACTSKELETON_P_H
diff --git a/src/core/transforms/qskeleton.cpp b/src/core/transforms/qskeleton.cpp
new file mode 100644
index 000000000..b4c4734e0
--- /dev/null
+++ b/src/core/transforms/qskeleton.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qskeleton.h"
+#include "qskeleton_p.h"
+#include <Qt3DCore/qjoint.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QSkeletonPrivate::QSkeletonPrivate()
+ : QAbstractSkeletonPrivate()
+ , m_rootJoint(nullptr)
+{
+}
+
+/*!
+ \qmltype Skeleton
+ \inqmlmodule Qt3D.Core
+ \inherits AbstractSkeleton
+ \instantiates Qt3DCore::QSkeleton
+ \since 5.10
+ \brief Holds the data for a skeleton to be used with skinned meshes
+
+ Use Skeleton if you wish to manually create the joints of a skeleton for
+ use with skinned meshes. This is mainly of use to people creating editors,
+ tooling, or dynamic skeletons. It is more common that a Qt 3D application
+ would simply consume an existing skeleton and skinned mesh as created in
+ a digital content creation tool such as Blender. For this use case, please
+ see SkeletonLoader.
+*/
+
+/*!
+ \qmlproperty Joint Skeleton::rootJoint
+
+ Holds the root joint of the hierarchy of joints forming the skeleton.
+*/
+
+/*!
+ \class Qt3DCore::QSkeleton
+ \inmodule Qt3DCore
+ \inherits Qt3DCore::QAbstractSkeleton
+ \since 5.10
+ \brief Holds the data for a skeleton to be used with skinned meshes
+
+ Use QSkeleton if you wish to manually create the joints of a skeleton for
+ use with skinned meshes. This is mainly of use to people creating editors,
+ tooling, or dynamic skeletons. It is more common that a Qt 3D application
+ would simply consume an existing skeleton and skinned mesh as created in
+ a digital content creation tool such as Blender. For this use case, please
+ see QSkeletonLoader.
+*/
+
+/*!
+ Constructs a new QSkeleton with \a parent.
+*/
+QSkeleton::QSkeleton(Qt3DCore::QNode *parent)
+ : QAbstractSkeleton(*new QSkeletonPrivate, parent)
+{
+}
+
+/*! \internal */
+QSkeleton::~QSkeleton()
+{
+}
+
+/*!
+ \property Qt3DCore::QSkeleton::rootJoint
+
+ Holds the root joint of the hierarchy of joints forming the skeleton.
+*/
+Qt3DCore::QJoint *QSkeleton::rootJoint() const
+{
+ Q_D(const QSkeleton);
+ return d->m_rootJoint;
+}
+
+void QSkeleton::setRootJoint(Qt3DCore::QJoint *rootJoint)
+{
+ Q_D(QSkeleton);
+ if (d->m_rootJoint != rootJoint) {
+ if (d->m_rootJoint)
+ d->unregisterDestructionHelper(d->m_rootJoint);
+
+ // We need to add it as a child of the current node if it has been declared inline
+ // Or not previously added as a child of the current node so that
+ // 1) The backend gets notified about it's creation
+ // 2) When the current node is destroyed, it gets destroyed as well
+ if (rootJoint && !rootJoint->parent())
+ rootJoint->setParent(this);
+ d->m_rootJoint = rootJoint;
+
+ // Ensures proper bookkeeping
+ if (d->m_rootJoint)
+ d->registerDestructionHelper(d->m_rootJoint, &QSkeleton::setRootJoint, d->m_rootJoint);
+
+ emit rootJointChanged(rootJoint);
+ }
+}
+
+/*! \internal */
+Qt3DCore::QNodeCreatedChangeBasePtr QSkeleton::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QSkeletonData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QSkeleton);
+ data.rootJointId = qIdForNode(d->m_rootJoint);
+ return creationChange;
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
diff --git a/src/core/transforms/qskeleton.h b/src/core/transforms/qskeleton.h
new file mode 100644
index 000000000..e3c0c9194
--- /dev/null
+++ b/src/core/transforms/qskeleton.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QSKELETON_H
+#define QT3DCORE_QSKELETON_H
+
+#include <Qt3DCore/qabstractskeleton.h>
+#include <Qt3DCore/qt3dcore_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QJoint;
+class QSkeletonPrivate;
+
+class QT3DCORESHARED_EXPORT QSkeleton : public QAbstractSkeleton
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DCore::QJoint* rootJoint READ rootJoint WRITE setRootJoint NOTIFY rootJointChanged)
+
+public:
+ QSkeleton(Qt3DCore::QNode *parent = nullptr);
+ ~QSkeleton();
+
+ Qt3DCore::QJoint *rootJoint() const;
+
+public Q_SLOTS:
+ void setRootJoint(Qt3DCore::QJoint *rootJoint);
+
+Q_SIGNALS:
+ void rootJointChanged(Qt3DCore::QJoint *rootJoint);
+
+private:
+ Q_DECLARE_PRIVATE(QSkeleton)
+ QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QSKELETON_H
diff --git a/src/core/transforms/qskeleton_p.h b/src/core/transforms/qskeleton_p.h
new file mode 100644
index 000000000..8f36af78d
--- /dev/null
+++ b/src/core/transforms/qskeleton_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QSKELETON_P_H
+#define QT3DCORE_QSKELETON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qabstractskeleton_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QJoint;
+
+class QSkeletonPrivate : public QAbstractSkeletonPrivate
+{
+public:
+ QSkeletonPrivate();
+
+ Q_DECLARE_PUBLIC(QSkeleton)
+
+ QJoint *m_rootJoint;
+};
+
+struct QSkeletonData
+{
+ QNodeId rootJointId;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QSKELETON_P_H
diff --git a/src/core/transforms/qskeletonloader.cpp b/src/core/transforms/qskeletonloader.cpp
new file mode 100644
index 000000000..e4dd37095
--- /dev/null
+++ b/src/core/transforms/qskeletonloader.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qskeletonloader.h"
+#include "qskeletonloader_p.h"
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+QSkeletonLoaderPrivate::QSkeletonLoaderPrivate()
+ : QAbstractSkeletonPrivate()
+ , m_source()
+ , m_status(QSkeletonLoader::NotReady)
+{
+}
+
+void QSkeletonLoaderPrivate::setStatus(QSkeletonLoader::Status status)
+{
+ Q_Q(QSkeletonLoader);
+ if (status != m_status) {
+ m_status = status;
+ const bool blocked = q->blockNotifications(true);
+ emit q->statusChanged(m_status);
+ q->blockNotifications(blocked);
+ }
+}
+
+/*!
+ \qmltype SkeletonLoader
+ \inqmlmodule Qt3D.Core
+ \inherits AbstractSkeleton
+ \instantiates Qt3DCore::QSkeletonLoader
+ \since 5.10
+ \brief Used to load a skeleton of joints from file
+
+ Use SkeletonLoader if you wish to load a whole skeleton from file rather
+ than creating the joints yourself using Skeleton and Joints. Creating a
+ skeleton and binding the vertices of a mesh to the skeleton is most easily
+ performed in a 3D digital content creation tool such as Blender. The
+ resulting skeleton and mesh can then be exported in a suitable format such
+ as glTF 2 for consumption by Qt 3D.
+*/
+
+/*!
+ \qmlproperty url SkeletonLoader::source
+
+ Holds the source url from which to load the skeleton.
+*/
+
+/*!
+ \qmlproperty SkeletonLoader.Status SkeletonLoader::status
+
+ Holds the current status of skeleton loading.
+*/
+
+/*!
+ \class Qt3DCore::QSkeletonLoader
+ \inmodule Qt3DCore
+ \inherits Qt3DCore::QAbstractSkeleton
+ \since 5.10
+ \brief Used to load a skeleton of joints from file
+
+ Use SkeletonLoader if you wish to load a whole skeleton from file rather
+ than creating the joints yourself using Skeleton and Joints. Creating a
+ skeleton and binding the vertices of a mesh to the skeleton is most easily
+ performed in a 3D digital content creation tool such as Blender. The
+ resulting skeleton and mesh can then be exported in a suitable format such
+ as glTF 2 for consumption by Qt 3D.
+*/
+
+/*!
+ \enum QSkeletonLoader::Status
+
+ This enum identifies the status of skeleton.
+
+ \value NotReady The skeleton has not been loaded yet
+ \value Ready The skeleton was successfully loaded
+ \value Error An error occurred while loading the skeleton
+*/
+
+/*!
+ Constructs a new QSkeletonLoader with \a parent.
+*/
+QSkeletonLoader::QSkeletonLoader(Qt3DCore::QNode *parent)
+ : QAbstractSkeleton(*new QSkeletonLoaderPrivate, parent)
+{
+}
+
+/*!
+ Constructs a new QSkeletonLoader with \a parent and sets the \a source.
+*/
+QSkeletonLoader::QSkeletonLoader(const QUrl &source, QNode *parent)
+ : QAbstractSkeleton(*new QSkeletonLoaderPrivate, parent)
+{
+ setSource(source);
+}
+
+/*! \internal */
+QSkeletonLoader::QSkeletonLoader(QSkeletonLoaderPrivate &dd, Qt3DCore::QNode *parent)
+ : QAbstractSkeleton(dd, parent)
+{
+}
+
+/*! \internal */
+QSkeletonLoader::~QSkeletonLoader()
+{
+}
+
+/*!
+ \property Qt3DCore::QSkeletonLoader::source
+
+ Holds the source url from which to load the skeleton.
+*/
+QUrl QSkeletonLoader::source() const
+{
+ Q_D(const QSkeletonLoader);
+ return d->m_source;
+}
+
+/*!
+ \property Qt3DCore::QSkeletonLoader::status
+
+ Holds the current status of skeleton loading.
+*/
+QSkeletonLoader::Status QSkeletonLoader::status() const
+{
+ Q_D(const QSkeletonLoader);
+ return d->m_status;
+}
+
+void QSkeletonLoader::setSource(const QUrl &source)
+{
+ Q_D(QSkeletonLoader);
+ if (d->m_source == source)
+ return;
+
+ d->m_source = source;
+ emit sourceChanged(source);
+}
+
+/*! \internal */
+void QSkeletonLoader::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ Q_D(QSkeletonLoader);
+ if (change->type() == Qt3DCore::PropertyUpdated) {
+ const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->propertyName() == QByteArrayLiteral("status"))
+ d->setStatus(static_cast<QSkeletonLoader::Status>(e->value().toInt()));
+ }
+}
+
+/*! \internal */
+Qt3DCore::QNodeCreatedChangeBasePtr QSkeletonLoader::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QSkeletonLoaderData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QSkeletonLoader);
+ data.source = d->m_source;
+ return creationChange;
+}
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
diff --git a/src/core/transforms/qskeletonloader.h b/src/core/transforms/qskeletonloader.h
new file mode 100644
index 000000000..efebe3684
--- /dev/null
+++ b/src/core/transforms/qskeletonloader.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QSKELETONLOADER_H
+#define QT3DCORE_QSKELETONLOADER_H
+
+#include <Qt3DCore/qabstractskeleton.h>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QSkeletonLoaderPrivate;
+
+class QT3DCORESHARED_EXPORT QSkeletonLoader : public QAbstractSkeleton
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+public:
+ explicit QSkeletonLoader(Qt3DCore::QNode *parent = nullptr);
+ explicit QSkeletonLoader(const QUrl &source,
+ Qt3DCore::QNode *parent = nullptr);
+ ~QSkeletonLoader();
+
+ enum Status {
+ NotReady = 0,
+ Ready,
+ Error
+ };
+ Q_ENUM(Status) // LCOV_EXCL_LINE
+
+ QUrl source() const;
+ Status status() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl &source);
+
+Q_SIGNALS:
+ void sourceChanged(const QUrl &source);
+ void statusChanged(Status status);
+
+protected:
+ explicit QSkeletonLoader(QSkeletonLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
+private:
+ Q_DECLARE_PRIVATE(QSkeletonLoader)
+ QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QSKELETONLOADER_H
diff --git a/src/core/transforms/qskeletonloader_p.h b/src/core/transforms/qskeletonloader_p.h
new file mode 100644
index 000000000..aca7eae55
--- /dev/null
+++ b/src/core/transforms/qskeletonloader_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_QSKELETONLOADER_P_H
+#define QT3DCORE_QSKELETONLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qabstractskeleton_p.h>
+#include "qskeletonloader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate
+{
+public:
+ QSkeletonLoaderPrivate();
+
+ void setStatus(QSkeletonLoader::Status status);
+
+ Q_DECLARE_PUBLIC(QSkeletonLoader)
+
+ QUrl m_source;
+ QSkeletonLoader::Status m_status;
+};
+
+struct QSkeletonLoaderData
+{
+ QUrl source;
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QSKELETONLOADER_P_H
diff --git a/src/core/transforms/transforms.pri b/src/core/transforms/transforms.pri
index aa214c693..d5eb965ae 100644
--- a/src/core/transforms/transforms.pri
+++ b/src/core/transforms/transforms.pri
@@ -1,13 +1,22 @@
SOURCES += \
$$PWD/qtransform.cpp \
- $$PWD/qjoint.cpp
+ $$PWD/qjoint.cpp \
+ $$PWD/qabstractskeleton.cpp \
+ $$PWD/qskeleton.cpp \
+ $$PWD/qskeletonloader.cpp
HEADERS += \
$$PWD/qtransform.h \
$$PWD/qtransform_p.h \
$$PWD/qmath3d_p.h \
$$PWD/qjoint.h \
- $$PWD/qjoint_p.h
+ $$PWD/qjoint_p.h \
+ $$PWD/qabstractskeleton.h \
+ $$PWD/qabstractskeleton_p.h \
+ $$PWD/qskeleton.h \
+ $$PWD/qskeleton_p.h \
+ $$PWD/qskeletonloader.h \
+ $$PWD/qskeletonloader_p.h
INCLUDEPATH += $$PWD
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"