From a56aaeed5f09bfa5d32fa7b40ec8782414998daa Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Sun, 2 Nov 2014 16:10:12 +0000 Subject: QAspectEngine owns the root of the scene The scene root is now also enforced to be a QEntity as that is what we were checking for in the backend anyway as it is impossible to create a plain QNode. This is another step towards solving the shutdown crashing bug. Change-Id: I8508afa80ec9e99954ab867be1ed28bc35405e79 Reviewed-by: Paul Lemire --- examples/bigscene-cpp/main.cpp | 2 +- examples/cpp_example/main.cpp | 3 +-- examples/cylinder-cpp/main.cpp | 3 +-- examples/deferred-renderer-cpp/main.cpp | 3 +-- examples/simple-cpp/main.cpp | 2 +- examples/torus-cpp/main.cpp | 3 +-- src/core/aspects/qaspectengine.cpp | 38 +++++++++++++++++++++++++++------ src/core/aspects/qaspectengine.h | 7 ++++-- src/core/aspects/qaspectengine_p.h | 6 +++--- src/core/aspects/qaspectmanager.cpp | 7 +----- src/core/aspects/qaspectmanager_p.h | 2 +- src/core/window.cpp | 12 ++--------- src/core/window.h | 12 ++++------- src/quick3d/quick3d/quickwindow.cpp | 19 +++++++++++------ 14 files changed, 66 insertions(+), 53 deletions(-) diff --git a/examples/bigscene-cpp/main.cpp b/examples/bigscene-cpp/main.cpp index b7b6561bc..6d252c459 100644 --- a/examples/bigscene-cpp/main.cpp +++ b/examples/bigscene-cpp/main.cpp @@ -136,7 +136,7 @@ int main(int ac, char **av) e->setParent(root); } - view.setRootObject(root); + view.setRootEntity(root); view.show(); return app.exec(); } diff --git a/examples/cpp_example/main.cpp b/examples/cpp_example/main.cpp index d6d590955..22c1218b9 100644 --- a/examples/cpp_example/main.cpp +++ b/examples/cpp_example/main.cpp @@ -148,8 +148,7 @@ int main(int ac, char **av) rootEntity->addComponent(frameGraph); // Set root object of the scene - view.setRootObject(rootEntity); - // Show window + view.setRootEntity(rootEntity); view.show(); return app.exec(); diff --git a/examples/cylinder-cpp/main.cpp b/examples/cylinder-cpp/main.cpp index c11435346..20800f389 100644 --- a/examples/cylinder-cpp/main.cpp +++ b/examples/cylinder-cpp/main.cpp @@ -132,8 +132,7 @@ int main(int argc, char **argv) rootEntity->addComponent(frameGraph); // Set root object of the scene - view.setRootObject(rootEntity); - // Show window + view.setRootEntity(rootEntity); view.show(); return app.exec(); diff --git a/examples/deferred-renderer-cpp/main.cpp b/examples/deferred-renderer-cpp/main.cpp index d91029a2f..0d0c065b9 100644 --- a/examples/deferred-renderer-cpp/main.cpp +++ b/examples/deferred-renderer-cpp/main.cpp @@ -185,8 +185,7 @@ int main(int ac, char **av) screenQuad->addComponent(planeMesh); // Set root object of the scene - view.setRootObject(rootEntity); - // Show window + view.setRootEntity(rootEntity); view.show(); return app.exec(); diff --git a/examples/simple-cpp/main.cpp b/examples/simple-cpp/main.cpp index 44313ebca..3bd32f720 100644 --- a/examples/simple-cpp/main.cpp +++ b/examples/simple-cpp/main.cpp @@ -165,7 +165,7 @@ int main(int argc, char* argv[]) rootEntity->addComponent(frameGraph); - view.setRootObject(rootEntity); + view.setRootEntity(rootEntity); view.show(); return app.exec(); diff --git a/examples/torus-cpp/main.cpp b/examples/torus-cpp/main.cpp index a26a9d581..98b457c78 100644 --- a/examples/torus-cpp/main.cpp +++ b/examples/torus-cpp/main.cpp @@ -132,8 +132,7 @@ int main(int argc, char **argv) rootEntity->addComponent(frameGraph); // Set root object of the scene - view.setRootObject(rootEntity); - // Show window + view.setRootEntity(rootEntity); view.show(); return app.exec(); diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index dea6987f3..ad7339b20 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -69,7 +69,7 @@ QAspectEnginePrivate::QAspectEnginePrivate(QAspectEngine *qq) m_postman->setScene(m_scene); qRegisterMetaType(); qRegisterMetaType(); - qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); } @@ -157,18 +157,44 @@ void QAspectEngine::registerAspect(QAbstractAspect *aspect) Q_ARG(Qt3D::QAbstractAspect *, aspect)); } -void QAspectEngine::setRoot(QNode *rootObject) +void QAspectEngine::setRootEntity(QEntity *root) { - Q_D(QAspectEngine); qCDebug(Aspects) << "Setting scene root on aspect manager"; - initNodeTree(rootObject); + Q_D(QAspectEngine); + if (d->m_root == root) + return; + + // Set the new root object. This will cause the old tree to be deleted + // and the deletion of the old frontend tree will cause the backends to + // free any related resources + d->m_root.reset(root); + + // The aspect engine takes ownership of the scene root. We also set the + // parent of the scene root to be the engine + d->m_root->setParent(this); + + // Prepare the frontend tree for use by giving each node a pointer to the + // scene object and adding each node to the scene + // TODO: We probably need a call symmetric to this one above in order to + // deregister the nodes from the scene + initNodeTree(root); + + // Finally, tell the aspects about the new scene object tree. This is done + // in a blocking manner to allow the backends to get synchronized before the + // main thread starts triggering potentially more notifications QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(), - "setRoot", + "setRootEntity", Qt::BlockingQueuedConnection, - Q_ARG(Qt3D::QNode *, rootObject)); + Q_ARG(Qt3D::QEntity *, root)); qCDebug(Aspects) << "Done setting scene root on aspect manager"; } +QSharedPointer QAspectEngine::rootEntity() const +{ + Q_D(const QAspectEngine); + return d->m_root; +} + } // namespace Qt3D QT_END_NAMESPACE diff --git a/src/core/aspects/qaspectengine.h b/src/core/aspects/qaspectengine.h index 96332517e..49d984ef1 100644 --- a/src/core/aspects/qaspectengine.h +++ b/src/core/aspects/qaspectengine.h @@ -52,10 +52,11 @@ class QSurface; namespace Qt3D { -class QNode; class QAbstractAspect; class QAspectThread; class QAspectEnginePrivate; +class QEntity; +class QNode; class QT3DCORESHARED_EXPORT QAspectEngine : public QObject { @@ -66,7 +67,9 @@ public: void initialize(); void shutdown(); - void setRoot(QNode *rootObject); + void setRootEntity(QEntity *root); + QSharedPointer rootEntity() const; + void setSurface(QSurface *surface); void registerAspect(QAbstractAspect *aspect); diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h index a4131ce56..68d0af221 100644 --- a/src/core/aspects/qaspectengine_p.h +++ b/src/core/aspects/qaspectengine_p.h @@ -43,14 +43,13 @@ #define QT3D_QASPECTENGINE_P_H #include -#include -#include -#include +#include QT_BEGIN_NAMESPACE namespace Qt3D { +class QEntity; class QNode; class QAspectEngine; class QAspectThread; @@ -67,6 +66,7 @@ public: QAspectThread *m_aspectThread; QPostman *m_postman; QSceneInterface *m_scene; + QSharedPointer m_root; }; } // Qt3D diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp index d6a6d4c21..0e7da01f6 100644 --- a/src/core/aspects/qaspectmanager.cpp +++ b/src/core/aspects/qaspectmanager.cpp @@ -101,15 +101,10 @@ void QAspectManager::shutdown() qDeleteAll(m_aspects); } -void QAspectManager::setRoot(QNode *rootObject) +void QAspectManager::setRootEntity(Qt3D::QEntity *root) { qCDebug(Aspects) << Q_FUNC_INFO; - QEntity *root = qobject_cast(rootObject); - - if (!root) - qWarning() << "Root object is not an Entity"; - if (root == m_root) return; diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h index 9be4423b4..7fccab637 100644 --- a/src/core/aspects/qaspectmanager_p.h +++ b/src/core/aspects/qaspectmanager_p.h @@ -72,7 +72,7 @@ public Q_SLOTS: void initialize(); void shutdown(); - void setRoot(Qt3D::QNode *rootObject); + void setRootEntity(Qt3D::QEntity *root); void setSurface(QSurface *surface); void registerAspect(Qt3D::QAbstractAspect *aspect); QSurface *surface() const; diff --git a/src/core/window.cpp b/src/core/window.cpp index 5d6ee003a..c09a138d9 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -105,17 +105,9 @@ void Window::onUpdate() m_controller->update(1.0 / 60.0); } -void Window::setRootObject( QObject* obj ) +void Window::setRootEntity(QEntity *root) { - if (m_root == obj) - return; - - if (obj) { - obj->setParent( this ); - m_root = QSharedPointer(obj); - } - - m_aspectEngine->setRoot(qobject_cast(obj)); + m_aspectEngine->setRootEntity(root); // Hook up controller input to camera // TODO: Do this more generically as we may want keyboard ot control an Entity etc diff --git a/src/core/window.h b/src/core/window.h index 4fbb0ebf0..9bc12b6f3 100644 --- a/src/core/window.h +++ b/src/core/window.h @@ -54,6 +54,7 @@ namespace Qt3D { class QAbstractAspect; class QAspectEngine; class QCamera; +class QEntity; // temporary solution to get control over camera class CameraController; @@ -65,11 +66,10 @@ public: explicit Window(QScreen *screen = 0); ~Window(); - void setRootObject( QObject* obj ); + void setRootEntity(QEntity *root); - QSharedPointer rootObject() { return m_root; } - void registerAspect(QAbstractAspect *aspect); - virtual void setCamera(QCamera *camera); + void registerAspect(QAbstractAspect *aspect); + virtual void setCamera(QCamera *camera); protected: virtual void keyPressEvent(QKeyEvent *e); @@ -85,10 +85,6 @@ private Q_SLOTS: void onUpdate(); protected: - QSharedPointer m_root; - - // The various aspects (subsystems) that will be interested in (parts) - // of the objects in the object tree. QAspectEngine *m_aspectEngine; QCamera* m_camera; diff --git a/src/quick3d/quick3d/quickwindow.cpp b/src/quick3d/quick3d/quickwindow.cpp index d19845440..d7c55f111 100644 --- a/src/quick3d/quick3d/quickwindow.cpp +++ b/src/quick3d/quick3d/quickwindow.cpp @@ -41,12 +41,14 @@ #include "quickwindow.h" #include +#include +#include #include #include + #include #include -#include QT_BEGIN_NAMESPACE @@ -88,11 +90,9 @@ void QuickWindow::setSource(const QUrl& source) return; } - if (m_root) { - m_aspectEngine->shutdown(); - m_aspectEngine->setRoot(0); - m_root = QSharedPointer(); - } + // If the engine already has a scene object tree, tidy up first + if (m_aspectEngine->rootEntity()) + m_aspectEngine->setRootEntity(Q_NULLPTR); if (m_component) m_component = QSharedPointer(); @@ -156,7 +156,12 @@ void QuickWindow::continueExecute() return; } - setRootObject(obj); + QEntity *rootEntity = qobject_cast(obj); + if (rootEntity) + setRootEntity(rootEntity); + else + delete obj; + emit statusChanged(status()); } -- cgit v1.2.3