summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWieland Hagen <wieland.hagen@kdab.com>2017-08-02 22:50:58 +0200
committerWieland Hagen <wieland.hagen@kdab.com>2017-09-08 11:53:24 +0000
commitcef1c7fe3c650f6fad4760230d3cf7052ed70253 (patch)
tree7275017003db416aa57dc253cb727ce2962c34c1
parentcc815a6146c9397539d5a639f29004a5aaeb6a5b (diff)
Re-build Blend-Trees when Clips have been loaded
We need to notify the BlendedClipAnimators, when any of the clips it depends on have been loaded. So we register each animator at the clips that it depends on, mark the animator dirty when the clip has been loaded and thus trigger a re-run of the BuildBlendTreesJob. Make sure to guard accesses to the Handler via mutexes, because backend objects can be marked dirty from various threads. Task-number: QTBUG-61941 Change-Id: I4890d0d76d3118538537252f920d9477bed8f934 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--src/animation/backend/animationclip.cpp31
-rw-r--r--src/animation/backend/animationclip_p.h9
-rw-r--r--src/animation/backend/blendedclipanimator_p.h2
-rw-r--r--src/animation/backend/buildblendtreesjob.cpp5
-rw-r--r--src/animation/backend/clipanimator.cpp5
-rw-r--r--src/animation/backend/clipanimator_p.h2
-rw-r--r--src/animation/backend/handler.cpp6
-rw-r--r--src/animation/backend/handler_p.h2
8 files changed, 61 insertions, 1 deletions
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index 6a3c3c15b..a7cec8343 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -40,6 +40,7 @@
#include <Qt3DAnimation/private/qanimationclip_p.h>
#include <Qt3DAnimation/private/qanimationcliploader_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
+#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
@@ -176,6 +177,24 @@ void AnimationClip::loadAnimation()
setStatus(QAnimationClipLoader::Ready);
}
+ // notify all ClipAnimators and BlendedClipAnimators that depend on this clip,
+ // that the clip has changed and that they are now dirty
+ {
+ QMutexLocker lock(&m_mutex);
+ for (const Qt3DCore::QNodeId id : qAsConst(m_dependingAnimators)) {
+ ClipAnimator *animator = m_handler->clipAnimatorManager()->lookupResource(id);
+ if (animator)
+ animator->animationClipMarkedDirty();
+ }
+ for (const Qt3DCore::QNodeId id : qAsConst(m_dependingBlendedAnimators)) {
+ BlendedClipAnimator *animator = m_handler->blendedClipAnimatorManager()->lookupResource(id);
+ if (animator)
+ animator->animationClipMarkedDirty();
+ }
+ m_dependingAnimators.clear();
+ m_dependingBlendedAnimators.clear();
+ }
+
qCDebug(Jobs) << "Loaded animation data:" << *this;
}
@@ -224,6 +243,18 @@ void AnimationClip::loadAnimationFromData()
m_channels[i++].setFromQChannel(frontendChannel);
}
+void AnimationClip::addDependingClipAnimator(const Qt3DCore::QNodeId &id)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dependingAnimators.push_back(id);
+}
+
+void AnimationClip::addDependingBlendedClipAnimator(const Qt3DCore::QNodeId &id)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dependingBlendedAnimators.push_back(id);
+}
+
void AnimationClip::setDuration(float duration)
{
if (qFuzzyCompare(duration, m_duration))
diff --git a/src/animation/backend/animationclip_p.h b/src/animation/backend/animationclip_p.h
index 7ff79c01a..7570c76ce 100644
--- a/src/animation/backend/animationclip_p.h
+++ b/src/animation/backend/animationclip_p.h
@@ -53,6 +53,7 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/fcurve_p.h>
#include <QtCore/qurl.h>
+#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -73,6 +74,9 @@ public:
QAnimationClipLoader::Status status() const { return m_status; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void addDependingClipAnimator(const Qt3DCore::QNodeId &id);
+ void addDependingBlendedClipAnimator(const Qt3DCore::QNodeId &id);
+
QString name() const { return m_name; }
const QVector<Channel> &channels() const { return m_channels; }
@@ -106,6 +110,8 @@ private:
float findDuration();
int findChannelComponentCount();
+ QMutex m_mutex;
+
QUrl m_source;
QAnimationClipLoader::Status m_status;
QAnimationClipData m_clipData;
@@ -115,6 +121,9 @@ private:
QVector<Channel> m_channels;
float m_duration;
int m_channelComponentCount;
+
+ Qt3DCore::QNodeIdVector m_dependingAnimators;
+ Qt3DCore::QNodeIdVector m_dependingBlendedAnimators;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h
index 4421cb43a..df2c41b7c 100644
--- a/src/animation/backend/blendedclipanimator_p.h
+++ b/src/animation/backend/blendedclipanimator_p.h
@@ -91,6 +91,8 @@ public:
void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes);
+ void animationClipMarkedDirty() { setDirty(Handler::BlendedClipAnimatorDirty); }
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
Qt3DCore::QNodeId m_blendTreeRootId;
diff --git a/src/animation/backend/buildblendtreesjob.cpp b/src/animation/backend/buildblendtreesjob.cpp
index fe56099a2..f35280cbf 100644
--- a/src/animation/backend/buildblendtreesjob.cpp
+++ b/src/animation/backend/buildblendtreesjob.cpp
@@ -95,7 +95,7 @@ void BuildBlendTreesJob::run()
Q_ASSERT(valueNode);
const Qt3DCore::QNodeId clipId = valueNode->clipId();
- const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipId);
+ AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipId);
Q_ASSERT(clip);
const ComponentIndices formatIndices
@@ -103,6 +103,9 @@ void BuildBlendTreesJob::run()
channelComponentIndices,
clip);
valueNode->setFormatIndices(blendClipAnimator->peerId(), formatIndices);
+
+ // this BlendClipAnimator needs to be notified when the clip has been loaded
+ clip->addDependingBlendedClipAnimator(blendClipAnimator->peerId());
}
// Finally, build the mapping data vector for this blended clip animator. This
diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp
index 65fd0f57f..e68168f9e 100644
--- a/src/animation/backend/clipanimator.cpp
+++ b/src/animation/backend/clipanimator.cpp
@@ -75,6 +75,11 @@ void ClipAnimator::setClipId(Qt3DCore::QNodeId clipId)
{
m_clipId = clipId;
setDirty(Handler::ClipAnimatorDirty);
+
+ // register at the clip to make sure we are marked dirty when the clip finished loading
+ AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipId);
+ if (clip)
+ clip->addDependingClipAnimator(peerId());
}
void ClipAnimator::setMapperId(Qt3DCore::QNodeId mapperId)
diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h
index da9109cfb..9db575ab9 100644
--- a/src/animation/backend/clipanimator_p.h
+++ b/src/animation/backend/clipanimator_p.h
@@ -92,6 +92,8 @@ public:
void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes);
+ void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); }
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
diff --git a/src/animation/backend/handler.cpp b/src/animation/backend/handler.cpp
index 406ac950b..daa98ed54 100644
--- a/src/animation/backend/handler.cpp
+++ b/src/animation/backend/handler.cpp
@@ -75,24 +75,28 @@ void Handler::setDirty(DirtyFlag flag, Qt3DCore::QNodeId nodeId)
{
switch (flag) {
case AnimationClipDirty: {
+ QMutexLocker lock(&m_mutex);
const auto handle = m_animationClipLoaderManager->lookupHandle(nodeId);
m_dirtyAnimationClips.push_back(handle);
break;
}
case ChannelMappingsDirty: {
+ QMutexLocker lock(&m_mutex);
const auto handle = m_channelMapperManager->lookupHandle(nodeId);
m_dirtyChannelMappers.push_back(handle);
break;
}
case ClipAnimatorDirty: {
+ QMutexLocker lock(&m_mutex);
const auto handle = m_clipAnimatorManager->lookupHandle(nodeId);
m_dirtyClipAnimators.push_back(handle);
break;
}
case BlendedClipAnimatorDirty: {
+ QMutexLocker lock(&m_mutex);
const HBlendedClipAnimator handle = m_blendedClipAnimatorManager->lookupHandle(nodeId);
m_dirtyBlendedAnimators.push_back(handle);
break;
@@ -172,6 +176,8 @@ QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
QVector<Qt3DCore::QAspectJobPtr> jobs;
+ QMutexLocker lock(&m_mutex);
+
// If there are any dirty animation clips that need loading,
// queue up a job for them
if (!m_dirtyAnimationClips.isEmpty()) {
diff --git a/src/animation/backend/handler_p.h b/src/animation/backend/handler_p.h
index 97adfdc13..467cd3a0e 100644
--- a/src/animation/backend/handler_p.h
+++ b/src/animation/backend/handler_p.h
@@ -53,6 +53,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -120,6 +121,7 @@ public:
void cleanupHandleList(QVector<HBlendedClipAnimator> *animators);
private:
+ QMutex m_mutex;
QScopedPointer<AnimationClipLoaderManager> m_animationClipLoaderManager;
QScopedPointer<ClipAnimatorManager> m_clipAnimatorManager;
QScopedPointer<BlendedClipAnimatorManager> m_blendedClipAnimatorManager;