summaryrefslogtreecommitdiffstats
path: root/src/core/nodes
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-04-02 15:08:50 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-04-02 15:25:12 +0200
commitf3259300bde381b10cb737735fe19b039c969782 (patch)
tree43c70cfe34cbf08947752653e98ccb777c1c9521 /src/core/nodes
parent6f7ac29268df048b5f23ad26c47efcbfdfdb3585 (diff)
parent59d26d3e9411150c7ed0fb0cf68d48988c8dbf59 (diff)
Merge branch '5.12' into 5.13
Diffstat (limited to 'src/core/nodes')
-rw-r--r--src/core/nodes/qentity.cpp2
-rw-r--r--src/core/nodes/qnode.cpp35
-rw-r--r--src/core/nodes/qnode_p.h1
3 files changed, 32 insertions, 6 deletions
diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp
index 3c8805a67..69d774dd1 100644
--- a/src/core/nodes/qentity.cpp
+++ b/src/core/nodes/qentity.cpp
@@ -159,6 +159,8 @@ void QEntity::addComponent(QComponent *comp)
if (!comp->parent())
comp->setParent(this);
+ QNodePrivate::get(comp)->_q_ensureBackendNodeCreated();
+
d->m_components.append(comp);
// Ensures proper bookkeeping
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index 83ac49471..c2373b805 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -394,15 +394,15 @@ void QNodePrivate::propertyChanged(int propertyIndex)
if (data.canConvert<QNode*>()) {
QNode *node = data.value<QNode*>();
- // Ensure the node has issued a node creation change. We can end
- // up here if a newly created node with a parent is immediately set
+ // Ensure the node and all ancestors have issued their node creation changes.
+ // We can end up here if a newly created node with a parent is immediately set
// as a property on another node. In this case the deferred call to
// _q_postConstructorInit() will not have happened yet as the event
- // loop will still be blocked. So force it here and we catch this
- // eventuality in the _q_postConstructorInit() function so that we
- // do not repeat the creation and new child scene change events.
+ // loop will still be blocked. We need to do this for all ancestors,
+ // since the subtree of this node otherwise can end up on the backend
+ // with a reference to a non-existent parent.
if (node)
- QNodePrivate::get(node)->_q_postConstructorInit();
+ QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
const QNodeId id = node ? node->id() : QNodeId();
return QVariant::fromValue(id);
@@ -506,6 +506,29 @@ void QNodePrivate::setArbiter(QLockableObserverInterface *arbiter)
}
/*!
+ * \internal
+ * Makes sure this node has a backend by traversing the tree up to the most distant ancestor
+ * without a backend node and initializing that node. This is done to make sure the parent nodes
+ * are always created before the child nodes, since child nodes reference parent nodes at creation
+ * time.
+ */
+void QNodePrivate::_q_ensureBackendNodeCreated()
+{
+ if (m_hasBackendNode)
+ return;
+
+ Q_Q(QNode);
+
+ QNode *nextNode = q;
+ QNode *topNodeWithoutBackend = nullptr;
+ while (nextNode != nullptr && !QNodePrivate::get(nextNode)->m_hasBackendNode) {
+ topNodeWithoutBackend = nextNode;
+ nextNode = nextNode->parentNode();
+ }
+ QNodePrivate::get(topNodeWithoutBackend)->_q_postConstructorInit();
+}
+
+/*!
\class Qt3DCore::QNode
\inherits QObject
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index 73893cc1e..6ffb19ce8 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -152,6 +152,7 @@ public:
static const QMetaObject *findStaticMetaObject(const QMetaObject *metaObject);
void _q_postConstructorInit();
+ void _q_ensureBackendNodeCreated();
private:
void notifyCreationChange();