summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2017-01-24 10:43:32 +0100
committerPaul Lemire <paul.lemire@kdab.com>2017-01-25 14:56:43 +0000
commit393ab950be4a622dc2616c061eeb4f2194991093 (patch)
treea8e83bb510c9cc58c1461eb2345f122925e09c34 /src
parent4f6bf6d53c50221977d3f6e2c04ced70d815e6ac (diff)
Allow to filter change events based on a track property
* QNode now has a PropertyTrackMode property * QScene contains a table of PropertyTrakcMode data * QPostman checks if a QNode is supposed to receive a change based on the information available in the QScene property track mode table * Unit tests updated and added for QPostman Change-Id: I3b88037a949020a917c81817f1451ef532065982 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/changes/qpropertyupdatedchangebase.cpp6
-rw-r--r--src/core/changes/qpropertyupdatedchangebase_p.h3
-rw-r--r--src/core/core.pri3
-rw-r--r--src/core/nodes/qnode.cpp73
-rw-r--r--src/core/nodes/qnode.h16
-rw-r--r--src/core/nodes/qnode_p.h3
-rw-r--r--src/core/qchangearbiter.cpp6
-rw-r--r--src/core/qchangearbiter_p.h8
-rw-r--r--src/core/qpostman.cpp44
-rw-r--r--src/core/qpostman_p.h4
-rw-r--r--src/core/qpostman_p_p.h85
-rw-r--r--src/core/qscene.cpp23
-rw-r--r--src/core/qscene_p.h12
-rw-r--r--src/render/geometry/buffer.cpp2
-rw-r--r--src/render/io/scene.cpp3
15 files changed, 264 insertions, 27 deletions
diff --git a/src/core/changes/qpropertyupdatedchangebase.cpp b/src/core/changes/qpropertyupdatedchangebase.cpp
index 18f2039fc..d33c737e5 100644
--- a/src/core/changes/qpropertyupdatedchangebase.cpp
+++ b/src/core/changes/qpropertyupdatedchangebase.cpp
@@ -46,6 +46,7 @@ namespace Qt3DCore {
QPropertyUpdatedChangeBasePrivate::QPropertyUpdatedChangeBasePrivate()
: QSceneChangePrivate()
+ , m_isFinal(false)
{
}
@@ -53,6 +54,11 @@ QPropertyUpdatedChangeBasePrivate::~QPropertyUpdatedChangeBasePrivate()
{
}
+QPropertyUpdatedChangeBasePrivate *QPropertyUpdatedChangeBasePrivate::get(QPropertyUpdatedChangeBase *q)
+{
+ return q->d_func();
+}
+
/*!
* \class Qt3DCore::QPropertyUpdatedChangeBase
* \inheaderfile Qt3DCore/QPropertyUpdatedChangeBase
diff --git a/src/core/changes/qpropertyupdatedchangebase_p.h b/src/core/changes/qpropertyupdatedchangebase_p.h
index 314b1ea15..3c32b2237 100644
--- a/src/core/changes/qpropertyupdatedchangebase_p.h
+++ b/src/core/changes/qpropertyupdatedchangebase_p.h
@@ -66,7 +66,10 @@ public:
QPropertyUpdatedChangeBasePrivate();
virtual ~QPropertyUpdatedChangeBasePrivate();
+ static QPropertyUpdatedChangeBasePrivate *get(QPropertyUpdatedChangeBase *q);
+
Q_DECLARE_PUBLIC(QPropertyUpdatedChangeBase)
+ bool m_isFinal;
};
} // namespace Qt3DCore
diff --git a/src/core/core.pri b/src/core/core.pri
index becdbb282..458a0328d 100644
--- a/src/core/core.pri
+++ b/src/core/core.pri
@@ -13,7 +13,8 @@ HEADERS += \
$$PWD/qchangearbiter_p.h \
$$PWD/qbackendnodefactory_p.h \
$$PWD/qt3dcore_global_p.h \
- $$PWD/qscene_p.h
+ $$PWD/qscene_p.h \
+ $$PWD/qpostman_p_p.h
SOURCES += \
$$PWD/qtickclock.cpp \
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index e4bb5d4a3..77d7c0a6b 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -73,6 +73,7 @@ QNodePrivate::QNodePrivate()
, m_blockNotifications(false)
, m_hasBackendNode(false)
, m_enabled(true)
+ , m_propertyTrackMode(QNode::DefaultTrackMode)
, m_propertyChangesSetup(false)
, m_signals(this)
{
@@ -402,7 +403,6 @@ void QNodePrivate::unsetSceneHelper(QNode *root)
m_scene->removeEntityForComponent(c->id(), entity->id());
}
}
-
if (m_scene != nullptr)
m_scene->removeObservable(root);
root->d_func()->setScene(nullptr);
@@ -495,8 +495,13 @@ void QNode::sceneChangeEvent(const QSceneChangePtr &change)
*/
void QNodePrivate::setScene(QScene *scene)
{
- if (m_scene != scene)
+ if (m_scene != scene) {
+ if (m_scene != nullptr)
+ m_scene->removePropertyTrackDataForNode(m_id);
m_scene = scene;
+ // set PropertyTrackData in the scene
+ updatePropertyTrackMode();
+ }
}
/*!
@@ -580,6 +585,16 @@ void QNodePrivate::insertTree(QNode *treeRoot, int depth)
treeRoot->setParent(q_func());
}
+void QNodePrivate::updatePropertyTrackMode()
+{
+ if (m_scene != nullptr) {
+ QScene::NodePropertyTrackData trackData;
+ trackData.updateMode = m_propertyTrackMode;
+ trackData.namedProperties = m_trackedProperties;
+ m_scene->setPropertyTrackDataForNode(m_id,trackData);
+ }
+}
+
/*!
\internal
*/
@@ -769,6 +784,34 @@ void QNode::setEnabled(bool isEnabled)
emit enabledChanged(isEnabled);
}
+void QNode::setPropertyTrackMode(QNode::PropertyTrackMode mode)
+{
+ Q_D(QNode);
+ if (d->m_propertyTrackMode == mode)
+ return;
+
+ d->m_propertyTrackMode = mode;
+ // The backend doesn't care about such notification
+ const bool blocked = blockNotifications(true);
+ emit propertyUpdateModeChanged(mode);
+ blockNotifications(blocked);
+ d->updatePropertyTrackMode();
+}
+
+void QNode::setTrackedProperties(const QStringList &trackedProperties)
+{
+ Q_D(QNode);
+ if (d->m_trackedProperties == trackedProperties)
+ return;
+
+ d->m_trackedProperties = trackedProperties;
+ // The backend doesn't care about such notification
+ const bool blocked = blockNotifications(true);
+ emit trackedPropertiesChanged(trackedProperties);
+ blockNotifications(blocked);
+ d->updatePropertyTrackMode();
+}
+
/*!
\property Qt3DCore::QNode::enabled
@@ -785,6 +828,32 @@ bool QNode::isEnabled() const
return d->m_enabled;
}
+/*!
+ \property Qt3DCore::QNode::propertyTrackMode
+
+ Holds the property track mode which determines whether a QNode should
+ be listening for property updates
+
+ By default it is set to QNode::DontTrackProperties
+*/
+QNode::PropertyTrackMode QNode::propertyTrackMode() const
+{
+ Q_D(const QNode);
+ return d->m_propertyTrackMode;
+}
+
+/*!
+ \property Qt3DCore::QNode::trackedProperties
+
+ Holds the names of the properties to be tracked when propertyTrackMode is
+ set to TrackNamedProperties.
+*/
+QStringList QNode::trackedProperties() const
+{
+ Q_D(const QNode);
+ return d->m_trackedProperties;
+}
+
QNodeCreatedChangeBasePtr QNode::createNodeCreationChange() const
{
// Uncomment this when implementing new frontend and backend types.
diff --git a/src/core/nodes/qnode.h b/src/core/nodes/qnode.h
index cadcc7d5c..75ea61cc7 100644
--- a/src/core/nodes/qnode.h
+++ b/src/core/nodes/qnode.h
@@ -69,7 +69,17 @@ class QT3DCORESHARED_EXPORT QNode : public QObject
Q_OBJECT
Q_PROPERTY(Qt3DCore::QNode *parent READ parentNode WRITE setParent NOTIFY parentChanged)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(PropertyTrackMode propertyTrackMode READ propertyTrackMode WRITE setPropertyTrackMode NOTIFY propertyUpdateModeChanged)
+ Q_PROPERTY(QStringList trackedProperties READ trackedProperties WRITE setTrackedProperties NOTIFY trackedPropertiesChanged)
public:
+
+ enum PropertyTrackMode {
+ DefaultTrackMode,
+ TrackNamedPropertiesMode,
+ TrackAllPropertiesMode
+ };
+ Q_ENUM(PropertyTrackMode)
+
explicit QNode(QNode *parent = nullptr);
virtual ~QNode();
@@ -82,14 +92,20 @@ public:
QNodeVector childNodes() const;
bool isEnabled() const;
+ PropertyTrackMode propertyTrackMode() const;
+ QStringList trackedProperties() const;
public Q_SLOTS:
void setParent(QNode *parent);
void setEnabled(bool isEnabled);
+ void setPropertyTrackMode(PropertyTrackMode mode);
+ void setTrackedProperties(const QStringList &trackedProperties);
Q_SIGNALS:
void parentChanged(QObject *parent);
void enabledChanged(bool enabled);
+ void propertyUpdateModeChanged(PropertyTrackMode mode);
+ void trackedPropertiesChanged(const QStringList &trackedProperties);
void nodeDestroyed();
protected:
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index a90011128..5d6329e62 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -84,6 +84,7 @@ public:
void notifyObservers(const QSceneChangePtr &change) Q_DECL_OVERRIDE;
void insertTree(QNode *treeRoot, int depth = 0);
+ void updatePropertyTrackMode();
Q_DECLARE_PUBLIC(QNode)
@@ -97,6 +98,8 @@ public:
bool m_blockNotifications;
bool m_hasBackendNode;
bool m_enabled;
+ QNode::PropertyTrackMode m_propertyTrackMode;
+ QStringList m_trackedProperties;
static QNodePrivate *get(QNode *q);
static void nodePtrDeleter(QNode *q);
diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp
index 3bd3f69e8..a7ca3ed40 100644
--- a/src/core/qchangearbiter.cpp
+++ b/src/core/qchangearbiter.cpp
@@ -132,9 +132,11 @@ void QChangeArbiter::distributeQueueChanges(QChangeQueue *changeQueue)
(change->deliveryFlags() & QSceneChange::BackendNodes))
observer.second->sceneChangeEvent(change);
}
+ // Also send change to the postman
if (change->deliveryFlags() & QSceneChange::Nodes) {
- // Also send change to the postman
- m_postman->sceneChangeEvent(change);
+ // Check if QNode actually cares about the change
+ if (m_postman->shouldNotifyFrontend(change))
+ m_postman->sceneChangeEvent(change);
}
}
}
diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h
index e3fdcad9b..e381abc65 100644
--- a/src/core/qchangearbiter_p.h
+++ b/src/core/qchangearbiter_p.h
@@ -136,14 +136,8 @@ private:
QMutex m_mutex;
QAbstractAspectJobManager *m_jobManager;
- // The lists of observers indexed by observable. We maintain two
- // distinct hashes:
- //
- // m_aspectObservations is for observables owned by aspects
+ // The lists of observers indexed by observable (QNodeId).
// m_nodeObservations is for observables in the main thread's object tree
- //
- // We keep these distinct because we do not manage the main thread which means
- // the mechanisms for working with objects there is different.
QHash<QNodeId, QObserverList> m_nodeObservations;
QList<QSceneObserverInterface *> m_sceneObservers;
diff --git a/src/core/qpostman.cpp b/src/core/qpostman.cpp
index ac78450c6..2b8e6c3a8 100644
--- a/src/core/qpostman.cpp
+++ b/src/core/qpostman.cpp
@@ -38,30 +38,22 @@
****************************************************************************/
#include "qpostman_p.h"
-#include <private/qobject_p.h>
+#include "qpostman_p_p.h"
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
#include <Qt3DCore/qnode.h>
#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QPostmanPrivate : public QObjectPrivate
+QPostmanPrivate *QPostmanPrivate::get(QPostman *q)
{
-public:
- QPostmanPrivate()
- : QObjectPrivate()
- , m_scene(nullptr)
- {
- }
-
- Q_DECLARE_PUBLIC(QPostman)
- QScene *m_scene;
- std::vector<QSceneChangePtr> m_batch;
-};
+ return q->d_func();
+}
QPostman::QPostman(QObject *parent)
: QObject(*new QPostmanPrivate, parent)
@@ -118,6 +110,32 @@ void QPostman::notifyBackend(const QSceneChangePtr &change)
d->m_batch.push_back(change);
}
+// AspectThread
+bool QPostman::shouldNotifyFrontend(const QSceneChangePtr &e)
+{
+ Q_D(QPostman);
+ const QPropertyUpdatedChangePtr propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e);
+ if (Q_LIKELY(d->m_scene != nullptr) && !propertyChange.isNull()) {
+ const bool isFinal = QPropertyUpdatedChangeBasePrivate::get(propertyChange.data())->m_isFinal;
+ if (isFinal)
+ return true;
+ const QScene::NodePropertyTrackData propertyTrackData = d->m_scene->lookupNodePropertyTrackData(e->subjectId());
+ switch (propertyTrackData.updateMode) {
+ case QNode::TrackAllPropertiesMode:
+ return true;
+ case QNode::TrackNamedPropertiesMode:
+ return propertyTrackData.namedProperties.contains(QLatin1String(propertyChange->propertyName()));
+ case QNode::DefaultTrackMode:
+ return false;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+ }
+ return true;
+}
+
+// Main Thread
void QPostman::notifyFrontendNode(const QSceneChangePtr &e)
{
Q_D(QPostman);
diff --git a/src/core/qpostman_p.h b/src/core/qpostman_p.h
index 4fe788960..cbc4048ce 100644
--- a/src/core/qpostman_p.h
+++ b/src/core/qpostman_p.h
@@ -66,9 +66,10 @@ class QT3DCORE_PRIVATE_EXPORT QAbstractPostman : public QObserverInterface
public:
virtual void setScene(QScene *sceneLookup) = 0;
virtual void notifyBackend(const QSceneChangePtr &change) = 0;
+ virtual bool shouldNotifyFrontend(const QSceneChangePtr &change) = 0;
};
-class QPostman Q_DECL_FINAL
+class Q_AUTOTEST_EXPORT QPostman Q_DECL_FINAL
: public QObject
, public QAbstractPostman
{
@@ -80,6 +81,7 @@ public:
void setScene(QScene *sceneLookup) Q_DECL_FINAL;
void sceneChangeEvent(const QSceneChangePtr &e) Q_DECL_FINAL;
void notifyBackend(const QSceneChangePtr &change) Q_DECL_FINAL;
+ bool shouldNotifyFrontend(const QSceneChangePtr &e) Q_DECL_FINAL;
public Q_SLOTS:
void submitChangeBatch();
diff --git a/src/core/qpostman_p_p.h b/src/core/qpostman_p_p.h
new file mode 100644
index 000000000..1b5cca3c9
--- /dev/null
+++ b/src/core/qpostman_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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_QPOSTMAN_P_P_H
+#define QT3DCORE_QPOSTMAN_P_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/qscenechange.h>
+#include <private/qobject_p.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+class QScene;
+class QPostman;
+
+class QT3DCORE_PRIVATE_EXPORT QPostmanPrivate : public QObjectPrivate
+{
+public:
+ QPostmanPrivate()
+ : QObjectPrivate()
+ , m_scene(nullptr)
+ {
+ }
+
+ static QPostmanPrivate *get(QPostman *q);
+
+ Q_DECLARE_PUBLIC(QPostman)
+ QScene *m_scene;
+ std::vector<QSceneChangePtr> m_batch;
+};
+
+} // Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_QPOSTMAN_P_P_H
diff --git a/src/core/qscene.cpp b/src/core/qscene.cpp
index 42c3a2bc8..972659131 100644
--- a/src/core/qscene.cpp
+++ b/src/core/qscene.cpp
@@ -63,8 +63,10 @@ public:
QMultiHash<QNodeId, QNodeId> m_componentToEntities;
QMultiHash<QNodeId, QObservableInterface *> m_observablesLookupTable;
QHash<QObservableInterface *, QNodeId> m_observableToUuid;
+ QHash<QNodeId, QScene::NodePropertyTrackData> m_nodePropertyTrackModeLookupTable;
QLockableObserverInterface *m_arbiter;
mutable QReadWriteLock m_lock;
+ mutable QReadWriteLock m_nodePropertyTrackModeLock;
};
@@ -213,6 +215,27 @@ bool QScene::hasEntityForComponent(QNodeId componentUuid, QNodeId entityUuid)
return d->m_componentToEntities.values(componentUuid).contains(entityUuid);
}
+QScene::NodePropertyTrackData QScene::lookupNodePropertyTrackData(QNodeId id) const
+{
+ Q_D(const QScene);
+ QReadLocker lock(&d->m_nodePropertyTrackModeLock);
+ return d->m_nodePropertyTrackModeLookupTable.value(id);
+}
+
+void QScene::setPropertyTrackDataForNode(QNodeId nodeId, const QScene::NodePropertyTrackData &data)
+{
+ Q_D(QScene);
+ QWriteLocker lock(&d->m_nodePropertyTrackModeLock);
+ d->m_nodePropertyTrackModeLookupTable.insert(nodeId, data);
+}
+
+void QScene::removePropertyTrackDataForNode(QNodeId nodeId)
+{
+ Q_D(QScene);
+ QWriteLocker lock(&d->m_nodePropertyTrackModeLock);
+ d->m_nodePropertyTrackModeLookupTable.remove(nodeId);
+}
+
} // Qt3D
QT_END_NAMESPACE
diff --git a/src/core/qscene_p.h b/src/core/qscene_p.h
index 6b4009538..1a313c249 100644
--- a/src/core/qscene_p.h
+++ b/src/core/qscene_p.h
@@ -53,13 +53,13 @@
#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/private/qobservableinterface_p.h>
+#include <Qt3DCore/qnode.h>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QNode;
class QScenePrivate;
class QAspectEngine;
@@ -92,6 +92,16 @@ public:
void removeEntityForComponent(QNodeId componentUuid, QNodeId entityUuid);
bool hasEntityForComponent(QNodeId componentUuid, QNodeId entityUuid);
+ // Node -> Property Update Data
+ struct NodePropertyTrackData
+ {
+ QNode::PropertyTrackMode updateMode = QNode::DefaultTrackMode;
+ QStringList namedProperties;
+ };
+ NodePropertyTrackData lookupNodePropertyTrackData(QNodeId id) const;
+ void setPropertyTrackDataForNode(QNodeId id, const NodePropertyTrackData &data);
+ void removePropertyTrackDataForNode(QNodeId id);
+
private:
Q_DECLARE_PRIVATE(QScene)
QScopedPointer<QScenePrivate> d_ptr;
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index aaae9825f..df0bc3c92 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -41,6 +41,7 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/qbuffer_p.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -92,6 +93,7 @@ void Buffer::executeFunctor()
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("data");
e->setValue(QVariant::fromValue(m_data));
+ Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
}
diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp
index cf1ca4736..2057ffd3d 100644
--- a/src/render/io/scene.cpp
+++ b/src/render/io/scene.cpp
@@ -46,6 +46,7 @@
#include <Qt3DRender/private/qsceneloader_p.h>
#include <Qt3DRender/private/scenemanager_p.h>
#include <QtCore/qcoreapplication.h>
+#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +73,7 @@ void Scene::setStatus(QSceneLoader::Status status)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("status");
e->setValue(QVariant::fromValue(status));
+ Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}
@@ -114,6 +116,7 @@ void Scene::setSceneSubtree(Qt3DCore::QEntity *subTree)
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
e->setPropertyName("scene");
e->setValue(QVariant::fromValue(subTree));
+ Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isFinal = true;
notifyObservers(e);
}