summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-01-21 15:53:09 +0000
committerPaul Lemire <paul.lemire@kdab.com>2017-01-27 11:17:15 +0000
commit4a94e68d5975b53f11ab2ab7755f6b944fc8b614 (patch)
tree6cc7116b0e37d69a54f6f64241240001b7e17add
parent50181a712f547ec93f8ba026385c99e982535a66 (diff)
Add a job to load animation clips
Defers the actual work to AnimationClip. Also made all backend nodes have a common base class to make it easy to track the Handler. Added a manual test to exercise this and which we can build up over time as we add API. Change-Id: I7cdd8da948498544059ba51efe38642dd54ea410 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/animation/backend/animationclip.cpp74
-rw-r--r--src/animation/backend/animationclip_p.h36
-rw-r--r--src/animation/backend/backend.pri8
-rw-r--r--src/animation/backend/backendnode.cpp71
-rw-r--r--src/animation/backend/backendnode_p.h81
-rw-r--r--src/animation/backend/blendedclipanimator.cpp3
-rw-r--r--src/animation/backend/blendedclipanimator_p.h8
-rw-r--r--src/animation/backend/clipanimator.cpp3
-rw-r--r--src/animation/backend/clipanimator_p.h5
-rw-r--r--src/animation/backend/conductedclipanimator.cpp3
-rw-r--r--src/animation/backend/conductedclipanimator_p.h8
-rw-r--r--src/animation/backend/fcurve.cpp58
-rw-r--r--src/animation/backend/fcurve_p.h63
-rw-r--r--src/animation/backend/handler.cpp26
-rw-r--r--src/animation/backend/handler_p.h12
-rw-r--r--src/animation/backend/loadanimationclipjob.cpp82
-rw-r--r--src/animation/backend/loadanimationclipjob_p.h87
-rw-r--r--tests/auto/animation/animationclip/tst_animationclip.cpp6
-rw-r--r--tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml35
-rw-r--r--tests/manual/animation-keyframe-simple/animation-keyframe-simple.pro5
-rw-r--r--tests/manual/animation-keyframe-simple/cubeanimation.json35
-rw-r--r--tests/manual/animation-keyframe-simple/main.cpp25
-rw-r--r--tests/manual/animation-keyframe-simple/main.qml53
-rw-r--r--tests/manual/animation-keyframe-simple/main.qrc7
-rw-r--r--tests/manual/manual.pro3
25 files changed, 765 insertions, 32 deletions
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index d5244e8c5..c7d262507 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -37,17 +37,27 @@
#include "animationclip_p.h"
#include <Qt3DAnimation/qanimationclip.h>
#include <Qt3DAnimation/private/qanimationclip_p.h>
+#include <Qt3DAnimation/private/animationlogging_p.h>
+#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
AnimationClip::AnimationClip()
- : Qt3DCore::QBackendNode(ReadOnly)
- , m_handler(nullptr)
+ : BackendNode(ReadOnly)
, m_source()
+ , m_name()
+ , m_objectName()
+ , m_channelGroups()
{
}
@@ -56,6 +66,8 @@ void AnimationClip::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAnimationClipData>>(change);
const auto &data = typedChange->data;
m_source = data.source;
+ if (!m_source.isEmpty())
+ setDirty(Handler::AnimationClipDirty);
}
void AnimationClip::cleanup()
@@ -63,6 +75,8 @@ void AnimationClip::cleanup()
setEnabled(false);
m_handler = nullptr;
m_source.clear();
+
+ clearData();
}
void AnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
@@ -70,8 +84,10 @@ void AnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
switch (e->type()) {
case Qt3DCore::PropertyUpdated: {
const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("source"))
+ if (change->propertyName() == QByteArrayLiteral("source")) {
m_source = change->value().toUrl();
+ setDirty(Handler::AnimationClipDirty);
+ }
break;
}
@@ -81,6 +97,58 @@ void AnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
QBackendNode::sceneChangeEvent(e);
}
+/*!
+ \internal
+ Called by LoadAnimationClipJob on the threadpool
+ */
+void AnimationClip::loadAnimation()
+{
+ qCDebug(Jobs) << Q_FUNC_INFO << m_source;
+ clearData();
+
+ // TODO: Handle remote files
+ QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source);
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Could not find animation clip:" << filePath;
+ return;
+ }
+
+ QByteArray animationData = file.readAll();
+ QJsonDocument document = QJsonDocument::fromJson(animationData);
+ QJsonObject rootObject = document.object();
+
+ // TODO: Allow loading of a named animation from a file containing many
+ QJsonArray animationsArray = rootObject[QLatin1String("animations")].toArray();
+ qCDebug(Jobs) << "Found" << animationsArray.size() << "animations:";
+ for (int i = 0; i < animationsArray.size(); ++i) {
+ QJsonObject animation = animationsArray.at(i).toObject();
+ qCDebug(Jobs) << "\tName:" << animation[QLatin1String("action")].toString()
+ << "Object:" << animation[QLatin1String("object")].toString();
+ }
+
+ // For now just load the first animation
+ QJsonObject animation = animationsArray.at(0).toObject();
+ m_name = animation[QLatin1String("action")].toString();
+ m_objectName = animation[QLatin1String("object")].toString();
+ QJsonArray groupsArray = animation[QLatin1String("groups")].toArray();
+ const int groupCount = groupsArray.size();
+ m_channelGroups.resize(groupCount);
+ for (int i = 0; i < groupCount; ++i) {
+ const QJsonObject group = groupsArray.at(i).toObject();
+ m_channelGroups[i].read(group);
+ }
+
+ qCDebug(Jobs) << "Loaded animation data:" << *this;
+}
+
+void AnimationClip::clearData()
+{
+ m_name.clear();
+ m_objectName.clear();
+ m_channelGroups.clear();
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/animationclip_p.h b/src/animation/backend/animationclip_p.h
index 9a2da5ed0..6170c3423 100644
--- a/src/animation/backend/animationclip_p.h
+++ b/src/animation/backend/animationclip_p.h
@@ -48,7 +48,8 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DAnimation/private/backendnode_p.h>
+#include <Qt3DAnimation/private/fcurve_p.h>
#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,7 @@ namespace Animation {
class Handler;
-class Q_AUTOTEST_EXPORT AnimationClip : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT AnimationClip : public BackendNode
{
public:
AnimationClip();
@@ -68,15 +69,42 @@ public:
QUrl source() const { return m_source; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
- void setHandler(Handler *handler) { m_handler = handler; }
+ QString name() const { return m_name; }
+ QString objectName() const { return m_objectName; }
+ QVector<ChannelGroup> channelGroups() const { return m_channelGroups; }
+
+ // Called from jobs
+ void loadAnimation();
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void clearData();
- Handler *m_handler;
QUrl m_source;
+
+ QString m_name;
+ QString m_objectName;
+ QVector<ChannelGroup> m_channelGroups;
};
+#ifndef QT_NO_DEBUG_STREAM
+inline QDebug operator<<(QDebug dbg, const AnimationClip &animationClip)
+{
+ QDebugStateSaver saver(dbg);
+ dbg << "QNodeId =" << animationClip.peerId() << endl
+ << "Name =" << animationClip.name() << endl
+ << "Object Name =" << animationClip.objectName() << endl
+ << "Channel Groups:" << endl;
+
+ const QVector<ChannelGroup> channelGroups = animationClip.channelGroups();
+ for (const auto channelGroup : channelGroups) {
+ dbg << channelGroup;
+ }
+
+ return dbg;
+}
+#endif
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/backend.pri b/src/animation/backend/backend.pri
index 1e8b27fa2..86b2b9e15 100644
--- a/src/animation/backend/backend.pri
+++ b/src/animation/backend/backend.pri
@@ -13,7 +13,9 @@ HEADERS += \
$$PWD/functionrangefinder_p.h \
$$PWD/clipanimator_p.h \
$$PWD/blendedclipanimator_p.h \
- $$PWD/conductedclipanimator_p.h
+ $$PWD/conductedclipanimator_p.h \
+ $$PWD/backendnode_p.h \
+ $$PWD/loadanimationclipjob_p.h
SOURCES += \
$$PWD/animationclip.cpp \
@@ -23,4 +25,6 @@ SOURCES += \
$$PWD/functionrangefinder.cpp \
$$PWD/clipanimator.cpp \
$$PWD/blendedclipanimator.cpp \
- $$PWD/conductedclipanimator.cpp
+ $$PWD/conductedclipanimator.cpp \
+ $$PWD/backendnode.cpp \
+ $$PWD/loadanimationclipjob.cpp
diff --git a/src/animation/backend/backendnode.cpp b/src/animation/backend/backendnode.cpp
new file mode 100644
index 000000000..6ea7f89c7
--- /dev/null
+++ b/src/animation/backend/backendnode.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "backendnode_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+BackendNode::BackendNode(Mode mode)
+ : Qt3DCore::QBackendNode(mode)
+ , m_handler(nullptr)
+{
+}
+
+BackendNode::~BackendNode()
+{
+}
+
+void BackendNode::setHandler(Handler *handler)
+{
+ m_handler = handler;
+}
+
+void BackendNode::setDirty(Handler::DirtyFlag flag)
+{
+ Q_ASSERT(m_handler);
+ m_handler->setDirty(flag, peerId());
+}
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/backendnode_p.h b/src/animation/backend/backendnode_p.h
new file mode 100644
index 000000000..d7842517a
--- /dev/null
+++ b/src/animation/backend/backendnode_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 QT3DANIMATION_ANIMATION_BACKENDNODE_H
+#define QT3DANIMATION_ANIMATION_BACKENDNODE_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 <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DAnimation/private/handler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+class Q_AUTOTEST_EXPORT BackendNode : public Qt3DCore::QBackendNode
+{
+public:
+ BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
+ ~BackendNode();
+
+ void setHandler(Handler *handler);
+
+protected:
+ void setDirty(Handler::DirtyFlag flag);
+ Handler *m_handler;
+};
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_BACKENDNODE_H
diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp
index 1fbd2cd0e..63278dbb6 100644
--- a/src/animation/backend/blendedclipanimator.cpp
+++ b/src/animation/backend/blendedclipanimator.cpp
@@ -45,8 +45,7 @@ namespace Qt3DAnimation {
namespace Animation {
BlendedClipAnimator::BlendedClipAnimator()
- : Qt3DCore::QBackendNode(ReadOnly)
- , m_handler(nullptr)
+ : BackendNode(ReadOnly)
{
}
diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h
index 47c0c7310..022399b25 100644
--- a/src/animation/backend/blendedclipanimator_p.h
+++ b/src/animation/backend/blendedclipanimator_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DAnimation/private/backendnode_p.h>
QT_BEGIN_NAMESPACE
@@ -57,7 +57,7 @@ namespace Animation {
class Handler;
-class Q_AUTOTEST_EXPORT BlendedClipAnimator : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT BlendedClipAnimator : public BackendNode
{
public:
BlendedClipAnimator();
@@ -66,12 +66,8 @@ public:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
- void setHandler(Handler *handler) { m_handler = handler; }
-
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
-
- Handler *m_handler;
};
} // namespace Animation
diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp
index 1f9af398b..a0e62c636 100644
--- a/src/animation/backend/clipanimator.cpp
+++ b/src/animation/backend/clipanimator.cpp
@@ -45,8 +45,7 @@ namespace Qt3DAnimation {
namespace Animation {
ClipAnimator::ClipAnimator()
- : Qt3DCore::QBackendNode(ReadOnly)
- , m_handler(nullptr)
+ : BackendNode(ReadOnly)
, m_clipId()
{
}
diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h
index 6b5b13bb2..87039cec7 100644
--- a/src/animation/backend/clipanimator_p.h
+++ b/src/animation/backend/clipanimator_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DAnimation/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +58,7 @@ namespace Animation {
class Handler;
-class Q_AUTOTEST_EXPORT ClipAnimator : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT ClipAnimator : public BackendNode
{
public:
ClipAnimator();
@@ -73,7 +73,6 @@ public:
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
- Handler *m_handler;
Qt3DCore::QNodeId m_clipId;
};
diff --git a/src/animation/backend/conductedclipanimator.cpp b/src/animation/backend/conductedclipanimator.cpp
index 2342e06fc..32db1b7ea 100644
--- a/src/animation/backend/conductedclipanimator.cpp
+++ b/src/animation/backend/conductedclipanimator.cpp
@@ -45,8 +45,7 @@ namespace Qt3DAnimation {
namespace Animation {
ConductedClipAnimator::ConductedClipAnimator()
- : Qt3DCore::QBackendNode(ReadOnly)
- , m_handler(nullptr)
+ : BackendNode(ReadOnly)
{
}
diff --git a/src/animation/backend/conductedclipanimator_p.h b/src/animation/backend/conductedclipanimator_p.h
index 2a96e99ef..d4534447e 100644
--- a/src/animation/backend/conductedclipanimator_p.h
+++ b/src/animation/backend/conductedclipanimator_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DAnimation/private/backendnode_p.h>
QT_BEGIN_NAMESPACE
@@ -57,7 +57,7 @@ namespace Animation {
class Handler;
-class Q_AUTOTEST_EXPORT ConductedClipAnimator : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT ConductedClipAnimator : public BackendNode
{
public:
ConductedClipAnimator();
@@ -66,12 +66,8 @@ public:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
- void setHandler(Handler *handler) { m_handler = handler; }
-
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
-
- Handler *m_handler;
};
} // namespace Animation
diff --git a/src/animation/backend/fcurve.cpp b/src/animation/backend/fcurve.cpp
index 95e3d1568..88874cab5 100644
--- a/src/animation/backend/fcurve.cpp
+++ b/src/animation/backend/fcurve.cpp
@@ -37,6 +37,10 @@
#include "fcurve_p.h"
#include <private/bezierevaluator_p.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/QLatin1String>
+
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
@@ -77,6 +81,60 @@ void FCurve::appendKeyframe(float localTime, const Keyframe &keyframe)
m_keyframes.append(keyframe);
}
+void FCurve::read(const QJsonObject &json)
+{
+ clearKeyframes();
+
+ const QJsonArray keyframeArray = json[QLatin1String("keyframes")].toArray();
+ const int keyframeCount = keyframeArray.size();
+
+ for (int i = 0; i < keyframeCount; ++i) {
+ const QJsonObject keyframeData = keyframeArray.at(i).toObject();
+
+ // Extract the keyframe local time and value
+ const QJsonArray keyframeCoords = keyframeData[QLatin1String("co")].toArray();
+ float localTime = keyframeCoords.at(0).toDouble();
+
+ Keyframe keyframe;
+ keyframe.interpolation = Keyframe::Bezier;
+ keyframe.value = keyframeCoords.at(1).toDouble();
+
+ const QJsonArray leftHandle = keyframeData[QLatin1String("handle_left")].toArray();
+ keyframe.leftControlPoint[0] = leftHandle.at(0).toDouble();
+ keyframe.leftControlPoint[1] = leftHandle.at(1).toDouble();
+
+ const QJsonArray rightHandle = keyframeData[QLatin1String("handle_right")].toArray();
+ keyframe.rightControlPoint[0] = rightHandle.at(0).toDouble();
+ keyframe.rightControlPoint[1] = rightHandle.at(1).toDouble();
+
+ appendKeyframe(localTime, keyframe);
+ }
+
+ // TODO: Ensure beziers have no loops or cusps by scaling the control points
+ // back so they do not interset.
+}
+
+void Channel::read(const QJsonObject &json)
+{
+ fcurve.read(json);
+}
+
+void ChannelGroup::read(const QJsonObject &json)
+{
+ name = json[QLatin1String("group")].toString();
+ const QJsonArray channelsArray = json[QLatin1String("channels")].toArray();
+ const int channelCount = channelsArray.size();
+ channels.resize(channelCount);
+
+ // TODO: Add channel names to export format
+ const QStringList channelNameSuffixes = {QLatin1String("X"), QLatin1String("Y"), QLatin1String("Z")};
+ for (int i = 0; i < channelCount; ++i) {
+ const QJsonObject channel = channelsArray.at(i).toObject();
+ channels[i].read(channel);
+ channels[i].name = name + QLatin1String(".") + channelNameSuffixes.at(i);
+ }
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/fcurve_p.h b/src/animation/backend/fcurve_p.h
index 88990fb81..def33941e 100644
--- a/src/animation/backend/fcurve_p.h
+++ b/src/animation/backend/fcurve_p.h
@@ -52,6 +52,10 @@
#include "functionrangefinder_p.h"
#include <QtCore/qvector.h>
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
@@ -76,6 +80,8 @@ public:
float evaluateAtTime(float localTime) const;
+ void read(const QJsonObject &json);
+
private:
QVector<float> m_localTimes;
QVector<Keyframe> m_keyframes;
@@ -83,6 +89,63 @@ private:
FunctionRangeFinder m_rangeFinder;
};
+#ifndef QT_NO_DEBUG_STREAM
+inline QDebug operator<<(QDebug dbg, const FCurve &fcurve)
+{
+ QDebugStateSaver saver(dbg);
+ dbg << "Keyframe Count =" << fcurve.keyframeCount() << endl;
+ for (int i = 0; i < fcurve.keyframeCount(); ++i) {
+ const Keyframe &kf = fcurve.keyframe(i);
+ dbg << "t =" << fcurve.localTime(i)
+ << "value =" << kf.value
+ << "leftHandle =" << kf.leftControlPoint
+ << "rightHandle =" << kf.rightControlPoint
+ << endl;
+ }
+ return dbg;
+}
+#endif
+
+struct Channel
+{
+ QString name;
+ FCurve fcurve;
+
+ void read(const QJsonObject &json);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+inline QDebug operator<<(QDebug dbg, const Channel &channel)
+{
+ QDebugStateSaver saver(dbg);
+ dbg << "Channel Name: " << channel.name << endl
+ << "Fcurve:" << channel.fcurve << endl;
+ return dbg;
+}
+#endif
+
+struct ChannelGroup
+{
+ QString name;
+ QVector<Channel> channels;
+
+ void read(const QJsonObject &json);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+inline QDebug operator<<(QDebug dbg, const ChannelGroup &channelGroup)
+{
+ QDebugStateSaver saver(dbg);
+ dbg << "Name: " << channelGroup.name << endl
+ << "Channels:" << channelGroup.channels.size() << endl;
+
+ for (const auto channel : qAsConst(channelGroup.channels)) {
+ dbg << channel;
+ }
+ return dbg;
+}
+#endif
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/handler.cpp b/src/animation/backend/handler.cpp
index bfcb22090..0da9ba4dd 100644
--- a/src/animation/backend/handler.cpp
+++ b/src/animation/backend/handler.cpp
@@ -36,7 +36,8 @@
#include "handler_p.h"
#include <Qt3DAnimation/private/managers_p.h>
-
+#include <Qt3DAnimation/private/loadanimationclipjob_p.h>
+#include <Qt3DAnimation/private/animationlogging_p.h>
QT_BEGIN_NAMESPACE
@@ -48,17 +49,40 @@ Handler::Handler()
, m_clipAnimatorManager(new ClipAnimatorManager)
, m_blendedClipAnimatorManager(new BlendedClipAnimatorManager)
, m_conductedClipAnimatorManager(new ConductedClipAnimatorManager)
+ , m_loadAnimationClipJob(new LoadAnimationClipJob)
{
+ m_loadAnimationClipJob->setHandler(this);
}
Handler::~Handler()
{
}
+void Handler::setDirty(DirtyFlag flag, Qt3DCore::QNodeId nodeId)
+{
+ switch (flag) {
+ case AnimationClipDirty: {
+ const auto handle = m_animationClipManager->lookupHandle(nodeId);
+ m_dirtyAnimationClips.push_back(handle);
+ break;
+ }
+ }
+}
+
QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
{
Q_UNUSED(time);
QVector<Qt3DCore::QAspectJobPtr> jobs;
+
+ // If there are any dirty animation clips that need loading,
+ // queue up a job for them
+ if (!m_dirtyAnimationClips.isEmpty()) {
+ qCDebug(HandlerLogic) << "Added LoadAnimationClipJob";
+ m_loadAnimationClipJob->addDirtyAnimationClips(m_dirtyAnimationClips);
+ jobs.push_back(m_loadAnimationClipJob);
+ m_dirtyAnimationClips.clear();
+ }
+
return jobs;
}
diff --git a/src/animation/backend/handler_p.h b/src/animation/backend/handler_p.h
index 248184a04..8a5f1bfd4 100644
--- a/src/animation/backend/handler_p.h
+++ b/src/animation/backend/handler_p.h
@@ -72,12 +72,20 @@ class BlendedClipAnimatorManager;
class ConductedClipAnimator;
class ConductedClipAnimatorManager;
+class LoadAnimationClipJob;
+
class Q_AUTOTEST_EXPORT Handler
{
public:
Handler();
~Handler();
+ enum DirtyFlag {
+ AnimationClipDirty
+ };
+
+ void setDirty(DirtyFlag flag, Qt3DCore::QNodeId nodeId);
+
AnimationClipManager *animationClipManager() const Q_DECL_NOTHROW { return m_animationClipManager.data(); }
ClipAnimatorManager *clipAnimatorManager() const Q_DECL_NOTHROW { return m_clipAnimatorManager.data(); }
BlendedClipAnimatorManager *blendedClipAnimatorManager() const Q_DECL_NOTHROW { return m_blendedClipAnimatorManager.data(); }
@@ -91,6 +99,10 @@ private:
QScopedPointer<BlendedClipAnimatorManager> m_blendedClipAnimatorManager;
QScopedPointer<ConductedClipAnimatorManager> m_conductedClipAnimatorManager;
+ QVector<HAnimationClip> m_dirtyAnimationClips;
+
+ QSharedPointer<LoadAnimationClipJob> m_loadAnimationClipJob;
+
#if defined(QT_BUILD_INTERNAL)
friend class QT_PREPEND_NAMESPACE(tst_Handler);
#endif
diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp
new file mode 100644
index 000000000..c94435398
--- /dev/null
+++ b/src/animation/backend/loadanimationclipjob.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "loadanimationclipjob_p.h"
+
+#include <Qt3DAnimation/private/animationclip_p.h>
+#include <Qt3DAnimation/private/handler_p.h>
+#include <Qt3DAnimation/private/managers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+LoadAnimationClipJob::LoadAnimationClipJob()
+ : Qt3DCore::QAspectJob()
+ , m_animationClipHandles()
+{
+}
+
+void LoadAnimationClipJob::addDirtyAnimationClips(const QVector<HAnimationClip> &animationClipHandles)
+{
+ for (const auto handle : animationClipHandles) {
+ if (!m_animationClipHandles.contains(handle))
+ m_animationClipHandles.push_back(handle);
+ }
+}
+
+void LoadAnimationClipJob::clearDirtyAnimationClips()
+{
+ m_animationClipHandles.clear();
+}
+
+void LoadAnimationClipJob::run()
+{
+ Q_ASSERT(m_handler);
+ AnimationClipManager *animationClipManager = m_handler->animationClipManager();
+ for (const auto animationClipHandle : qAsConst(m_animationClipHandles)) {
+ AnimationClip *animationClip = animationClipManager->data(animationClipHandle);
+ animationClip->loadAnimation();
+ }
+
+ clearDirtyAnimationClips();
+}
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/loadanimationclipjob_p.h b/src/animation/backend/loadanimationclipjob_p.h
new file mode 100644
index 000000000..f5d0a3b82
--- /dev/null
+++ b/src/animation/backend/loadanimationclipjob_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_ANIMATION_LOADANIMATIONCLIPJOB_H
+#define QT3DANIMATION_ANIMATION_LOADANIMATIONCLIPJOB_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/qaspectjob.h>
+#include <Qt3DAnimation/private/handle_types_p.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+class Handler;
+class FindGraphJob;
+
+class LoadAnimationClipJob : public Qt3DCore::QAspectJob
+{
+public:
+ LoadAnimationClipJob();
+
+ void setHandler(Handler *handler) { m_handler = handler; }
+ Handler *handler() const { return m_handler; }
+
+ void addDirtyAnimationClips(const QVector<HAnimationClip> &animationClipHandles);
+ void clearDirtyAnimationClips();
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
+private:
+ QVector<HAnimationClip> m_animationClipHandles;
+ Handler *m_handler;
+};
+
+} // namespace Animation
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_LOADANIMATIONCLIPJOB_H
diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp
index 735646db6..cd1d2ccf0 100644
--- a/tests/auto/animation/animationclip/tst_animationclip.cpp
+++ b/tests/auto/animation/animationclip/tst_animationclip.cpp
@@ -45,6 +45,8 @@ private Q_SLOTS:
{
// GIVEN
Qt3DAnimation::Animation::AnimationClip backendClip;
+ Qt3DAnimation::Animation::Handler handler;
+ backendClip.setHandler(&handler);
Qt3DAnimation::QAnimationClip clip;
clip.setSource(QUrl::fromLocalFile("walk.qlip"));
@@ -62,6 +64,8 @@ private Q_SLOTS:
{
// GIVEN
Qt3DAnimation::Animation::AnimationClip backendClip;
+ Qt3DAnimation::Animation::Handler handler;
+ backendClip.setHandler(&handler);
// THEN
QVERIFY(backendClip.peerId().isNull());
@@ -86,6 +90,8 @@ private Q_SLOTS:
{
// GIVEN
Qt3DAnimation::Animation::AnimationClip backendClip;
+ Qt3DAnimation::Animation::Handler handler;
+ backendClip.setHandler(&handler);
Qt3DCore::QPropertyUpdatedChangePtr updateChange;
// WHEN
diff --git a/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml b/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml
new file mode 100644
index 000000000..efffd44c9
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/DefaultSceneEntity.qml
@@ -0,0 +1,35 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB)
+ * All rights reserved.
+ *
+ * See the LICENSE.txt file shipped along with this file for the license.
+ *
+ *************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.0
+
+Entity {
+ id: root
+ property Camera camera
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ camera: root.camera
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { }
+ ]
+
+ Entity {
+ components: [
+ PointLight { intensity: 0.5 },
+ Transform { translation: camera.position }
+ ]
+ }
+}
diff --git a/tests/manual/animation-keyframe-simple/animation-keyframe-simple.pro b/tests/manual/animation-keyframe-simple/animation-keyframe-simple.pro
new file mode 100644
index 000000000..04db4207e
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/animation-keyframe-simple.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+QT += 3dquickextras 3dquickanimation
+SOURCES += main.cpp
+RESOURCES += main.qrc
+OTHER_FILES += main.qml DefaultSceneEntity.qml
diff --git a/tests/manual/animation-keyframe-simple/cubeanimation.json b/tests/manual/animation-keyframe-simple/cubeanimation.json
new file mode 100644
index 000000000..e9c55177f
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/cubeanimation.json
@@ -0,0 +1,35 @@
+{
+ "animations": [
+ { "object": "Cube",
+ "action": "CubeAction",
+ "groups": [
+ { "group": "Location",
+ "channels": [
+ { "keyframes": [
+ { "co": [1.0, 0.0],
+ "handle_left": [-22.034278869628906, 0.0],
+ "handle_right": [24.034278869628906, 0.0]}
+ ,{ "co": [60.0, 5.0],
+ "handle_left": [36.965721130371094, 5.0],
+ "handle_right": [83.0342788696289, 5.0]}
+ ]}
+ ,{ "keyframes": [
+ { "co": [1.0, 0.0],
+ "handle_left": [-22.034278869628906, 0.0],
+ "handle_right": [24.034278869628906, 0.0]}
+ ,{ "co": [60.0, 0.0],
+ "handle_left": [36.965721130371094, 0.0],
+ "handle_right": [83.0342788696289, 0.0]}
+ ]}
+ ,{ "keyframes": [
+ { "co": [1.0, 0.0],
+ "handle_left": [-22.034278869628906, 0.0],
+ "handle_right": [24.034278869628906, 0.0]}
+ ,{ "co": [60.0, 0.0],
+ "handle_left": [36.965721130371094, 0.0],
+ "handle_right": [83.0342788696289, 0.0]}
+ ]}
+ ]}
+ ]}
+ ]
+}
diff --git a/tests/manual/animation-keyframe-simple/main.cpp b/tests/manual/animation-keyframe-simple/main.cpp
new file mode 100644
index 000000000..fc48fc702
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/main.cpp
@@ -0,0 +1,25 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB)
+ * All rights reserved.
+ *
+ * See the LICENSE.txt file shipped along with this file for the license.
+ *
+ *************************************************************************/
+
+#include <QGuiApplication>
+#include <Qt3DAnimation/QAnimationAspect>
+#include <Qt3DQuickExtras/Qt3DQuickWindow>
+#include <Qt3DQuick/QQmlAspectEngine>
+#include <QQmlEngine>
+#include <QQmlContext>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+ view.registerAspect(new Qt3DAnimation::QAnimationAspect());
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+ return app.exec();
+}
diff --git a/tests/manual/animation-keyframe-simple/main.qml b/tests/manual/animation-keyframe-simple/main.qml
new file mode 100644
index 000000000..37f5eba2f
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/main.qml
@@ -0,0 +1,53 @@
+/*************************************************************************
+ *
+ * Copyright (c) 2016, Klaralvdalens Datakonsult AB (KDAB)
+ * All rights reserved.
+ *
+ * See the LICENSE.txt file shipped along with this file for the license.
+ *
+ *************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Input 2.0
+import Qt3D.Animation 2.2
+import Qt3D.Extras 2.0
+
+DefaultSceneEntity {
+ id: scene
+
+ Entity {
+ id: cube
+
+ components: [
+ CuboidMesh {
+ },
+ PhongMaterial {
+ ambient: Qt.rgba(0.02, 0.02, 0.02, 1.0)
+ diffuse: "blue"
+ shininess: 50
+ },
+ Transform {
+ id: cubeTransform
+ },
+ ClipAnimator {
+ running: true
+ clip: AnimationClip {
+ source: "cubeanimation.json"
+ }
+ }
+
+ ]
+ }
+
+ camera: Camera {
+ position: Qt.vector3d(10, 10, 10)
+ viewCenter: Qt.vector3d(0, 0, 0)
+ }
+
+ OrbitCameraController {
+ camera: scene.camera
+ linearSpeed: 8
+ lookSpeed: 180
+ }
+}
diff --git a/tests/manual/animation-keyframe-simple/main.qrc b/tests/manual/animation-keyframe-simple/main.qrc
new file mode 100644
index 000000000..ca5342f26
--- /dev/null
+++ b/tests/manual/animation-keyframe-simple/main.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>DefaultSceneEntity.qml</file>
+ <file>cubeanimation.json</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 90e9c250e..a2ca61758 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -37,7 +37,8 @@ SUBDIRS += \
transparency-qml-scene3d \
rendercapture-qml \
additional-attributes-qml \
- dynamic-model-loader-qml
+ dynamic-model-loader-qml \
+ animation-keyframe-simple
qtHaveModule(widgets): {
SUBDIRS += \