summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/animation/backend/animationclip.cpp39
-rw-r--r--src/animation/backend/animationclip_p.h4
-rw-r--r--src/animation/frontend/qanimationclip.cpp30
-rw-r--r--src/animation/frontend/qanimationclip.h4
-rw-r--r--src/animation/frontend/qanimationclip_p.h5
-rw-r--r--tests/auto/animation/animationclip/tst_animationclip.cpp34
-rw-r--r--tests/auto/animation/qanimationclip/tst_qanimationclip.cpp1
-rw-r--r--tests/manual/animation-keyframe-simple/main.qml2
8 files changed, 118 insertions, 1 deletions
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index c7d262507..ae34fa64c 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -40,6 +40,7 @@
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
@@ -53,11 +54,12 @@ namespace Qt3DAnimation {
namespace Animation {
AnimationClip::AnimationClip()
- : BackendNode(ReadOnly)
+ : BackendNode(ReadWrite)
, m_source()
, m_name()
, m_objectName()
, m_channelGroups()
+ , m_duration(0.0f)
{
}
@@ -75,6 +77,8 @@ void AnimationClip::cleanup()
setEnabled(false);
m_handler = nullptr;
m_source.clear();
+ m_channelGroups.clear();
+ m_duration = 0.0f;
clearData();
}
@@ -139,9 +143,28 @@ void AnimationClip::loadAnimation()
m_channelGroups[i].read(group);
}
+ const float t = findDuration();
+ setDuration(t);
+
qCDebug(Jobs) << "Loaded animation data:" << *this;
}
+void AnimationClip::setDuration(float duration)
+{
+ if (qFuzzyCompare(duration, m_duration))
+ return;
+
+ m_duration = duration;
+
+ // Send a change to the frontend
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
+ e->setPropertyName("duration");
+ e->setValue(m_duration);
+ notifyObservers(e);
+}
+
void AnimationClip::clearData()
{
m_name.clear();
@@ -149,6 +172,20 @@ void AnimationClip::clearData()
m_channelGroups.clear();
}
+float AnimationClip::findDuration()
+{
+ // Iterate over the contained fcurves and find the longest one
+ double tMax = 0.0;
+ for (const auto channelGroup : qAsConst(m_channelGroups)) {
+ for (const auto channel : qAsConst(channelGroup.channels)) {
+ const float t = channel.fcurve.endTime();
+ if (t > tMax)
+ tMax = t;
+ }
+ }
+ return tMax;
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/animationclip_p.h b/src/animation/backend/animationclip_p.h
index 6170c3423..ddfe7e875 100644
--- a/src/animation/backend/animationclip_p.h
+++ b/src/animation/backend/animationclip_p.h
@@ -75,16 +75,20 @@ public:
// Called from jobs
void loadAnimation();
+ void setDuration(float duration);
+ float duration() const { return m_duration; }
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
void clearData();
+ float findDuration();
QUrl m_source;
QString m_name;
QString m_objectName;
QVector<ChannelGroup> m_channelGroups;
+ float m_duration;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/animation/frontend/qanimationclip.cpp b/src/animation/frontend/qanimationclip.cpp
index 527f1cc30..56fe3978c 100644
--- a/src/animation/frontend/qanimationclip.cpp
+++ b/src/animation/frontend/qanimationclip.cpp
@@ -36,6 +36,7 @@
#include "qanimationclip.h"
#include "qanimationclip_p.h"
+#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -43,9 +44,22 @@ namespace Qt3DAnimation {
QAnimationClipPrivate::QAnimationClipPrivate()
: Qt3DCore::QNodePrivate()
+ , m_duration(0.0f)
{
}
+void QAnimationClipPrivate::setDuration(float duration)
+{
+ if (qFuzzyCompare(duration, m_duration))
+ return;
+
+ Q_Q(QAnimationClip);
+ bool wasBlocked = q->blockNotifications(true);
+ m_duration = duration;
+ emit q->durationChanged(duration);
+ q->blockNotifications(wasBlocked);
+}
+
QAnimationClip::QAnimationClip(Qt3DCore::QNode *parent)
: Qt3DCore::QNode(*new QAnimationClipPrivate, parent)
{
@@ -66,6 +80,12 @@ QUrl QAnimationClip::source() const
return d->m_source;
}
+float QAnimationClip::duration() const
+{
+ Q_D(const QAnimationClip);
+ return d->m_duration;
+}
+
void QAnimationClip::setSource(QUrl source)
{
Q_D(QAnimationClip);
@@ -76,6 +96,16 @@ void QAnimationClip::setSource(QUrl source)
emit sourceChanged(source);
}
+void QAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QAnimationClip);
+ if (change->type() == Qt3DCore::PropertyUpdated) {
+ Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->propertyName() == QByteArrayLiteral("duration"))
+ d->setDuration(e->value().toFloat());
+ }
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QAnimationClip::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipData>::create(this);
diff --git a/src/animation/frontend/qanimationclip.h b/src/animation/frontend/qanimationclip.h
index f5394f8ff..55b1910fa 100644
--- a/src/animation/frontend/qanimationclip.h
+++ b/src/animation/frontend/qanimationclip.h
@@ -51,21 +51,25 @@ class QT3DANIMATIONSHARED_EXPORT QAnimationClip : public Qt3DCore::QNode
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(float duration READ duration NOTIFY durationChanged)
public:
explicit QAnimationClip(Qt3DCore::QNode *parent = nullptr);
~QAnimationClip();
QUrl source() const;
+ float duration() const;
public Q_SLOTS:
void setSource(QUrl source);
Q_SIGNALS:
void sourceChanged(QUrl source);
+ void durationChanged(float duration);
protected:
QAnimationClip(QAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
private:
Q_DECLARE_PRIVATE(QAnimationClip)
diff --git a/src/animation/frontend/qanimationclip_p.h b/src/animation/frontend/qanimationclip_p.h
index 87ebf99e1..5e3df0e6e 100644
--- a/src/animation/frontend/qanimationclip_p.h
+++ b/src/animation/frontend/qanimationclip_p.h
@@ -62,7 +62,12 @@ public:
Q_DECLARE_PUBLIC(QAnimationClip)
+ void setDuration(float duration);
+
QUrl m_source;
+
+ // Set from the backend
+ float m_duration;
};
struct QAnimationClipData
diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp
index cd1d2ccf0..f0b45bfeb 100644
--- a/tests/auto/animation/animationclip/tst_animationclip.cpp
+++ b/tests/auto/animation/animationclip/tst_animationclip.cpp
@@ -33,6 +33,7 @@
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -71,6 +72,7 @@ private Q_SLOTS:
QVERIFY(backendClip.peerId().isNull());
QCOMPARE(backendClip.isEnabled(), false);
QCOMPARE(backendClip.source(), QUrl());
+ QCOMPARE(backendClip.duration(), 0.0f);
// GIVEN
Qt3DAnimation::QAnimationClip clip;
@@ -84,6 +86,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendClip.source(), QUrl());
QCOMPARE(backendClip.isEnabled(), false);
+ QCOMPARE(backendClip.duration(), 0.0f);
}
void checkPropertyChanges()
@@ -113,6 +116,37 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendClip.source(), newSource);
}
+
+ void checkDurationPropertyBackendNotification()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DAnimation::Animation::AnimationClip backendClip;
+ backendClip.setEnabled(true);
+ Qt3DCore::QBackendNodePrivate::get(&backendClip)->setArbiter(&arbiter);
+
+ // WHEN
+ backendClip.setDuration(64.0f);
+
+ // THEN
+ QCOMPARE(backendClip.duration(), 64.0f);
+ QCOMPARE(arbiter.events.count(), 1);
+ Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "duration");
+ QCOMPARE(change->value().toFloat(), backendClip.duration());
+ QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isFinal, true);
+
+ arbiter.events.clear();
+
+ // WHEN
+ backendClip.setDuration(64.0f);
+
+ // THEN
+ QCOMPARE(backendClip.duration(), 64.0f);
+ QCOMPARE(arbiter.events.count(), 0);
+
+ arbiter.events.clear();
+ }
};
QTEST_APPLESS_MAIN(tst_AnimationClip)
diff --git a/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp b/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp
index 09f41ae99..8c83f6530 100644
--- a/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp
+++ b/tests/auto/animation/qanimationclip/tst_qanimationclip.cpp
@@ -49,6 +49,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(clip.source(), QUrl());
+ QCOMPARE(clip.duration(), 0.0f);
}
void checkPropertyChanges()
diff --git a/tests/manual/animation-keyframe-simple/main.qml b/tests/manual/animation-keyframe-simple/main.qml
index 587f851c5..e53772434 100644
--- a/tests/manual/animation-keyframe-simple/main.qml
+++ b/tests/manual/animation-keyframe-simple/main.qml
@@ -35,6 +35,8 @@ DefaultSceneEntity {
running: true
clip: AnimationClip {
source: "cubeanimation.json"
+
+ onDurationChanged: console.log("duration = " + duration)
}
// By default introspect parent Entity and try