summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2021-12-17 10:06:15 +0100
committerPaul Lemire <paul.lemire@kdab.com>2022-02-03 13:37:03 +0100
commit220abad34731351f676eec9c17b833002de5166f (patch)
tree426bac445a66a6ee574de9fac5fd854c90859faa
parentc072ab346a8e343abec6bbaec62a3a273a88218f (diff)
downloadqt3d-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.cpp38
-rw-r--r--src/quick3d/imports/scene3d/scene3dview_p.h9
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)