diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2021-12-17 10:06:15 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2022-02-03 13:37:03 +0100 |
commit | 220abad34731351f676eec9c17b833002de5166f (patch) | |
tree | 426bac445a66a6ee574de9fac5fd854c90859faa | |
parent | c072ab346a8e343abec6bbaec62a3a273a88218f (diff) | |
download | qt3d-220abad34731351f676eec9c17b833002de5166f.tar.gz |
Scene3DView: fix shutdown crash
By using a QPointer to whatch whether the Entity was already destroyed.
Also had a ownsEntity property to control whether Scene3DView should
own the Entity ptr or not.
Patch provided by my colleague Tobias Koenig <tobias.koenig@kdab.com>
Change-Id: Ideb0e842419df73c8e1bc0608965859750195ca7
Task-number: QTBUG-85575
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dview.cpp | 38 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dview_p.h | 9 |
2 files changed, 39 insertions, 8 deletions
diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp index 19ef43757..3cdfbc01c 100644 --- a/src/quick3d/imports/scene3d/scene3dview.cpp +++ b/src/quick3d/imports/scene3d/scene3dview.cpp @@ -118,6 +118,10 @@ namespace Qt3DRender { There are no restriction on the sharing of elements between different scenes in different Scene3DView instances. + + By default, you are in charge of ensuring the lifetime of the referenced + Entity. If you wish to transfer this duty to the Scene3DView, the + ownsEntity property can be set to true (defaults to false). */ namespace { @@ -146,6 +150,7 @@ Scene3DView::Scene3DView(QQuickItem *parent) , m_holderViewport(new Qt3DRender::QViewport()) , m_dirtyFlags(DirtyNode|DirtyTexture) , m_texture(nullptr) + , m_ownsEntity(false) { setFlag(QQuickItem::ItemHasContents, true);\ @@ -157,8 +162,11 @@ Scene3DView::Scene3DView(QQuickItem *parent) Scene3DView::~Scene3DView() { - if (m_entity) - abandonSubtree(m_entity); + if (m_entity) { + abandonSubtree(m_entity.data()); + if (m_ownsEntity) + m_entity->deleteLater(); + } if (m_scene3D) m_scene3D->removeView(this); @@ -166,7 +174,7 @@ Scene3DView::~Scene3DView() Qt3DCore::QEntity *Scene3DView::entity() const { - return m_entity; + return m_entity.data(); } Scene3DItem *Scene3DView::scene3D() const @@ -197,6 +205,11 @@ QSGTexture *Scene3DView::texture() const return m_texture; } +bool Scene3DView::ownsEntity() const +{ + return m_ownsEntity; +} + // Called by Scene3DRender::beforeSynchronizing in RenderThread void Scene3DView::markSGNodeDirty() { @@ -207,17 +220,20 @@ void Scene3DView::markSGNodeDirty() // Main Thread void Scene3DView::setEntity(Qt3DCore::QEntity *entity) { - if (m_entity == entity) + if (m_entity.data() == entity) return; - if (m_entity) - abandonSubtree(m_entity); + if (m_entity) { + abandonSubtree(m_entity.data()); + if (m_ownsEntity) + m_entity->deleteLater(); + } m_entity = entity; emit entityChanged(); if (m_entity) - adoptSubtree(m_entity); + adoptSubtree(m_entity.data()); } // Main Thread @@ -247,6 +263,14 @@ void Scene3DView::setScene3D(Scene3DItem *scene3D) } } +void Scene3DView::setOwnsEntity(bool ownsEntity) +{ + if (ownsEntity == m_ownsEntity) + return; + m_ownsEntity = ownsEntity; + emit ownsEntityChanged(); +} + // Render Thread QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) { diff --git a/src/quick3d/imports/scene3d/scene3dview_p.h b/src/quick3d/imports/scene3d/scene3dview_p.h index 3278bc6c4..bec9b7846 100644 --- a/src/quick3d/imports/scene3d/scene3dview_p.h +++ b/src/quick3d/imports/scene3d/scene3dview_p.h @@ -53,6 +53,7 @@ #include <QtQuick/QQuickItem> #include <QtCore/QFlags> +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -76,6 +77,7 @@ class Scene3DView : public QQuickItem Q_OBJECT Q_PROPERTY(Qt3DCore::QEntity* entity READ entity WRITE setEntity NOTIFY entityChanged) Q_PROPERTY(Qt3DRender::Scene3DItem *scene3D READ scene3D WRITE setScene3D NOTIFY scene3DChanged) + Q_PROPERTY(bool ownsEntity READ ownsEntity WRITE setOwnsEntity NOTIFY ownsEntityChanged) Q_CLASSINFO("DefaultProperty", "entity") public: @@ -97,15 +99,19 @@ public: void setTexture(QSGTexture *texture); QSGTexture *texture() const; + bool ownsEntity() const; + void markSGNodeDirty(); public Q_SLOTS: void setEntity(Qt3DCore::QEntity *entity); void setScene3D(Scene3DItem *scene3D); + void setOwnsEntity(bool ownsEntity); Q_SIGNALS: void entityChanged(); void scene3DChanged(); + void ownsEntityChanged(); private: QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override; @@ -113,7 +119,7 @@ private: void abandonSubtree(Qt3DCore::QEntity *subtree); Scene3DItem *m_scene3D; - Qt3DCore::QEntity *m_entity; + QPointer<Qt3DCore::QEntity> m_entity; Qt3DCore::QNode *m_previousFGParent; Qt3DCore::QEntity *m_holderEntity; @@ -125,6 +131,7 @@ private: DirtyFlags m_dirtyFlags; QSGTexture *m_texture; + bool m_ownsEntity; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Scene3DView::DirtyFlags) |