summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/aspects/qaspectengine.cpp1
-rw-r--r--src/core/aspects/qaspectmanager.cpp9
-rw-r--r--src/core/aspects/qaspectmanager_p.h4
-rw-r--r--src/core/nodes/qnode_p.h2
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp61
5 files changed, 62 insertions, 15 deletions
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 6d1a8ca30..426741a61 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -275,6 +275,7 @@ void QAspectEnginePrivate::initialize()
arbiter->setPostman(m_postman);
arbiter->setScene(m_scene);
m_initialized = true;
+ m_aspectManager->setPostConstructorInit(m_scene->postConstructorInit());
#if QT_CONFIG(qt3d_profile_jobs)
m_commandDebugger->setAspectEngine(q_func());
m_commandDebugger->initialize();
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index 6bca77a9e..a33f771e9 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -374,6 +374,11 @@ QServiceLocator *QAspectManager::serviceLocator() const
return m_serviceLocator.data();
}
+void QAspectManager::setPostConstructorInit(NodePostConstructorInit *postConstructorInit)
+{
+ m_postConstructorInit = postConstructorInit;
+}
+
/*!
\internal
\brief Drives the Qt3D simulation loop in the main thread
@@ -429,6 +434,10 @@ void QAspectManager::processFrame()
changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
#endif
+ // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
+ // tree changes
+ m_postConstructorInit->processNodes();
+
// Add and Remove Nodes
const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
for (const NodeTreeChange &change : nodeTreeChanges) {
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index b39ad1f89..38ddbc55d 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -74,6 +74,7 @@ class QChangeArbiter;
class QAbstractAspect;
class QAbstractAspectJobManager;
class QServiceLocator;
+class NodePostConstructorInit;
struct NodeTreeChange;
class Q_3DCORE_PRIVATE_EXPORT QAspectManager : public QObject
@@ -105,6 +106,7 @@ public:
QAbstractAspectJobManager *jobManager() const;
QChangeArbiter *changeArbiter() const;
QServiceLocator *serviceLocator() const;
+ void setPostConstructorInit(NodePostConstructorInit *postConstructorInit);
private:
bool event(QEvent *event) override;
@@ -121,6 +123,8 @@ private:
bool m_simulationLoopRunning;
QAspectEngine::RunMode m_driveMode;
QVector<NodeTreeChange> m_nodeTreeChanges;
+ NodePostConstructorInit* m_postConstructorInit;
+
};
} // namespace Qt3DCore
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index 491059ff9..d8310731c 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -194,7 +194,7 @@ public:
void removeNode(QNode *node);
void addNode(QNode *node);
-private Q_SLOTS:
+public Q_SLOTS:
void processNodes();
private:
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 76c66604c..c5369ab3e 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -79,6 +79,7 @@ private slots:
void checkParentChangeFromExistingBackendParentToNewlyCreatedParent();
void checkBackendNodesCreatedFromTopDown(); //QTBUG-74106
void checkBackendNodesCreatedFromTopDownWithReparenting();
+ void checkAllBackendCreationDoneInSingleFrame();
void removingSingleChildNodeFromNode();
void removingMultipleChildNodesFromNode();
@@ -929,8 +930,6 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
MyQNode *child(new MyQNode(root.data()));
MyQNode *child2(new MyQNode(root.data()));
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// Due to the way we create root, it has a backend
@@ -961,8 +960,6 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QVERIFY(Qt3DCore::QNodePrivate::get(child)->scene() != nullptr);
// WHEN
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// THEN
@@ -1039,8 +1036,6 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QVERIFY(Qt3DCore::QNodePrivate::get(child)->scene() != nullptr);
// WHEN
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// THEN
@@ -1099,8 +1094,6 @@ void tst_Nodes::checkBackendNodesCreatedFromTopDown()
QCOMPARE(spy.events.count(), 0);
// WHEN - create the backend nodes
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// THEN
@@ -1159,8 +1152,6 @@ void tst_Nodes::checkBackendNodesCreatedFromTopDownWithReparenting()
auto parent1 = new MyQNode(parentWithBackend.data());
node1->setParent(parent1);
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// THEN
@@ -1175,8 +1166,6 @@ void tst_Nodes::checkBackendNodesCreatedFromTopDownWithReparenting()
node2->setParent(parent2);
parent2->setParent(parentWithBackend.get());
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
// THEN
@@ -1221,6 +1210,52 @@ void tst_Nodes::removingSingleChildNodeFromNode()
QCOMPARE(removalEvent->metaObject(), child->metaObject());
}
+void tst_Nodes::checkAllBackendCreationDoneInSingleFrame()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+
+ QScopedPointer<MyQEntity> root(new MyQEntity());
+ root->setArbiterAndEngine(&spy, &engine);
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ // Due to the way we create root, it has a backend
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode == true);
+ QCOMPARE(aspect->events.count(), 1);
+ QCOMPARE(aspect->events[0].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[0].nodeId, root->id());
+
+ // WHEN -> create 2 children:
+ // 1. a child with parent with backend node
+ // 2. a child with no parent that is then reparented to a parent with backend node
+ aspect->clearNodes();
+ auto child1 = new MyQNode(root.data());
+ auto child2 = new MyQNode;
+ child2->setParent(root.data());
+
+ // THEN - reparented child should have a backend node, but other child should
+ // still be waiting
+ QCOMPARE(child1->parent(), root.data());
+ QCOMPARE(child2->parent(), root.data());
+ QVERIFY(Qt3DCore::QNodePrivate::get(child1)->m_hasBackendNode == false);
+ QVERIFY(Qt3DCore::QNodePrivate::get(child2)->m_hasBackendNode == true);
+
+ // WHEN
+ QCoreApplication::processEvents();
+
+ // THEN - both children have their backend nodes actually created.
+ QCOMPARE(aspect->events.count(), 2);
+ QCOMPARE(aspect->events[0].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[0].nodeId, child2->id());
+ QCOMPARE(aspect->events[1].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[1].nodeId, child1->id());
+}
+
void tst_Nodes::removingMultipleChildNodesFromNode()
{
// GIVEN
@@ -1329,8 +1364,6 @@ void tst_Nodes::checkConstructionSetParentMix()
}
// THEN
- // processEvents 2x because the postConstructorInit happens after the frame advance.
- QCoreApplication::processEvents();
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
QCOMPARE(subTreeRoot->children().count(), 100);