summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2015-06-09 15:26:58 +0200
committerSean Harmer <sean.harmer@kdab.com>2015-06-11 19:27:56 +0000
commit3fc58a37f50cbae3d3e551dc6311771b561175cd (patch)
treef85094e6b55b450f2a2656427f07cf82f7b7d6a9
parent1d2818870034eacb1b0b6de3df279284d3ad24c3 (diff)
QNode parent changes
- introduce QNode::setParent(QNode *) - QNode created with explicit parent now invoke QNodePrivate::_q_addChild - QNode::cleanup introduces, need to be added to the dtor of every QT3D_CLONABLE QNode subclass. Handles proper destruction. - QNode::cleanup added to all classes that should have it. - Updated unit tests of Nodes, Entity, Scene Change-Id: Id2c2784122a78edaae5580fe5976d88be5a1921c Task-number: QTBUG-45947 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--examples/qt3d/tessellation-modes/tessellatedquadmesh.cpp5
-rw-r--r--examples/qt3d/tessellation-modes/tessellatedquadmesh.h1
-rw-r--r--src/core/aspects/qaspectengine.cpp43
-rw-r--r--src/core/aspects/qaspectengine.h2
-rw-r--r--src/core/aspects/qaspectengine_p.h3
-rw-r--r--src/core/core-components/qcamera.cpp5
-rw-r--r--src/core/core-components/qcamera.h2
-rw-r--r--src/core/core-components/qcameralens.cpp5
-rw-r--r--src/core/core-components/qcameralens.h1
-rw-r--r--src/core/nodes/qcomponent.cpp13
-rw-r--r--src/core/nodes/qentity.cpp46
-rw-r--r--src/core/nodes/qentity.h1
-rw-r--r--src/core/nodes/qentity_p.h1
-rw-r--r--src/core/nodes/qnode.cpp245
-rw-r--r--src/core/nodes/qnode.h26
-rw-r--r--src/core/nodes/qnode_p.h10
-rw-r--r--src/core/nodes/qnodevisitor.cpp6
-rw-r--r--src/core/nodes/qnodevisitor.h48
-rw-r--r--src/core/transforms/qtransform.cpp1
-rw-r--r--src/input/qinputaspect.cpp4
-rw-r--r--src/input/qkeyboardcontroller.cpp5
-rw-r--r--src/input/qkeyboardcontroller.h1
-rw-r--r--src/input/qkeyboardinput.cpp5
-rw-r--r--src/input/qkeyboardinput.h1
-rw-r--r--src/plugins/sceneparsers/assimp/assimpparser.cpp6
-rw-r--r--src/quick3d/quick3d/items/quick3dentityloader.cpp7
-rw-r--r--src/quick3d/quick3d/items/quick3dentityloader.h1
-rw-r--r--src/quick3d/quick3d/items/quick3dnode.cpp12
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp3
-rw-r--r--src/quick3d/quick3drenderer/items/quick3dshaderdataarray.cpp5
-rw-r--r--src/quick3d/quick3drenderer/items/quick3dshaderdataarray.h1
-rw-r--r--src/render/backend/qrenderaspect.cpp4
-rw-r--r--src/render/backend/renderentity.cpp9
-rw-r--r--src/render/defaults/qskyboxentity.cpp1
-rw-r--r--src/render/frontend/framegraph-components/qcameraselector.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qcameraselector.h1
-rw-r--r--src/render/frontend/framegraph-components/qclearbuffer.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qclearbuffer.h1
-rw-r--r--src/render/frontend/framegraph-components/qframegraph.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qframegraph.h3
-rw-r--r--src/render/frontend/framegraph-components/qframegraphnode.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qframegraphnode.h1
-rw-r--r--src/render/frontend/framegraph-components/qframegraphselector.cpp1
-rw-r--r--src/render/frontend/framegraph-components/qlayerfilter.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qlayerfilter.h1
-rw-r--r--src/render/frontend/framegraph-components/qnodraw.cpp1
-rw-r--r--src/render/frontend/framegraph-components/qrenderpassfilter.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qrenderpassfilter.h1
-rw-r--r--src/render/frontend/framegraph-components/qrendertargetselector.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qrendertargetselector.h1
-rw-r--r--src/render/frontend/framegraph-components/qsortcriterion.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qsortcriterion.h1
-rw-r--r--src/render/frontend/framegraph-components/qsortmethod.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qsortmethod.h1
-rw-r--r--src/render/frontend/framegraph-components/qstateset.cpp1
-rw-r--r--src/render/frontend/framegraph-components/qtechniquefilter.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qtechniquefilter.h1
-rw-r--r--src/render/frontend/framegraph-components/qviewport.cpp5
-rw-r--r--src/render/frontend/framegraph-components/qviewport.h1
-rw-r--r--src/render/frontend/qabstractmesh.cpp5
-rw-r--r--src/render/frontend/qabstractmesh.h3
-rw-r--r--src/render/frontend/qabstractsceneloader.cpp5
-rw-r--r--src/render/frontend/qabstractsceneloader.h1
-rw-r--r--src/render/frontend/qabstracttextureimage.cpp1
-rw-r--r--src/render/frontend/qabstracttextureprovider.cpp3
-rw-r--r--src/render/frontend/qabstracttextureprovider.h1
-rw-r--r--src/render/frontend/qalphacoverage.cpp5
-rw-r--r--src/render/frontend/qalphacoverage.h1
-rw-r--r--src/render/frontend/qalphatest.cpp5
-rw-r--r--src/render/frontend/qalphatest.h1
-rw-r--r--src/render/frontend/qannotation.cpp5
-rw-r--r--src/render/frontend/qannotation.h1
-rw-r--r--src/render/frontend/qblendequation.cpp5
-rw-r--r--src/render/frontend/qblendequation.h1
-rw-r--r--src/render/frontend/qblendstate.cpp5
-rw-r--r--src/render/frontend/qblendstate.h1
-rw-r--r--src/render/frontend/qcolormask.cpp1
-rw-r--r--src/render/frontend/qcuboidmesh.cpp5
-rw-r--r--src/render/frontend/qcuboidmesh.h3
-rw-r--r--src/render/frontend/qcullface.cpp5
-rw-r--r--src/render/frontend/qcullface.h1
-rw-r--r--src/render/frontend/qcylindermesh.cpp4
-rw-r--r--src/render/frontend/qcylindermesh.h3
-rw-r--r--src/render/frontend/qdepthmask.cpp5
-rw-r--r--src/render/frontend/qdepthmask.h1
-rw-r--r--src/render/frontend/qdepthtest.cpp5
-rw-r--r--src/render/frontend/qdepthtest.h1
-rw-r--r--src/render/frontend/qdithering.cpp5
-rw-r--r--src/render/frontend/qdithering.h1
-rw-r--r--src/render/frontend/qeffect.cpp5
-rw-r--r--src/render/frontend/qeffect.h1
-rw-r--r--src/render/frontend/qfrontface.cpp5
-rw-r--r--src/render/frontend/qfrontface.h1
-rw-r--r--src/render/frontend/qlayer.cpp5
-rw-r--r--src/render/frontend/qlayer.h1
-rw-r--r--src/render/frontend/qmaterial.cpp5
-rw-r--r--src/render/frontend/qmaterial.h1
-rw-r--r--src/render/frontend/qmesh.cpp5
-rw-r--r--src/render/frontend/qmesh.h1
-rw-r--r--src/render/frontend/qparameter.cpp5
-rw-r--r--src/render/frontend/qparameter.h1
-rw-r--r--src/render/frontend/qparametermapping.cpp5
-rw-r--r--src/render/frontend/qparametermapping.h1
-rw-r--r--src/render/frontend/qplanemesh.cpp5
-rw-r--r--src/render/frontend/qplanemesh.h3
-rw-r--r--src/render/frontend/qpolygonoffset.cpp5
-rw-r--r--src/render/frontend/qpolygonoffset.h1
-rw-r--r--src/render/frontend/qrenderattachment.cpp5
-rw-r--r--src/render/frontend/qrenderattachment.h1
-rw-r--r--src/render/frontend/qrenderpass.cpp5
-rw-r--r--src/render/frontend/qrenderpass.h1
-rw-r--r--src/render/frontend/qrenderstate.cpp5
-rw-r--r--src/render/frontend/qrenderstate.h4
-rw-r--r--src/render/frontend/qrendertarget.cpp5
-rw-r--r--src/render/frontend/qrendertarget.h1
-rw-r--r--src/render/frontend/qsceneloader.cpp5
-rw-r--r--src/render/frontend/qsceneloader.h1
-rw-r--r--src/render/frontend/qscissortest.cpp5
-rw-r--r--src/render/frontend/qscissortest.h1
-rw-r--r--src/render/frontend/qshaderdata.cpp5
-rw-r--r--src/render/frontend/qshaderdata.h1
-rw-r--r--src/render/frontend/qshaderprogram.cpp5
-rw-r--r--src/render/frontend/qshaderprogram.h1
-rw-r--r--src/render/frontend/qspheremesh.cpp5
-rw-r--r--src/render/frontend/qspheremesh.h3
-rw-r--r--src/render/frontend/qstenciltest.cpp5
-rw-r--r--src/render/frontend/qstenciltest.h1
-rw-r--r--src/render/frontend/qtechnique.cpp5
-rw-r--r--src/render/frontend/qtechnique.h1
-rw-r--r--src/render/frontend/qtextureimage.cpp1
-rw-r--r--src/render/frontend/qtextureproviders.cpp23
-rw-r--r--src/render/frontend/qtorusmesh.cpp6
-rw-r--r--src/render/frontend/qtorusmesh.h3
-rw-r--r--src/render/frontend/qwrapmode.h2
-rw-r--r--tests/auto/core/cloning/tst_cloning.cpp16
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp694
-rw-r--r--tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp2
-rw-r--r--tests/auto/core/qentity/tst_qentity.cpp538
-rw-r--r--tests/auto/core/qscene/tst_qscene.cpp57
139 files changed, 1767 insertions, 391 deletions
diff --git a/examples/qt3d/tessellation-modes/tessellatedquadmesh.cpp b/examples/qt3d/tessellation-modes/tessellatedquadmesh.cpp
index 6b04e5da3..08a3f54b3 100644
--- a/examples/qt3d/tessellation-modes/tessellatedquadmesh.cpp
+++ b/examples/qt3d/tessellation-modes/tessellatedquadmesh.cpp
@@ -45,6 +45,11 @@ TessellatedQuadMesh::TessellatedQuadMesh(Qt3D::QNode *parent)
{
}
+TessellatedQuadMesh::~TessellatedQuadMesh()
+{
+ QNode::cleanup();
+}
+
class TessellatedQuadMeshFunctor : public Qt3D::QAbstractMeshFunctor
{
public:
diff --git a/examples/qt3d/tessellation-modes/tessellatedquadmesh.h b/examples/qt3d/tessellation-modes/tessellatedquadmesh.h
index 76b00ae01..0bb6459ef 100644
--- a/examples/qt3d/tessellation-modes/tessellatedquadmesh.h
+++ b/examples/qt3d/tessellation-modes/tessellatedquadmesh.h
@@ -44,6 +44,7 @@ class TessellatedQuadMesh : public Qt3D::QAbstractMesh
Q_OBJECT
public:
explicit TessellatedQuadMesh(Qt3D::QNode *parent = 0);
+ ~TessellatedQuadMesh();
Qt3D::QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_OVERRIDE;
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 1ef1d803a..8b4a76a84 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -50,6 +50,7 @@
#include <private/qnode_p.h>
#include "qentity.h"
#include "qcomponent.h"
+#include "qnodevisitor.h"
QT_BEGIN_NAMESPACE
@@ -70,6 +71,26 @@ QAspectEnginePrivate::QAspectEnginePrivate()
qRegisterMetaType<Qt3D::QSceneInterface *>();
}
+/*!
+ Used to init the scene tree when the Qt3D aspect is first started. Basically
+ sets the scene/change arbiter on the items and store the entity - component
+ pairs in the scene
+ */
+void QAspectEnginePrivate::initNode(QNode *node)
+{
+ QNodePrivate::get(node)->setScene(m_scene);
+ m_scene->addObservable(node);
+}
+
+void QAspectEnginePrivate::initEntity(QEntity *entity)
+{
+ Q_FOREACH (QComponent *comp, entity->components()) {
+ if (!comp->shareable() && !m_scene->entitiesForComponent(comp->id()).isEmpty())
+ qWarning() << "Trying to assign a non shareable component to more than one Entity";
+ m_scene->addEntityForComponent(comp->id(), entity->id());
+ }
+}
+
QAspectEngine::QAspectEngine(QObject *parent)
: QObject(*new QAspectEnginePrivate, parent)
{
@@ -107,24 +128,10 @@ QAspectEngine::~QAspectEngine()
delete d->m_scene;
}
-void QAspectEngine::initNodeTree(QNode *node) const
+void QAspectEngine::initNodeTree(QNode *node)
{
- Q_D(const QAspectEngine);
- node->d_func()->setScene(d->m_scene);
- d->m_scene->addObservable(node);
- QEntity *entity = qobject_cast<QEntity *>(node);
- if (entity != Q_NULLPTR)
- Q_FOREACH (QComponent *comp, entity->components()) {
- if (!comp->shareable() && !d->m_scene->entitiesForComponent(comp->id()).isEmpty())
- qWarning() << "Trying to assign a non shareable component to more than one Entity";
- d->m_scene->addEntityForComponent(comp->id(), entity->id());
- }
-
- Q_FOREACH (QObject *c, node->children()) {
- QNode *childNode = qobject_cast<QNode *>(c);
- if (childNode != Q_NULLPTR)
- initNodeTree(childNode);
- }
+ QNodeVisitor visitor;
+ visitor.traverse(node, d_func(), &QAspectEnginePrivate::initNode, &QAspectEnginePrivate::initEntity);
}
void QAspectEngine::initialize()
@@ -218,7 +225,7 @@ void QAspectEngine::setRootEntity(QEntity *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);
+ static_cast<QObject *>(d->m_root.data())->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
diff --git a/src/core/aspects/qaspectengine.h b/src/core/aspects/qaspectengine.h
index c93fcb653..cdbb01a30 100644
--- a/src/core/aspects/qaspectengine.h
+++ b/src/core/aspects/qaspectengine.h
@@ -78,7 +78,7 @@ protected:
QAspectEngine(QAspectEnginePrivate &dd, QObject *parent = 0);
private:
- void initNodeTree(QNode *node) const;
+ void initNodeTree(QNode *node);
};
} // namespace Qt3D
diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h
index d2f2da88e..b1456dad2 100644
--- a/src/core/aspects/qaspectengine_p.h
+++ b/src/core/aspects/qaspectengine_p.h
@@ -65,6 +65,9 @@ public:
QSceneInterface *m_scene;
QSharedPointer<QEntity> m_root;
QList<QAbstractAspect*> m_aspects;
+
+ void initNode(QNode *node);
+ void initEntity(QEntity *entity);
};
} // Qt3D
diff --git a/src/core/core-components/qcamera.cpp b/src/core/core-components/qcamera.cpp
index 76d208cc9..e90479d06 100644
--- a/src/core/core-components/qcamera.cpp
+++ b/src/core/core-components/qcamera.cpp
@@ -82,6 +82,11 @@ QCamera::QCamera(QNode *parent) :
addComponent(d_func()->m_transform);
}
+QCamera::~QCamera()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QCamera::QCamera(QCameraPrivate &dd, QNode *parent)
: QEntity(dd, parent)
diff --git a/src/core/core-components/qcamera.h b/src/core/core-components/qcamera.h
index 9c3ac338f..b6b9de4a6 100644
--- a/src/core/core-components/qcamera.h
+++ b/src/core/core-components/qcamera.h
@@ -72,7 +72,7 @@ class QT3DCORESHARED_EXPORT QCamera : public QEntity
public:
explicit QCamera(QNode *parent = 0);
-
+ ~QCamera();
enum CameraTranslationOption {
TranslateViewCenter,
diff --git a/src/core/core-components/qcameralens.cpp b/src/core/core-components/qcameralens.cpp
index 5fc43e5c3..35f9fdd7a 100644
--- a/src/core/core-components/qcameralens.cpp
+++ b/src/core/core-components/qcameralens.cpp
@@ -66,6 +66,11 @@ QCameraLens::QCameraLens(QNode *parent)
d->updateProjectionMatrix();
}
+QCameraLens::~QCameraLens()
+{
+ QNode::cleanup();
+}
+
void QCameraLens::copy(const QNode *ref)
{
QComponent::copy(ref);
diff --git a/src/core/core-components/qcameralens.h b/src/core/core-components/qcameralens.h
index 0e871cc6b..7ec77adf7 100644
--- a/src/core/core-components/qcameralens.h
+++ b/src/core/core-components/qcameralens.h
@@ -66,6 +66,7 @@ class QT3DCORESHARED_EXPORT QCameraLens : public QComponent
public:
explicit QCameraLens(QNode *parent = 0);
+ ~QCameraLens();
enum ProjectionType {
OrthogonalProjection,
diff --git a/src/core/nodes/qcomponent.cpp b/src/core/nodes/qcomponent.cpp
index 4194c68e4..9f2cdbd66 100644
--- a/src/core/nodes/qcomponent.cpp
+++ b/src/core/nodes/qcomponent.cpp
@@ -38,7 +38,7 @@
#include "qcomponent_p.h"
#include "qentity.h"
#include "qentity_p.h"
-
+#include "qsceneinterface.h"
#include <Qt3DCore/qscenepropertychange.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +60,12 @@ void QComponentPrivate::addEntity(QEntity *entity)
{
m_entities.append(entity);
+ if (m_scene != Q_NULLPTR) {
+ if (!m_shareable && !m_scene->entitiesForComponent(m_id).isEmpty())
+ qWarning() << "Trying to assign a non shareable component to more than one Entity";
+ m_scene->addEntityForComponent(m_id, entity->id());
+ }
+
// We notify only if we have a QChangeArbiter
if (m_changeArbiter != Q_NULLPTR) {
Q_Q(QComponent);
@@ -81,6 +87,9 @@ void QComponentPrivate::removeEntity(QEntity *entity)
notifyObservers(e);
}
+ if (m_scene != Q_NULLPTR)
+ m_scene->removeEntityForComponent(m_id, entity->id());
+
m_entities.removeAll(entity);
}
@@ -116,6 +125,8 @@ QComponent::QComponent(QNode *parent)
QComponent::~QComponent()
{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QComponent subclass didn't call QNode::cleanup in its destructor");
+
Q_FOREACH (QEntity *entity, entities()) {
QEntityPrivate *entityPimpl = dynamic_cast<QEntityPrivate *>(QEntityPrivate::get(entity));
if (entityPimpl)
diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp
index e0aff9466..8f9df993e 100644
--- a/src/core/nodes/qentity.cpp
+++ b/src/core/nodes/qentity.cpp
@@ -58,6 +58,7 @@ namespace Qt3D {
QEntityPrivate::QEntityPrivate()
: QNodePrivate()
, m_enabled(true)
+ , m_parentEntityId()
{}
/*!
@@ -89,12 +90,13 @@ QEntity::QEntity(QNode *parent)
QEntity::~QEntity()
{
+ // remove all component aggregations
+ removeAllComponents();
+
+ QNode::cleanup();
// If all children are removed
// That includes the components that are parented by this entity
- // We need to call removeAllComponent only for real Entities (not clone)
- if (d_func()->m_changeArbiter)
- removeAllComponents();
}
/*! \internal */
@@ -113,6 +115,7 @@ void QEntity::copy(const QNode *ref)
const QEntity *entity = static_cast<const QEntity*>(ref);
d_func()->m_enabled = entity->d_func()->m_enabled;
d_func()->m_visible = entity->d_func()->m_visible;
+ d_func()->m_parentEntityId = entity->parentEntityId();
Q_FOREACH (QComponent *c, entity->d_func()->m_components) {
QNode *ccclone = QNode::clone(c);
@@ -140,19 +143,17 @@ void QEntity::addComponent(QComponent *comp)
Q_D(QEntity);
Q_CHECK_PTR( comp );
qCDebug(Nodes) << Q_FUNC_INFO << comp;
- Q_ASSERT(d->m_components.count(comp) == 0);
+
+ // A Component can only be aggregated once
+ if (d->m_components.count(comp) != 0)
+ return ;
+
d->m_components.append(comp);
// We only set the Entity as the Component's parent when it has no parent
// This will be the case mostly on C++ but rarely in QML
if (!comp->parent())
comp->setParent(this);
- if (d->m_scene != Q_NULLPTR) {
- if (!comp->shareable() && !d->m_scene->entitiesForComponent(comp->id()).isEmpty())
- qWarning() << "Trying to assign a non shareable component to more than one Entity";
- d->m_scene->addEntityForComponent(comp->id(), d->m_id);
- }
-
if (d->m_changeArbiter != Q_NULLPTR) {
// Sending a full fledged component in the notification as we'll need
// to know which type of component it was and its properties to create
@@ -186,9 +187,6 @@ void QEntity::removeComponent(QComponent *comp)
d->notifyObservers(propertyChange);
}
- if (d->m_scene != Q_NULLPTR)
- d->m_scene->removeEntityForComponent(comp->id(), d->m_id);
-
d->m_components.removeOne(comp);
}
@@ -210,6 +208,7 @@ void QEntity::removeAllComponents()
*/
QEntity *QEntity::parentEntity() const
{
+ Q_D(const QEntity);
QNode *parentNode = QNode::parentNode();
QEntity *parentEntity = qobject_cast<QEntity *>(parentNode);
@@ -217,9 +216,30 @@ QEntity *QEntity::parentEntity() const
parentNode = parentNode->parentNode();
parentEntity = qobject_cast<QEntity*>(parentNode);
}
+ if (!parentEntity) {
+ if (!d->m_parentEntityId.isNull())
+ d->m_parentEntityId = QNodeId();
+ } else {
+ if (d->m_parentEntityId != parentEntity->id())
+ d->m_parentEntityId = parentEntity->id();
+ }
return parentEntity;
}
+/*!
+ Returns the Qt3D::QNodeId id of the parent Qt3D::QEntity instance of the
+ current Qt3D::QEntity object. The QNodeId isNull method will return true if
+ there is no Qt3D::QEntity parent of the current Qt3D::QEntity in the scene
+ hierarchy.
+ */
+QNodeId QEntity::parentEntityId() const
+{
+ Q_D(const QEntity);
+ if (d->m_parentEntityId.isNull())
+ parentEntity();
+ return d->m_parentEntityId;
+}
+
} // namespace Qt3D
QT_END_NAMESPACE
diff --git a/src/core/nodes/qentity.h b/src/core/nodes/qentity.h
index 86a6ba791..967611684 100644
--- a/src/core/nodes/qentity.h
+++ b/src/core/nodes/qentity.h
@@ -66,6 +66,7 @@ public:
void removeAllComponents();
QEntity *parentEntity() const;
+ QNodeId parentEntityId() const;
protected:
QEntity(QEntityPrivate &dd, QNode *parent = 0);
diff --git a/src/core/nodes/qentity_p.h b/src/core/nodes/qentity_p.h
index b28d0c391..4dc851103 100644
--- a/src/core/nodes/qentity_p.h
+++ b/src/core/nodes/qentity_p.h
@@ -58,6 +58,7 @@ public :
// TODO: Is a bool enough here or do we need additional states for entities?
// Perhaps aboutToBeDeleted would be useful?
bool m_enabled;
+ mutable QNodeId m_parentEntityId;
};
}
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index d6472cfd6..a8061a9cd 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -47,6 +47,7 @@
#include <QMetaProperty>
#include <Qt3DCore/QComponent>
#include <Qt3DCore/private/corelogging_p.h>
+#include <Qt3DCore/qnodevisitor.h>
QT_BEGIN_NAMESPACE
@@ -64,24 +65,29 @@ QNodePrivate::QNodePrivate()
, m_scene(Q_NULLPTR)
, m_id(QNodeId::createId())
, m_blockNotifications(false)
+ , m_wasCleanedUp(false)
, m_propertyChangesSetup(false)
, m_signals(this)
{
}
-// Called by QEvent::childAdded (main thread)
-void QNodePrivate::addChild(QNode *childNode)
+// Called by QNodePrivate::ctor or setParent (main thread)
+void QNodePrivate::_q_addChild(QNode *childNode)
{
Q_ASSERT(childNode);
if (childNode == q_func())
return ;
- // Set the scene
- childNode->d_func()->setScene(m_scene);
+ // If the scene is null it means that the current node is part of a subtree
+ // that has been pre-prepared. Therefore the node shouldn't be added by
+ // itself but only when the root of the said subtree is inserted into an
+ // existing node whose m_scene member is valid
+ if (m_scene == Q_NULLPTR)
+ return;
- // addObservable set the QChangeArbiter
- if (m_scene != Q_NULLPTR)
- m_scene->addObservable(childNode);
+ QNodeVisitor visitor;
+ // Recursively set scene and change arbiter for the node subtree
+ visitor.traverse(childNode, this, &QNodePrivate::setSceneHelper);
// We notify only if we have a QChangeArbiter
if (m_changeArbiter != Q_NULLPTR) {
@@ -100,10 +106,13 @@ void QNodePrivate::addChild(QNode *childNode)
e->setValue(QVariant::fromValue(QNodePtr(childClone, &QNodePrivate::nodePtrDeleter)));
notifyObservers(e);
}
+
+ // Handle Entity - Components
+ visitor.traverse(childNode, this, &QNodePrivate::addEntityComponentToScene);
}
-// Called by QEvent::childRemoved (main thread)
-void QNodePrivate::removeChild(QNode *childNode)
+// Called by setParent or cleanup (main thread) (could be other thread if created on the backend in a job)
+void QNodePrivate::_q_removeChild(QNode *childNode)
{
Q_ASSERT(childNode);
if (childNode->parent() != q_func())
@@ -134,18 +143,9 @@ void QNodePrivate::removeChild(QNode *childNode)
notifyObservers(e);
}
- if (m_scene != Q_NULLPTR)
- m_scene->removeObservable(childNode);
- childNode->d_func()->setScene(Q_NULLPTR);
-}
-
-void QNodePrivate::removeAllChildren()
-{
- Q_FOREACH (QObject *child, q_func()->children()) {
- QNode *childNode = qobject_cast<QNode *>(child);
- if (childNode != Q_NULLPTR)
- removeChild(childNode);
- }
+ // Recursively unset the scene on all children
+ QNodeVisitor visitor;
+ visitor.traverse(childNode, this, &QNodePrivate::unsetSceneHelper);
}
void QNodePrivate::registerNotifiedProperties()
@@ -198,6 +198,64 @@ void QNodePrivate::propertyChanged(int propertyIndex)
}
}
+/*!
+ \internal
+ Recursively sets and adds the nodes in the subtree of base node \a root to the scene.
+ Also takes care of connecting Components and Entities together in the scene.
+ */
+void QNodePrivate::setSceneHelper(QNode *root)
+{
+ // Sets the scene
+ root->d_func()->setScene(m_scene);
+ // addObservable sets the QChangeArbiter
+ m_scene->addObservable(root);
+
+ // We also need to handle QEntity <-> QComponent relationships
+ if (QComponent *c = qobject_cast<QComponent *>(root)) {
+ const QVector<QEntity *> entities = c->entities();
+ Q_FOREACH (QEntity *entity, entities) {
+ if (!c->shareable() && !m_scene->entitiesForComponent(c->id()).isEmpty())
+ qWarning() << "Trying to assign a non shareable component to more than one Entity";
+ m_scene->addEntityForComponent(c->id(), entity->id());
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Recursively unsets and remove nodes in the subtree of base node \a root from
+ the scene. Also takes care of removing Components and Entities connections.
+ */
+void QNodePrivate::unsetSceneHelper(QNode *root)
+{
+ // We also need to handle QEntity <-> QComponent relationships removal
+ if (QComponent *c = qobject_cast<QComponent *>(root)) {
+ const QVector<QEntity *> entities = c->entities();
+ Q_FOREACH (QEntity *entity, entities) {
+ m_scene->removeEntityForComponent(c->id(), entity->id());
+ }
+ }
+
+ if (m_scene != Q_NULLPTR)
+ m_scene->removeObservable(root);
+ root->d_func()->setScene(Q_NULLPTR);
+}
+
+/*!
+ \internal
+ */
+void QNodePrivate::addEntityComponentToScene(QNode *root)
+{
+ if (QEntity *e = qobject_cast<QEntity *>(root)) {
+ Q_FOREACH (QComponent *c, e->components())
+ m_scene->addEntityForComponent(c->id(), e->id());
+ }
+}
+
+/*!
+ \internal
+ */
// Called in the main thread by QScene -> following QEvent::childAdded / addChild
void QNodePrivate::setArbiter(QLockableObserverInterface *arbiter)
{
@@ -221,17 +279,26 @@ void QNode::sceneChangeEvent(const QSceneChangePtr &change)
qWarning() << Q_FUNC_INFO << "sceneChangeEvent should have been subclassed";
}
+/*!
+ \internal
+ */
void QNodePrivate::setScene(QSceneInterface *scene)
{
if (m_scene != scene)
m_scene = scene;
}
+/*!
+ \internal
+ */
QSceneInterface *QNodePrivate::scene() const
{
return m_scene;
}
+/*!
+ \internal
+ */
void QNodePrivate::notifyPropertyChange(const char *name, const QVariant &value)
{
// Bail out early if we can to avoid operator new
@@ -244,6 +311,9 @@ void QNodePrivate::notifyPropertyChange(const char *name, const QVariant &value)
notifyObservers(e);
}
+/*!
+ \internal
+ */
// Called by the main thread
void QNodePrivate::notifyObservers(const QSceneChangePtr &change)
{
@@ -264,6 +334,9 @@ void QNodePrivate::notifyObservers(const QSceneChangePtr &change)
// QNode *subtree;
// QNodePrivate::get(root)->insertTree(subtree);
+/*!
+ \internal
+ */
void QNodePrivate::insertTree(QNode *treeRoot, int depth)
{
if (m_scene != Q_NULLPTR) {
@@ -281,11 +354,17 @@ void QNodePrivate::insertTree(QNode *treeRoot, int depth)
treeRoot->setParent(q_func());
}
+/*!
+ \internal
+ */
QNodePrivate *QNodePrivate::get(QNode *q)
{
return q->d_func();
}
+/*!
+ \internal
+ */
void QNodePrivate::nodePtrDeleter(QNode *q)
{
QObject *p = q->parent();
@@ -310,6 +389,9 @@ void QNodePrivate::nodePtrDeleter(QNode *q)
and no particular meaning, it is there as a way of building a node based tree
structure.
+ The parent of a Qt3D::QNode instance can only be another Qt3D::QNode
+ instance.
+
Each Qt3D::QNode instance has a unique id that allows it to be recognizable
from other instances.
@@ -317,24 +399,46 @@ void QNodePrivate::nodePtrDeleter(QNode *q)
will automatically generate notifications that the Qt3D backend aspects will
receive.
+ When subclassing Qt3D::QNode make sure to call QNode::cleanup() from your
+ subclass's destructor to ensure proper notification to backend aspects.
+ Faiure to do so will result in crashes when one of your Qt3D::QNode
+ subclass instance is eventually destroyed.
+
\sa Qt3D::QEntity, Qt3D::QComponent
*/
/*!
Creates a new Qt3D::QNode instance with parent \a parent.
+
+ \note The backend aspects will be notified that a Qt3D::QNode instance is
+ part of the scene only if it has a parent; unless this is the root node of
+ the Qt3D scene.
+
+ \sa setParent(Qt3D::QNode *)
*/
QNode::QNode(QNode *parent)
: QObject(*new QNodePrivate, parent)
{
- // We rely on QEvent::childAdded to be triggered on the parent
- // So we don't actually need to invoke a method or anything
- // to add ourselve with the parent
+ qRegisterMetaType<QNode *>("QNode*");
+ // We need to add ourselves with the parent if it is valid
+ // This will notify the backend about the new child
+ if (parent) {
+ // This needs to be invoked only after the QNode has been fully
+ QMetaObject::invokeMethod(parent, "_q_addChild", Qt::QueuedConnection, Q_ARG(QNode*, this));
+ }
}
/*! \internal */
QNode::QNode(QNodePrivate &dd, QNode *parent)
: QObject(dd, parent)
{
+ qRegisterMetaType<QNode *>("QNode*");
+ // We need to add ourselves with the parent if it is valid
+ // This will notify the backend about the new child
+ if (parent) {
+ // This needs to be invoked only after the QNode has been fully
+ QMetaObject::invokeMethod(parent, "_q_addChild", Qt::QueuedConnection, Q_ARG(QNode*, this));
+ }
}
/*!
@@ -352,6 +456,7 @@ void QNode::copy(const QNode *ref)
QNode::~QNode()
{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QNode subclass didn't call QNode::cleanup in its destructor");
}
/*!
@@ -403,6 +508,42 @@ bool QNode::blockNotifications(bool block)
}
/*!
+ * Sets the parent node of the current Qt3D::QNode instance to \a parent.
+ * Setting the parent will notify the backend aspects about current Qt3D::QNode
+ * instance's parent change.
+ *
+ * \note if \a parent happens to be null, this will actually notify that the
+ * current Qt3D::QNode instance was removed from the scene.
+ */
+void QNode::setParent(QNode *parent)
+{
+ if (parentNode())
+ QNodePrivate::get(parentNode())->_q_removeChild(this);
+ QObject::setParent(parent);
+ if (parentNode())
+ QNodePrivate::get(parentNode())->_q_addChild(this);
+ emit parentChanged();
+}
+
+/*!
+ * Returns a list filled with the Qt3D::QNode children of the current
+ * Qt3D::QNode instance.
+ */
+QNodeList QNode::childrenNodes() const
+{
+ QNodeList nodeChildrenList;
+ const QObjectList objectChildrenList = QObject::children();
+ nodeChildrenList.reserve(objectChildrenList.size());
+
+ Q_FOREACH (QObject *c, objectChildrenList) {
+ if (QNode *n = qobject_cast<QNode *>(c))
+ nodeChildrenList.push_back(n);
+ }
+
+ return nodeChildrenList;
+}
+
+/*!
Returns a clone of \a node. All the children of \a node are cloned as well.
\note This is the only way to create two nodes with the same id.
@@ -426,47 +567,19 @@ QNode *QNode::clone(QNode *node)
QNode *childNode = qobject_cast<QNode *>(c);
if (childNode != Q_NULLPTR) {
QNode *cclone = QNode::clone(childNode);
+ // We use QObject::setParent instead of QNode::setParent to avoid the
+ // whole overhead generated by the latter as we are only dealing with clones
if (cclone != Q_NULLPTR)
- cclone->setParent(clonedNode);
+ static_cast<QObject *>(cclone)->setParent(clonedNode);
}
}
- if (--clearLock == 0)
+ if (--clearLock == 0) // Cloning done
QNodePrivate::m_clonesLookupTable.clear();
return clonedNode;
}
-bool QNode::event(QEvent *e)
-{
- Q_D(QNode);
-
- switch (e->type()) {
-
- case QEvent::ChildAdded: {
- QNode *childNode = qobject_cast<QNode *>(static_cast<QChildEvent *>(e)->child());
- if (childNode != Q_NULLPTR) {
- d->addChild(childNode);
- }
- break;
- }
-
- case QEvent::ChildRemoved: {
- QNode *childNode = qobject_cast<QNode *>(static_cast<QChildEvent *>(e)->child());
- if (childNode != Q_NULLPTR) {
- d->removeChild(childNode);
- }
- break;
- }
-
- default:
- break;
-
- } // switch
-
- return QObject::event(e);
-}
-
/*!
Returns a pointer to the Qt3D::QNode instance's scene.
*/
@@ -476,6 +589,26 @@ QSceneInterface *QNode::scene() const
return d->m_scene;
}
+/*!
+ * This methods can only be called once and takes care of notyfing the backend
+ * aspects that the current Qt3D::QNode instance is about to be destroyed.
+ *
+ * \note It must be called by the destructor of every class subclassing
+ * Qt3D::QNode that is clonable (using the QT3D_CLONEABLE macro).
+ */
+void QNode::cleanup()
+{
+ Q_D(QNode);
+ if (!d->m_wasCleanedUp) {
+ d->m_wasCleanedUp = true;
+ qCDebug(Nodes) << Q_FUNC_INFO << this;
+ if (parentNode())
+ QNodePrivate::get(parentNode())->_q_removeChild(this);
+ // Root element has no parent and therefore we cannot
+ // call parent->_q_removeChild();
+ }
+}
+
} // namespace Qt3D
diff --git a/src/core/nodes/qnode.h b/src/core/nodes/qnode.h
index e61f30edb..900299077 100644
--- a/src/core/nodes/qnode.h
+++ b/src/core/nodes/qnode.h
@@ -42,6 +42,8 @@
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
+#define Q_NODE_NULLPTR static_cast<Qt3D::QNode *>(Q_NULLPTR)
+
QT_BEGIN_NAMESPACE
namespace Qt3D {
@@ -62,12 +64,18 @@ typedef QSharedPointer<QNode> QNodePtr;
return clone_; \
}
+
+// Each QNode subclass should call QNode::cleanup in it dtor
+// QNode::cleanup checks that a flags wasn't set to true,
+// sets it to true and sends a clone to the backend
+
class QT3DCORESHARED_EXPORT QNode : public QObject
{
Q_OBJECT
+ Q_PROPERTY(Qt3D::QNode *parent READ parentNode WRITE setParent NOTIFY parentChanged)
public:
explicit QNode(QNode *parent = 0);
- ~QNode();
+ virtual ~QNode();
const QNodeId id() const;
QNode *parentNode() const;
@@ -75,6 +83,9 @@ public:
bool notificationsBlocked() const;
bool blockNotifications(bool block);
+ virtual void setParent(QNode *parent);
+ QNodeList childrenNodes() const;
+
protected:
// Clone should only be made in the main thread
static QNode *clone(QNode *node);
@@ -82,16 +93,27 @@ protected:
QNode(QNodePrivate &dd, QNode *parent = 0);
virtual void copy(const QNode *ref);
virtual void sceneChangeEvent(const QSceneChangePtr &change);
- bool event(QEvent *e) Q_DECL_OVERRIDE;
QSceneInterface *scene() const;
+ void cleanup();
+
private:
Q_DECLARE_PRIVATE(QNode)
virtual QNode *doClone() const = 0;
+ // We only want setParent(QNode *) to be callable
+ // when dealing with QNode objects
+ void setParent(QObject *) Q_DECL_EQ_DELETE;
+
+ Q_PRIVATE_SLOT(d_func(), void _q_addChild(QNode *))
+ Q_PRIVATE_SLOT(d_func(), void _q_removeChild(QNode *))
+
friend class QAspectEngine;
friend class QPostman;
friend class QScene;
+
+Q_SIGNALS:
+ void parentChanged();
};
} // namespace Qt3D
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index 7e654bf7a..11f64be9c 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -74,18 +74,22 @@ public:
QSceneInterface *m_scene;
mutable QNodeId m_id;
bool m_blockNotifications;
+ bool m_wasCleanedUp;
static QNodePrivate *get(QNode *q);
static void nodePtrDeleter(QNode *q);
private:
- void addChild(QNode *childNode);
- void removeChild(QNode *childNode);
- void removeAllChildren();
+ void _q_addChild(QNode *childNode);
+ void _q_removeChild(QNode *childNode);
void registerNotifiedProperties();
void unregisterNotifiedProperties();
void propertyChanged(int propertyIndex);
+ void setSceneHelper(QNode *root);
+ void unsetSceneHelper(QNode *root);
+ void addEntityComponentToScene(QNode *root);
+
friend class PropertyChangeHandler<QNodePrivate>;
bool m_propertyChangesSetup;
PropertyChangeHandler<QNodePrivate> m_signals;
diff --git a/src/core/nodes/qnodevisitor.cpp b/src/core/nodes/qnodevisitor.cpp
index f7acac132..ec10cbb73 100644
--- a/src/core/nodes/qnodevisitor.cpp
+++ b/src/core/nodes/qnodevisitor.cpp
@@ -41,7 +41,6 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
QNodeVisitor::QNodeVisitor()
- : m_traverseDisabled(false)
{
}
@@ -64,11 +63,6 @@ QNodeList QNodeVisitor::path() const
return m_path;
}
-void QNodeVisitor::setTraverseDisabled(bool on)
-{
- m_traverseDisabled = on;
-}
-
} // namespace Qt3D
QT_END_NAMESPACE
diff --git a/src/core/nodes/qnodevisitor.h b/src/core/nodes/qnodevisitor.h
index fdc728809..e903dc665 100644
--- a/src/core/nodes/qnodevisitor.h
+++ b/src/core/nodes/qnodevisitor.h
@@ -52,6 +52,18 @@ public:
QNodeVisitor();
virtual ~QNodeVisitor();
+ template<typename NodeVisitorFunc>
+ void traverse(QNode *rootNode_, NodeVisitorFunc fN)
+ {
+ startTraversing(rootNode_, createFunctor(fN));
+ }
+
+ template<typename Obj, typename NodeVisitorFunc>
+ void traverse(QNode *rootNode_, Obj *instance, NodeVisitorFunc fN)
+ {
+ startTraversing(rootNode_, createFunctor(instance, fN));
+ }
+
template<typename NodeVisitorFunc, typename EntityVisitorFunc>
void traverse(QNode *rootNode_, NodeVisitorFunc fN, EntityVisitorFunc fE)
{
@@ -67,11 +79,16 @@ public:
QNode *rootNode() const;
QNode *currentNode() const;
QNodeList path() const;
- void setTraverseDisabled(bool on);
private:
QNodeList m_path;
- bool m_traverseDisabled;
+
+ template<typename NodeVisitorFunctor>
+ void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN)
+ {
+ m_path = QNodeList() << rootNode_;
+ visitNode(rootNode_, fN);
+ }
template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
void startTraversing(QNode *rootNode_, NodeVisitorFunctor fN, EntityVisitorFunctor fE)
@@ -85,6 +102,13 @@ private:
visitNode(rootNode_, fN, fE);
}
+ template<typename NodeVisitorFunctor>
+ void visitNode(QNode *nd, NodeVisitorFunctor &fN)
+ {
+ fN(nd);
+ traverseChildren(fN);
+ }
+
template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
void visitNode(QNode *nd, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
{
@@ -109,6 +133,16 @@ private:
} // of children iteration
}
+ template<typename NodeVisitorFunctor>
+ void traverseChildren(NodeVisitorFunctor &fN)
+ {
+ Q_FOREACH (QObject *n, currentNode()->children()) {
+ QNode *node = qobject_cast<QNode *>(n);
+ if (node != Q_NULLPTR)
+ outerVisitNode(node, fN);
+ } // of children iteration
+ }
+
template<typename NodeVisitorFunctor, typename EntityVisitorFunctor>
void outerVisitNode(QNode *n, NodeVisitorFunctor &fN, EntityVisitorFunctor &fE)
{
@@ -116,10 +150,18 @@ private:
QEntity* e = qobject_cast<QEntity *>(n);
if (e) {
visitEntity(e, fN, fE);
- m_path.pop_back();
} else {
visitNode(n, fN, fE);
}
+ m_path.pop_back();
+ }
+
+ template<typename NodeVisitorFunctor>
+ void outerVisitNode(QNode *n, NodeVisitorFunctor &fN)
+ {
+ m_path.append(n);
+ visitNode(n, fN);
+ m_path.pop_back();
}
template <typename NodeType>
diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp
index f9700b60f..48bee2094 100644
--- a/src/core/transforms/qtransform.cpp
+++ b/src/core/transforms/qtransform.cpp
@@ -105,6 +105,7 @@ QTransform::QTransform(QTransformPrivate &dd, QNode *parent)
QTransform::~QTransform()
{
+ QNode::cleanup();
Q_D(QTransform);
// boost destruction by avoiding _q_update()-s
d->m_transforms.clear();
diff --git a/src/input/qinputaspect.cpp b/src/input/qinputaspect.cpp
index fc7fb8e8c..5b8c35abc 100644
--- a/src/input/qinputaspect.cpp
+++ b/src/input/qinputaspect.cpp
@@ -99,7 +99,7 @@ void QInputAspect::sceneNodeAdded(QSceneChangePtr &e)
QNodePtr nodePtr = propertyChange->value().value<QNodePtr>();
QNode *n = nodePtr.data();
QNodeVisitor visitor;
- visitor.traverse(n, this, &QInputAspect::visitNode, &QInputAspect::visitNode);
+ visitor.traverse(n, this, &QInputAspect::visitNode);
}
void QInputAspect::sceneNodeRemoved(QSceneChangePtr &e)
@@ -113,7 +113,7 @@ void QInputAspect::sceneNodeRemoved(QSceneChangePtr &e)
void QInputAspect::setRootEntity(QEntity *rootObject)
{
QNodeVisitor visitor;
- visitor.traverse(rootObject, this, &QInputAspect::visitNode, &QInputAspect::visitNode);
+ visitor.traverse(rootObject, this, &QInputAspect::visitNode);
}
void QInputAspect::onInitialize(const QVariantMap &data)
diff --git a/src/input/qkeyboardcontroller.cpp b/src/input/qkeyboardcontroller.cpp
index 69e93b479..0e984dd8c 100644
--- a/src/input/qkeyboardcontroller.cpp
+++ b/src/input/qkeyboardcontroller.cpp
@@ -58,6 +58,11 @@ QKeyboardController::QKeyboardController(QNode *parent)
{
}
+QKeyboardController::~QKeyboardController()
+{
+ QNode::cleanup();
+}
+
QKeyboardInput *QKeyboardController::activeInput() const
{
Q_D(const QKeyboardController);
diff --git a/src/input/qkeyboardcontroller.h b/src/input/qkeyboardcontroller.h
index df667b4d5..b2543192e 100644
--- a/src/input/qkeyboardcontroller.h
+++ b/src/input/qkeyboardcontroller.h
@@ -54,6 +54,7 @@ class QT3DINPUTSHARED_EXPORT QKeyboardController : public QNode
public:
explicit QKeyboardController(QNode *parent = 0);
+ ~QKeyboardController();
QKeyboardInput *activeInput() const;
diff --git a/src/input/qkeyboardinput.cpp b/src/input/qkeyboardinput.cpp
index e7030799d..8866ef94c 100644
--- a/src/input/qkeyboardinput.cpp
+++ b/src/input/qkeyboardinput.cpp
@@ -63,6 +63,11 @@ QKeyboardInput::QKeyboardInput(QNode *parent)
{
}
+QKeyboardInput::~QKeyboardInput()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QKeyboardInput::QKeyboardInput(QKeyboardInputPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/input/qkeyboardinput.h b/src/input/qkeyboardinput.h
index 5875a84d9..19e0d8ea9 100644
--- a/src/input/qkeyboardinput.h
+++ b/src/input/qkeyboardinput.h
@@ -55,6 +55,7 @@ class QT3DINPUTSHARED_EXPORT QKeyboardInput : public QComponent
Q_PROPERTY(bool focus READ focus WRITE setFocus NOTIFY focusChanged)
public:
explicit QKeyboardInput(QNode *parent = 0);
+ ~QKeyboardInput();
void setController(QKeyboardController *controller);
QKeyboardController *controller() const;
diff --git a/src/plugins/sceneparsers/assimp/assimpparser.cpp b/src/plugins/sceneparsers/assimp/assimpparser.cpp
index eab846dd3..272cc533a 100644
--- a/src/plugins/sceneparsers/assimp/assimpparser.cpp
+++ b/src/plugins/sceneparsers/assimp/assimpparser.cpp
@@ -257,6 +257,7 @@ class AssimpMesh : public QAbstractMesh
Q_OBJECT
public :
explicit AssimpMesh(QNode *parent = 0);
+ ~AssimpMesh();
void copy(const QNode *ref) Q_DECL_OVERRIDE;
QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_OVERRIDE;
@@ -891,6 +892,11 @@ AssimpMesh::AssimpMesh(QNode *parent)
{
}
+AssimpMesh::~AssimpMesh()
+{
+ QNode::cleanup();
+}
+
void AssimpMesh::copy(const QNode *ref)
{
QAbstractMesh::copy(ref);
diff --git a/src/quick3d/quick3d/items/quick3dentityloader.cpp b/src/quick3d/quick3d/items/quick3dentityloader.cpp
index 224c6e6d2..639451861 100644
--- a/src/quick3d/quick3d/items/quick3dentityloader.cpp
+++ b/src/quick3d/quick3d/items/quick3dentityloader.cpp
@@ -85,6 +85,11 @@ Quick3DEntityLoader::Quick3DEntityLoader(QNode *parent)
{
}
+Quick3DEntityLoader::~Quick3DEntityLoader()
+{
+ QNode::cleanup();
+}
+
/*!
\qmlproperty QtQml::QtObject Qt3D::EntityLoader::entity
\readonly
@@ -148,7 +153,7 @@ void Quick3DEntityLoaderPrivate::clear()
}
if (m_entity) {
- m_entity->setParent(Q_NULLPTR);
+ m_entity->setParent(Q_NODE_NULLPTR);
delete m_entity;
m_entity = Q_NULLPTR;
}
diff --git a/src/quick3d/quick3d/items/quick3dentityloader.h b/src/quick3d/quick3d/items/quick3dentityloader.h
index 66fa31644..0280ca3aa 100644
--- a/src/quick3d/quick3d/items/quick3dentityloader.h
+++ b/src/quick3d/quick3d/items/quick3dentityloader.h
@@ -62,6 +62,7 @@ class QT3DQUICKSHARED_EXPORT Quick3DEntityLoader : public QEntity
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
public:
explicit Quick3DEntityLoader(QNode *parent = 0);
+ ~Quick3DEntityLoader();
QObject *entity() const;
diff --git a/src/quick3d/quick3d/items/quick3dnode.cpp b/src/quick3d/quick3d/items/quick3dnode.cpp
index 3a93e0211..c230df447 100644
--- a/src/quick3d/quick3d/items/quick3dnode.cpp
+++ b/src/quick3d/quick3d/items/quick3dnode.cpp
@@ -149,14 +149,18 @@ void Quick3DNode::childAppended(int, QObject *obj)
if (obj->parent() == parentNode)
obj->setParent(0);
// Set after otherwise addChild might not work
- obj->setParent(parentNode);
+ if (QNode *n = qobject_cast<QNode *>(obj))
+ n->setParent(parentNode);
+ else
+ obj->setParent(parentNode);
}
void Quick3DNode::childRemoved(int, QObject *obj)
{
- QNode *node = qobject_cast<Qt3D::QNode *>(obj);
- if (node)
- node->setParent(Q_NULLPTR);
+ if (QNode *n = qobject_cast<QNode *>(obj))
+ n->setParent(Q_NODE_NULLPTR);
+ else
+ obj->setParent(Q_NULLPTR);
}
} // Quick
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
index 43c5b0f9e..c6257ec58 100644
--- a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
@@ -119,7 +119,7 @@ void Quick3DNodeInstantiatorPrivate::_q_createdItem(int idx, QObject *item)
Q_Q(Quick3DNodeInstantiator);
if (m_objects.contains(item)) //Case when it was created synchronously in regenerate
return;
- item->setParent(q);
+ static_cast<QNode *>(item)->setParent(q);
m_objects.insert(idx, item);
if (m_objects.count() == 1)
q->objectChanged();
@@ -218,6 +218,7 @@ Quick3DNodeInstantiator::Quick3DNodeInstantiator(QNode *parent)
Quick3DNodeInstantiator::~Quick3DNodeInstantiator()
{
+ QNode::cleanup();
}
/*!
diff --git a/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.cpp b/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.cpp
index 2b636a319..b5f0bc8de 100644
--- a/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.cpp
+++ b/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.cpp
@@ -60,6 +60,11 @@ Quick3DShaderDataArray::Quick3DShaderDataArray(QNode *parent)
{
}
+Quick3DShaderDataArray::~Quick3DShaderDataArray()
+{
+ QNode::cleanup();
+}
+
QQmlListProperty<QShaderData> Quick3DShaderDataArray::valuesList()
{
return QQmlListProperty<QShaderData>(this, 0,
diff --git a/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.h b/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.h
index 7e663fbb9..c9fa3d58d 100644
--- a/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.h
+++ b/src/quick3d/quick3drenderer/items/quick3dshaderdataarray.h
@@ -62,6 +62,7 @@ class QT3DQUICKRENDERERSHARED_EXPORT Quick3DShaderDataArray : public QNode
Q_CLASSINFO("DefaultProperty", "values")
public:
explicit Quick3DShaderDataArray(QNode *parent = 0);
+ ~Quick3DShaderDataArray();
QQmlListProperty<QShaderData> valuesList();
QList<QShaderData *> values() const;
diff --git a/src/render/backend/qrenderaspect.cpp b/src/render/backend/qrenderaspect.cpp
index 3a98ccc07..536c612ef 100644
--- a/src/render/backend/qrenderaspect.cpp
+++ b/src/render/backend/qrenderaspect.cpp
@@ -313,7 +313,7 @@ void QRenderAspect::sceneNodeAdded(QSceneChangePtr &e)
QNodePtr nodePtr = propertyChange->value().value<QNodePtr>();
QNode *n = nodePtr.data();
QNodeVisitor visitor;
- visitor.traverse(n, this, &QRenderAspect::visitNode, &QRenderAspect::visitNode);
+ visitor.traverse(n, this, &QRenderAspect::visitNode);
}
void QRenderAspect::sceneNodeRemoved(QSceneChangePtr &e)
@@ -335,7 +335,7 @@ void QRenderAspect::setRootEntity(QEntity *rootObject)
// setSceneGraphRoot is synchronized using the Renderer's mutex
Q_D(QRenderAspect);
QNodeVisitor visitor;
- visitor.traverse(rootObject, this, &QRenderAspect::visitNode, &QRenderAspect::visitNode);
+ visitor.traverse(rootObject, this, &QRenderAspect::visitNode);
d->m_renderer->setSceneGraphRoot(d->m_renderer->renderNodesManager()->lookupResource(rootObject->id()));
}
diff --git a/src/render/backend/renderentity.cpp b/src/render/backend/renderentity.cpp
index dbc39c40f..ffe78efb9 100644
--- a/src/render/backend/renderentity.cpp
+++ b/src/render/backend/renderentity.cpp
@@ -131,7 +131,7 @@ void RenderEntity::setHandle(HEntity handle)
void RenderEntity::updateFromPeer(QNode *peer)
{
QEntity *entity = static_cast<QEntity *>(peer);
- QEntity *parentEntity = entity->parentEntity();
+ const QNodeId parentEntityId = entity->parentEntityId();
m_objectName = peer->objectName();
m_worldTransform = m_renderer->worldMatrixManager()->getOrAcquireHandle(peerUuid());
@@ -147,8 +147,11 @@ void RenderEntity::updateFromPeer(QNode *peer)
Q_FOREACH (QComponent *comp, entity->components())
addComponent(comp);
- if (parentEntity != Q_NULLPTR)
- setParentHandle(m_renderer->renderNodesManager()->lookupHandle(parentEntity->id()));
+ if (!parentEntityId.isNull()) {
+ setParentHandle(m_renderer->renderNodesManager()->lookupHandle(parentEntityId));
+ } else {
+ qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "No parent entity found for Entity" << peerUuid();
+ }
}
void RenderEntity::sceneChangeEvent(const QSceneChangePtr &e)
diff --git a/src/render/defaults/qskyboxentity.cpp b/src/render/defaults/qskyboxentity.cpp
index 457fa746a..a2a1e0eaf 100644
--- a/src/render/defaults/qskyboxentity.cpp
+++ b/src/render/defaults/qskyboxentity.cpp
@@ -212,6 +212,7 @@ QSkyboxEntity::QSkyboxEntity(QNode *parent)
QSkyboxEntity::~QSkyboxEntity()
{
+ QNode::cleanup();
}
/*!
diff --git a/src/render/frontend/framegraph-components/qcameraselector.cpp b/src/render/frontend/framegraph-components/qcameraselector.cpp
index b4dc83727..5085adf45 100644
--- a/src/render/frontend/framegraph-components/qcameraselector.cpp
+++ b/src/render/frontend/framegraph-components/qcameraselector.cpp
@@ -76,6 +76,11 @@ QCameraSelector::QCameraSelector(Qt3D::QNode *parent)
: QFrameGraphNode(*new QCameraSelectorPrivate, parent)
{}
+QCameraSelector::~QCameraSelector()
+{
+ QNode::cleanup();
+}
+
void QCameraSelector::setCamera(QEntity *camera)
{
Q_D(QCameraSelector);
diff --git a/src/render/frontend/framegraph-components/qcameraselector.h b/src/render/frontend/framegraph-components/qcameraselector.h
index 023f5f13a..4811d7a96 100644
--- a/src/render/frontend/framegraph-components/qcameraselector.h
+++ b/src/render/frontend/framegraph-components/qcameraselector.h
@@ -54,6 +54,7 @@ class QT3DRENDERERSHARED_EXPORT QCameraSelector : public QFrameGraphNode
public:
explicit QCameraSelector(QNode *parent = 0);
+ ~QCameraSelector();
void setCamera(QEntity *camera);
QEntity *camera() const;
diff --git a/src/render/frontend/framegraph-components/qclearbuffer.cpp b/src/render/frontend/framegraph-components/qclearbuffer.cpp
index e6fc20a84..f40a80883 100644
--- a/src/render/frontend/framegraph-components/qclearbuffer.cpp
+++ b/src/render/frontend/framegraph-components/qclearbuffer.cpp
@@ -64,6 +64,11 @@ QClearBuffer::QClearBuffer(QNode *parent)
{
}
+QClearBuffer::~QClearBuffer()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QClearBuffer::QClearBuffer(QClearBufferPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qclearbuffer.h b/src/render/frontend/framegraph-components/qclearbuffer.h
index 1559511d3..782ec6ef4 100644
--- a/src/render/frontend/framegraph-components/qclearbuffer.h
+++ b/src/render/frontend/framegraph-components/qclearbuffer.h
@@ -51,6 +51,7 @@ class QT3DRENDERERSHARED_EXPORT QClearBuffer : public QFrameGraphNode
Q_PROPERTY(BufferType buffers READ buffers WRITE setBuffers NOTIFY buffersChanged)
public:
explicit QClearBuffer(QNode *parent = 0);
+ ~QClearBuffer();
enum BufferType {
None = 0,
diff --git a/src/render/frontend/framegraph-components/qframegraph.cpp b/src/render/frontend/framegraph-components/qframegraph.cpp
index 754e90ed3..629128180 100644
--- a/src/render/frontend/framegraph-components/qframegraph.cpp
+++ b/src/render/frontend/framegraph-components/qframegraph.cpp
@@ -98,6 +98,11 @@ QFrameGraph::QFrameGraph(QNode *parent)
{
}
+QFrameGraph::~QFrameGraph()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QFrameGraph::QFrameGraph(QFrameGraphPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qframegraph.h b/src/render/frontend/framegraph-components/qframegraph.h
index c8a88996b..9dc3fbc76 100644
--- a/src/render/frontend/framegraph-components/qframegraph.h
+++ b/src/render/frontend/framegraph-components/qframegraph.h
@@ -47,7 +47,7 @@ namespace Qt3D {
class QFrameGraphPrivate;
class QFrameGraphNode;
-class QT3DRENDERERSHARED_EXPORT QFrameGraph : public Qt3D::QComponent
+class QT3DRENDERERSHARED_EXPORT QFrameGraph : public QComponent
{
Q_OBJECT
// Note : The full namespace has to be used to define the property
@@ -57,6 +57,7 @@ class QT3DRENDERERSHARED_EXPORT QFrameGraph : public Qt3D::QComponent
public:
explicit QFrameGraph(QNode *parent = 0);
+ ~QFrameGraph();
QFrameGraphNode *activeFrameGraph() const;
void setActiveFrameGraph(QFrameGraphNode *activeFrameGraph);
diff --git a/src/render/frontend/framegraph-components/qframegraphnode.cpp b/src/render/frontend/framegraph-components/qframegraphnode.cpp
index 2f81b786e..ad5a8dbd5 100644
--- a/src/render/frontend/framegraph-components/qframegraphnode.cpp
+++ b/src/render/frontend/framegraph-components/qframegraphnode.cpp
@@ -80,6 +80,11 @@ QFrameGraphNode::QFrameGraphNode(QNode *parent)
{
}
+QFrameGraphNode::~QFrameGraphNode()
+{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QFrameGraphNode subclass didn't call QNode::cleanup in its destructor");
+}
+
/*!
Returns a pointer to the parent.
*/
diff --git a/src/render/frontend/framegraph-components/qframegraphnode.h b/src/render/frontend/framegraph-components/qframegraphnode.h
index 7fb5e4dfa..b13fd6eb6 100644
--- a/src/render/frontend/framegraph-components/qframegraphnode.h
+++ b/src/render/frontend/framegraph-components/qframegraphnode.h
@@ -53,6 +53,7 @@ class QT3DRENDERERSHARED_EXPORT QFrameGraphNode : public QNode
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
public:
explicit QFrameGraphNode(QNode *parent = 0);
+ ~QFrameGraphNode();
QFrameGraphNode *parentFrameGraphNode() const;
diff --git a/src/render/frontend/framegraph-components/qframegraphselector.cpp b/src/render/frontend/framegraph-components/qframegraphselector.cpp
index 20fba808c..6b912f974 100644
--- a/src/render/frontend/framegraph-components/qframegraphselector.cpp
+++ b/src/render/frontend/framegraph-components/qframegraphselector.cpp
@@ -71,6 +71,7 @@ QFrameGraphSelector::QFrameGraphSelector(QNode *parent)
QFrameGraphSelector::~QFrameGraphSelector()
{
+ QNode::cleanup();
}
/*!
diff --git a/src/render/frontend/framegraph-components/qlayerfilter.cpp b/src/render/frontend/framegraph-components/qlayerfilter.cpp
index cfccfb987..8df0d6416 100644
--- a/src/render/frontend/framegraph-components/qlayerfilter.cpp
+++ b/src/render/frontend/framegraph-components/qlayerfilter.cpp
@@ -86,6 +86,11 @@ QLayerFilter::QLayerFilter(QNode *parent)
{
}
+QLayerFilter::~QLayerFilter()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QLayerFilter::QLayerFilter(QLayerFilterPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qlayerfilter.h b/src/render/frontend/framegraph-components/qlayerfilter.h
index 817e01bd6..83b97b1e0 100644
--- a/src/render/frontend/framegraph-components/qlayerfilter.h
+++ b/src/render/frontend/framegraph-components/qlayerfilter.h
@@ -52,6 +52,7 @@ class QT3DRENDERERSHARED_EXPORT QLayerFilter : public QFrameGraphNode
Q_PROPERTY(QStringList layers READ layers WRITE setLayers NOTIFY layersChanged)
public:
explicit QLayerFilter(QNode *parent = 0);
+ ~QLayerFilter();
void setLayers(const QStringList &layers);
QStringList layers() const;
diff --git a/src/render/frontend/framegraph-components/qnodraw.cpp b/src/render/frontend/framegraph-components/qnodraw.cpp
index 0c11f5b34..ed695145d 100644
--- a/src/render/frontend/framegraph-components/qnodraw.cpp
+++ b/src/render/frontend/framegraph-components/qnodraw.cpp
@@ -62,6 +62,7 @@ QNoDraw::QNoDraw(QNode *parent)
QNoDraw::~QNoDraw()
{
+ QNode::cleanup();
}
} // Qt3D
diff --git a/src/render/frontend/framegraph-components/qrenderpassfilter.cpp b/src/render/frontend/framegraph-components/qrenderpassfilter.cpp
index 85fddc7b6..a0c845b00 100644
--- a/src/render/frontend/framegraph-components/qrenderpassfilter.cpp
+++ b/src/render/frontend/framegraph-components/qrenderpassfilter.cpp
@@ -54,6 +54,11 @@ QRenderPassFilter::QRenderPassFilter(QNode *parent)
: QFrameGraphNode(*new QRenderPassFilterPrivate, parent)
{}
+QRenderPassFilter::~QRenderPassFilter()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QRenderPassFilter::QRenderPassFilter(QRenderPassFilterPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qrenderpassfilter.h b/src/render/frontend/framegraph-components/qrenderpassfilter.h
index 27848d19f..e0f71a78b 100644
--- a/src/render/frontend/framegraph-components/qrenderpassfilter.h
+++ b/src/render/frontend/framegraph-components/qrenderpassfilter.h
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QRenderPassFilter : public QFrameGraphNode
public:
explicit QRenderPassFilter(QNode *parent = 0);
+ ~QRenderPassFilter();
QList<QAnnotation *> includes() const;
void addInclude(QAnnotation *criterion);
diff --git a/src/render/frontend/framegraph-components/qrendertargetselector.cpp b/src/render/frontend/framegraph-components/qrendertargetselector.cpp
index fd5a58640..069252766 100644
--- a/src/render/frontend/framegraph-components/qrendertargetselector.cpp
+++ b/src/render/frontend/framegraph-components/qrendertargetselector.cpp
@@ -69,6 +69,11 @@ QRenderTargetSelector::QRenderTargetSelector(QNode *parent)
{
}
+QRenderTargetSelector::~QRenderTargetSelector()
+{
+ QNode::cleanup();
+}
+
void QRenderTargetSelector::setTarget(QRenderTarget *target)
{
Q_D(QRenderTargetSelector);
diff --git a/src/render/frontend/framegraph-components/qrendertargetselector.h b/src/render/frontend/framegraph-components/qrendertargetselector.h
index f98f05f8f..33529d4d9 100644
--- a/src/render/frontend/framegraph-components/qrendertargetselector.h
+++ b/src/render/frontend/framegraph-components/qrendertargetselector.h
@@ -55,6 +55,7 @@ class QT3DRENDERERSHARED_EXPORT QRenderTargetSelector : public QFrameGraphNode
Q_PROPERTY(Qt3D::QRenderTarget *target READ target WRITE setTarget NOTIFY targetChanged)
public:
explicit QRenderTargetSelector(QNode *parent = 0);
+ ~QRenderTargetSelector();
void setTarget(QRenderTarget *target);
QRenderTarget *target() const;
diff --git a/src/render/frontend/framegraph-components/qsortcriterion.cpp b/src/render/frontend/framegraph-components/qsortcriterion.cpp
index 85b5cd9fa..a85608df9 100644
--- a/src/render/frontend/framegraph-components/qsortcriterion.cpp
+++ b/src/render/frontend/framegraph-components/qsortcriterion.cpp
@@ -64,6 +64,11 @@ QSortCriterion::QSortCriterion(QNode *parent)
{
}
+QSortCriterion::~QSortCriterion()
+{
+ QNode::cleanup();
+}
+
QSortCriterion::SortType QSortCriterion::sort() const
{
Q_D(const QSortCriterion);
diff --git a/src/render/frontend/framegraph-components/qsortcriterion.h b/src/render/frontend/framegraph-components/qsortcriterion.h
index ef413eeb5..b3b7848a4 100644
--- a/src/render/frontend/framegraph-components/qsortcriterion.h
+++ b/src/render/frontend/framegraph-components/qsortcriterion.h
@@ -52,6 +52,7 @@ class QT3DRENDERERSHARED_EXPORT QSortCriterion : public QNode
Q_PROPERTY(Qt3D::QSortCriterion::SortType sort READ sort WRITE setSort NOTIFY sortChanged)
public:
explicit QSortCriterion(QNode *parent = 0);
+ ~QSortCriterion();
enum SortType {
StateChangeCost = (1 << 0),
diff --git a/src/render/frontend/framegraph-components/qsortmethod.cpp b/src/render/frontend/framegraph-components/qsortmethod.cpp
index 4f70dd7cd..824c8d198 100644
--- a/src/render/frontend/framegraph-components/qsortmethod.cpp
+++ b/src/render/frontend/framegraph-components/qsortmethod.cpp
@@ -66,6 +66,11 @@ QSortMethod::QSortMethod(QNode *parent)
{
}
+QSortMethod::~QSortMethod()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QSortMethod::QSortMethod(QSortMethodPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qsortmethod.h b/src/render/frontend/framegraph-components/qsortmethod.h
index 5cb37c9dc..c0f17fdd4 100644
--- a/src/render/frontend/framegraph-components/qsortmethod.h
+++ b/src/render/frontend/framegraph-components/qsortmethod.h
@@ -52,6 +52,7 @@ class QT3DRENDERERSHARED_EXPORT QSortMethod : public QFrameGraphNode
public:
explicit QSortMethod(QNode *parent = 0);
+ ~QSortMethod();
void addCriterion(QSortCriterion *criterion);
void removeCriterion(QSortCriterion *criterion);
diff --git a/src/render/frontend/framegraph-components/qstateset.cpp b/src/render/frontend/framegraph-components/qstateset.cpp
index 6f5149b87..602876d5d 100644
--- a/src/render/frontend/framegraph-components/qstateset.cpp
+++ b/src/render/frontend/framegraph-components/qstateset.cpp
@@ -79,6 +79,7 @@ QStateSet::QStateSet(QStateSetPrivate &dd, QNode *parent)
QStateSet::~QStateSet()
{
+ QNode::cleanup();
}
void QStateSet::copy(const QNode *ref)
diff --git a/src/render/frontend/framegraph-components/qtechniquefilter.cpp b/src/render/frontend/framegraph-components/qtechniquefilter.cpp
index 7d93b40be..1a1efc553 100644
--- a/src/render/frontend/framegraph-components/qtechniquefilter.cpp
+++ b/src/render/frontend/framegraph-components/qtechniquefilter.cpp
@@ -68,6 +68,11 @@ QTechniqueFilter::QTechniqueFilter(QNode *parent)
{
}
+QTechniqueFilter::~QTechniqueFilter()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QTechniqueFilter::QTechniqueFilter(QTechniqueFilterPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qtechniquefilter.h b/src/render/frontend/framegraph-components/qtechniquefilter.h
index b7ddcb9b4..eae99d231 100644
--- a/src/render/frontend/framegraph-components/qtechniquefilter.h
+++ b/src/render/frontend/framegraph-components/qtechniquefilter.h
@@ -53,6 +53,7 @@ class QT3DRENDERERSHARED_EXPORT QTechniqueFilter : public QFrameGraphNode
Q_OBJECT
public:
explicit QTechniqueFilter(QNode *parent = 0);
+ ~QTechniqueFilter();
QList<QAnnotation *> criteria() const;
void addRequirement(QAnnotation *criterion);
diff --git a/src/render/frontend/framegraph-components/qviewport.cpp b/src/render/frontend/framegraph-components/qviewport.cpp
index 49ae81231..6197dcd52 100644
--- a/src/render/frontend/framegraph-components/qviewport.cpp
+++ b/src/render/frontend/framegraph-components/qviewport.cpp
@@ -65,6 +65,11 @@ QViewport::QViewport(QNode *parent)
{
}
+QViewport::~QViewport()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QViewport::QViewport(QViewportPrivate &dd, QNode *parent)
: QFrameGraphNode(dd, parent)
diff --git a/src/render/frontend/framegraph-components/qviewport.h b/src/render/frontend/framegraph-components/qviewport.h
index 73e3c5f1a..7390e85ae 100644
--- a/src/render/frontend/framegraph-components/qviewport.h
+++ b/src/render/frontend/framegraph-components/qviewport.h
@@ -55,6 +55,7 @@ class QT3DRENDERERSHARED_EXPORT QViewport : public QFrameGraphNode
public:
explicit QViewport(QNode *parent = 0);
+ ~QViewport();
QRectF rect() const;
void setRect(const QRectF& rect);
diff --git a/src/render/frontend/qabstractmesh.cpp b/src/render/frontend/qabstractmesh.cpp
index a4d6a163e..c81f5aa8f 100644
--- a/src/render/frontend/qabstractmesh.cpp
+++ b/src/render/frontend/qabstractmesh.cpp
@@ -76,6 +76,11 @@ QAbstractMesh::QAbstractMesh(QNode *parent)
{
}
+QAbstractMesh::~QAbstractMesh()
+{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QAbstractMesh subclass didn't call QNode::cleanup in its destructor");
+}
+
/*! \internal */
QAbstractMesh::QAbstractMesh(QAbstractMeshPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/render/frontend/qabstractmesh.h b/src/render/frontend/qabstractmesh.h
index 1be436846..f90e05dff 100644
--- a/src/render/frontend/qabstractmesh.h
+++ b/src/render/frontend/qabstractmesh.h
@@ -65,7 +65,8 @@ class QT3DRENDERERSHARED_EXPORT QAbstractMesh : public QComponent
Q_OBJECT
public:
- QAbstractMesh(QNode *parent = 0);
+ explicit QAbstractMesh(QNode *parent = 0);
+ ~QAbstractMesh();
void update();
diff --git a/src/render/frontend/qabstractsceneloader.cpp b/src/render/frontend/qabstractsceneloader.cpp
index f919a489e..4108b81e5 100644
--- a/src/render/frontend/qabstractsceneloader.cpp
+++ b/src/render/frontend/qabstractsceneloader.cpp
@@ -69,6 +69,11 @@ QAbstractSceneLoader::QAbstractSceneLoader(QNode *parent)
{
}
+QAbstractSceneLoader::~QAbstractSceneLoader()
+{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QAbstractSceneLoader subclass didn't call QNode::cleanup in its destructor");
+}
+
void QAbstractSceneLoader::copy(const QNode *ref)
{
const QAbstractSceneLoader *s = static_cast<const QAbstractSceneLoader*>(ref);
diff --git a/src/render/frontend/qabstractsceneloader.h b/src/render/frontend/qabstractsceneloader.h
index 14aa02e2a..368eb4bc6 100644
--- a/src/render/frontend/qabstractsceneloader.h
+++ b/src/render/frontend/qabstractsceneloader.h
@@ -57,6 +57,7 @@ class QT3DRENDERERSHARED_EXPORT QAbstractSceneLoader : public QComponent
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
explicit QAbstractSceneLoader(QNode *parent = 0);
+ ~QAbstractSceneLoader();
enum Status {
Loading = 0,
diff --git a/src/render/frontend/qabstracttextureimage.cpp b/src/render/frontend/qabstracttextureimage.cpp
index 96d679df6..356a64b08 100644
--- a/src/render/frontend/qabstracttextureimage.cpp
+++ b/src/render/frontend/qabstracttextureimage.cpp
@@ -89,6 +89,7 @@ QAbstractTextureImage::QAbstractTextureImage(QNode *parent)
*/
QAbstractTextureImage::~QAbstractTextureImage()
{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QAbstractTextureImage subclass didn't call QNode::cleanup in its destructor");
}
diff --git a/src/render/frontend/qabstracttextureprovider.cpp b/src/render/frontend/qabstracttextureprovider.cpp
index 75ea92f03..8aaa302b2 100644
--- a/src/render/frontend/qabstracttextureprovider.cpp
+++ b/src/render/frontend/qabstracttextureprovider.cpp
@@ -120,6 +120,9 @@ QAbstractTextureProvider::QAbstractTextureProvider(QAbstractTextureProviderPriva
QAbstractTextureProvider::~QAbstractTextureProvider()
{
+ // The subclasses of QAbstractTextureProvider are only there to set the type on a QTextureProvider
+ // QNode::cleanup needs to be handled here and not in the subclasses.
+ QNode::cleanup();
}
/*!
diff --git a/src/render/frontend/qabstracttextureprovider.h b/src/render/frontend/qabstracttextureprovider.h
index 025270cd5..9f3e385e4 100644
--- a/src/render/frontend/qabstracttextureprovider.h
+++ b/src/render/frontend/qabstracttextureprovider.h
@@ -250,7 +250,6 @@ public:
~QAbstractTextureProvider();
-
Target target() const;
void setFormat(TextureFormat format);
diff --git a/src/render/frontend/qalphacoverage.cpp b/src/render/frontend/qalphacoverage.cpp
index c96980d90..2075b2704 100644
--- a/src/render/frontend/qalphacoverage.cpp
+++ b/src/render/frontend/qalphacoverage.cpp
@@ -57,6 +57,11 @@ QAlphaCoverage::QAlphaCoverage(QNode *parent)
{
}
+QAlphaCoverage::~QAlphaCoverage()
+{
+ QNode::cleanup();
+}
+
} // Qt3D
QT_END_NAMESPACE
diff --git a/src/render/frontend/qalphacoverage.h b/src/render/frontend/qalphacoverage.h
index 9f92bd15d..7ac1c7765 100644
--- a/src/render/frontend/qalphacoverage.h
+++ b/src/render/frontend/qalphacoverage.h
@@ -51,6 +51,7 @@ class QT3DRENDERERSHARED_EXPORT QAlphaCoverage : public QRenderState
Q_OBJECT
public:
explicit QAlphaCoverage(QNode *parent = 0);
+ ~QAlphaCoverage();
private:
Q_DECLARE_PRIVATE(QAlphaCoverage)
diff --git a/src/render/frontend/qalphatest.cpp b/src/render/frontend/qalphatest.cpp
index 1b0498392..1fb92db3a 100644
--- a/src/render/frontend/qalphatest.cpp
+++ b/src/render/frontend/qalphatest.cpp
@@ -64,6 +64,11 @@ QAlphaTest::QAlphaTest(QNode *parent)
{
}
+QAlphaTest::~QAlphaTest()
+{
+ QNode::cleanup();
+}
+
void QAlphaTest::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qalphatest.h b/src/render/frontend/qalphatest.h
index 645677762..4e8e86ca6 100644
--- a/src/render/frontend/qalphatest.h
+++ b/src/render/frontend/qalphatest.h
@@ -66,6 +66,7 @@ public:
Q_ENUM(AlphaFunc)
explicit QAlphaTest(QNode *parent = 0);
+ ~QAlphaTest();
AlphaFunc func() const;
void setFunc(AlphaFunc func);
diff --git a/src/render/frontend/qannotation.cpp b/src/render/frontend/qannotation.cpp
index 0476e1d6a..9cb67f65c 100644
--- a/src/render/frontend/qannotation.cpp
+++ b/src/render/frontend/qannotation.cpp
@@ -88,6 +88,11 @@ QAnnotation::QAnnotation(QNode *parent)
{
}
+QAnnotation::~QAnnotation()
+{
+ QNode::cleanup();
+}
+
void QAnnotation::setValue(const QVariant &value)
{
Q_D(QAnnotation);
diff --git a/src/render/frontend/qannotation.h b/src/render/frontend/qannotation.h
index 639de2e0e..424177161 100644
--- a/src/render/frontend/qannotation.h
+++ b/src/render/frontend/qannotation.h
@@ -54,6 +54,7 @@ class QT3DRENDERERSHARED_EXPORT QAnnotation : public QNode
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
explicit QAnnotation(QNode *parent = 0);
+ ~QAnnotation();
void setValue(const QVariant &value);
void setName(const QString &customType);
diff --git a/src/render/frontend/qblendequation.cpp b/src/render/frontend/qblendequation.cpp
index 9960bb2b8..1631a74dd 100644
--- a/src/render/frontend/qblendequation.cpp
+++ b/src/render/frontend/qblendequation.cpp
@@ -68,6 +68,11 @@ QBlendEquation::QBlendEquation(QNode *parent)
{
}
+QBlendEquation::~QBlendEquation()
+{
+ QNode::cleanup();
+}
+
QBlendEquation::BlendMode QBlendEquation::mode() const
{
Q_D(const QBlendEquation);
diff --git a/src/render/frontend/qblendequation.h b/src/render/frontend/qblendequation.h
index 280df3155..78df85183 100644
--- a/src/render/frontend/qblendequation.h
+++ b/src/render/frontend/qblendequation.h
@@ -63,6 +63,7 @@ public:
Q_ENUM(BlendMode)
explicit QBlendEquation(QNode *parent = 0);
+ ~QBlendEquation();
BlendMode mode() const;
void setMode(BlendMode mode);
diff --git a/src/render/frontend/qblendstate.cpp b/src/render/frontend/qblendstate.cpp
index 642ce03ab..6711a99db 100644
--- a/src/render/frontend/qblendstate.cpp
+++ b/src/render/frontend/qblendstate.cpp
@@ -88,6 +88,11 @@ QBlendState::QBlendState(QNode *parent)
{
}
+QBlendState::~QBlendState()
+{
+ QNode::cleanup();
+}
+
/*! \fn void QBlendState::copy(const QNode *ref)
\internal
Copies \a ref into this object.
diff --git a/src/render/frontend/qblendstate.h b/src/render/frontend/qblendstate.h
index 2217944f3..7f3901f22 100644
--- a/src/render/frontend/qblendstate.h
+++ b/src/render/frontend/qblendstate.h
@@ -81,6 +81,7 @@ public:
Q_ENUM(Blending)
explicit QBlendState(QNode *parent = 0);
+ ~QBlendState();
Blending srcRGB() const;
void setSrcRGB(Blending srcRGB);
diff --git a/src/render/frontend/qcolormask.cpp b/src/render/frontend/qcolormask.cpp
index 923f16b4d..7d7c79481 100644
--- a/src/render/frontend/qcolormask.cpp
+++ b/src/render/frontend/qcolormask.cpp
@@ -83,6 +83,7 @@ QColorMask::QColorMask(QNode *parent)
QColorMask::~QColorMask()
{
+ QNode::cleanup();
}
bool QColorMask::isRed() const
diff --git a/src/render/frontend/qcuboidmesh.cpp b/src/render/frontend/qcuboidmesh.cpp
index 26238f8b6..665eafd7a 100644
--- a/src/render/frontend/qcuboidmesh.cpp
+++ b/src/render/frontend/qcuboidmesh.cpp
@@ -81,6 +81,11 @@ QCuboidMesh::QCuboidMesh(QNode *parent)
update();
}
+QCuboidMesh::~QCuboidMesh()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QCuboidMesh::QCuboidMesh(QCuboidMeshPrivate &dd, QNode *parent)
: QAbstractMesh(dd, parent)
diff --git a/src/render/frontend/qcuboidmesh.h b/src/render/frontend/qcuboidmesh.h
index 46fdad0e0..4568ddf3a 100644
--- a/src/render/frontend/qcuboidmesh.h
+++ b/src/render/frontend/qcuboidmesh.h
@@ -47,7 +47,7 @@ namespace Qt3D {
class QCuboidMeshPrivate;
-class QT3DRENDERERSHARED_EXPORT QCuboidMesh : public Qt3D::QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QCuboidMesh : public QAbstractMesh
{
Q_OBJECT
@@ -60,6 +60,7 @@ class QT3DRENDERERSHARED_EXPORT QCuboidMesh : public Qt3D::QAbstractMesh
public:
explicit QCuboidMesh(QNode *parent = 0);
+ ~QCuboidMesh();
void setXExtent(float xExtent);
float xExtent() const;
diff --git a/src/render/frontend/qcullface.cpp b/src/render/frontend/qcullface.cpp
index cf2303ee6..4bd885c34 100644
--- a/src/render/frontend/qcullface.cpp
+++ b/src/render/frontend/qcullface.cpp
@@ -62,6 +62,11 @@ QCullFace::QCullFace(QNode *parent)
{
}
+QCullFace::~QCullFace()
+{
+ QNode::cleanup();
+}
+
void QCullFace::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qcullface.h b/src/render/frontend/qcullface.h
index 3321e0cd0..646df0811 100644
--- a/src/render/frontend/qcullface.h
+++ b/src/render/frontend/qcullface.h
@@ -63,6 +63,7 @@ public:
Q_ENUM(CullingMode)
explicit QCullFace(QNode *parent = 0);
+ ~QCullFace();
CullingMode mode() const;
void setMode(CullingMode mode);
diff --git a/src/render/frontend/qcylindermesh.cpp b/src/render/frontend/qcylindermesh.cpp
index f7fe495c9..c45e68a74 100644
--- a/src/render/frontend/qcylindermesh.cpp
+++ b/src/render/frontend/qcylindermesh.cpp
@@ -99,6 +99,10 @@ QCylinderMesh::QCylinderMesh(QNode *parent)
update();
}
+QCylinderMesh::~QCylinderMesh()
+{
+ QNode::cleanup();
+}
void QCylinderMesh::setRings(int rings)
{
diff --git a/src/render/frontend/qcylindermesh.h b/src/render/frontend/qcylindermesh.h
index e33c835e6..13fc0f864 100644
--- a/src/render/frontend/qcylindermesh.h
+++ b/src/render/frontend/qcylindermesh.h
@@ -47,7 +47,7 @@ namespace Qt3D {
class QCylinderMeshPrivate;
-class QT3DRENDERERSHARED_EXPORT QCylinderMesh : public Qt3D::QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QCylinderMesh : public QAbstractMesh
{
Q_OBJECT
Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged)
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QCylinderMesh : public Qt3D::QAbstractMesh
Q_PROPERTY(float length READ length WRITE setLength NOTIFY lengthChanged)
public:
explicit QCylinderMesh(QNode *parent = 0);
+ ~QCylinderMesh();
void setRings(int rings);
void setSlices(int slices);
diff --git a/src/render/frontend/qdepthmask.cpp b/src/render/frontend/qdepthmask.cpp
index d3cb3d047..df95b08d7 100644
--- a/src/render/frontend/qdepthmask.cpp
+++ b/src/render/frontend/qdepthmask.cpp
@@ -62,6 +62,11 @@ QDepthMask::QDepthMask(QNode *parent)
{
}
+QDepthMask::~QDepthMask()
+{
+ QNode::cleanup();
+}
+
void QDepthMask::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qdepthmask.h b/src/render/frontend/qdepthmask.h
index af28d6fac..d8f33d651 100644
--- a/src/render/frontend/qdepthmask.h
+++ b/src/render/frontend/qdepthmask.h
@@ -52,6 +52,7 @@ class QT3DRENDERERSHARED_EXPORT QDepthMask : public QRenderState
Q_PROPERTY (bool mask READ mask WRITE setMask NOTIFY maskChanged)
public:
explicit QDepthMask(QNode *parent = 0);
+ ~QDepthMask();
bool mask() const;
void setMask(bool mask);
diff --git a/src/render/frontend/qdepthtest.cpp b/src/render/frontend/qdepthtest.cpp
index 331a5be8d..716544dac 100644
--- a/src/render/frontend/qdepthtest.cpp
+++ b/src/render/frontend/qdepthtest.cpp
@@ -71,6 +71,11 @@ QDepthTest::QDepthTest(QNode *parent)
{
}
+QDepthTest::~QDepthTest()
+{
+ QNode::cleanup();
+}
+
QDepthTest::DepthFunc QDepthTest::func() const
{
Q_D(const QDepthTest);
diff --git a/src/render/frontend/qdepthtest.h b/src/render/frontend/qdepthtest.h
index 07579a4e9..e58dc25e7 100644
--- a/src/render/frontend/qdepthtest.h
+++ b/src/render/frontend/qdepthtest.h
@@ -65,6 +65,7 @@ public:
Q_ENUM(DepthFunc)
explicit QDepthTest(QNode *parent = 0);
+ ~QDepthTest();
DepthFunc func() const;
void setFunc(DepthFunc func);
diff --git a/src/render/frontend/qdithering.cpp b/src/render/frontend/qdithering.cpp
index 6d8bb5fdf..c82272644 100644
--- a/src/render/frontend/qdithering.cpp
+++ b/src/render/frontend/qdithering.cpp
@@ -59,6 +59,11 @@ QDithering::QDithering(QNode *parent)
{
}
+QDithering::~QDithering()
+{
+ QNode::cleanup();
+}
+
} // Qt3D
QT_END_NAMESPACE
diff --git a/src/render/frontend/qdithering.h b/src/render/frontend/qdithering.h
index bd15ee570..5f41dc3d6 100644
--- a/src/render/frontend/qdithering.h
+++ b/src/render/frontend/qdithering.h
@@ -51,6 +51,7 @@ class QT3DRENDERERSHARED_EXPORT QDithering : public QRenderState
Q_OBJECT
public:
explicit QDithering(QNode *parent = 0);
+ ~QDithering();
private:
Q_DECLARE_PRIVATE(QDithering)
diff --git a/src/render/frontend/qeffect.cpp b/src/render/frontend/qeffect.cpp
index 70590ec58..2dc5a5def 100644
--- a/src/render/frontend/qeffect.cpp
+++ b/src/render/frontend/qeffect.cpp
@@ -59,6 +59,11 @@ QEffect::QEffect(QNode *parent)
{
}
+QEffect::~QEffect()
+{
+ QNode::cleanup();
+}
+
void QEffect::copy(const QNode* ref)
{
QNode::copy(ref);
diff --git a/src/render/frontend/qeffect.h b/src/render/frontend/qeffect.h
index ce91357bd..dd653e516 100644
--- a/src/render/frontend/qeffect.h
+++ b/src/render/frontend/qeffect.h
@@ -54,6 +54,7 @@ class QT3DRENDERERSHARED_EXPORT QEffect
Q_OBJECT
public:
explicit QEffect(QNode *parent = 0);
+ ~QEffect();
void addParameter(QParameter *parameter);
void removeParameter(QParameter *parameter);
diff --git a/src/render/frontend/qfrontface.cpp b/src/render/frontend/qfrontface.cpp
index add4f2bab..b56cce619 100644
--- a/src/render/frontend/qfrontface.cpp
+++ b/src/render/frontend/qfrontface.cpp
@@ -62,6 +62,11 @@ QFrontFace::QFrontFace(QNode *parent)
{
}
+QFrontFace::~QFrontFace()
+{
+ QNode::cleanup();
+}
+
void QFrontFace::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qfrontface.h b/src/render/frontend/qfrontface.h
index b1d6eb904..ad52685c4 100644
--- a/src/render/frontend/qfrontface.h
+++ b/src/render/frontend/qfrontface.h
@@ -60,6 +60,7 @@ public:
Q_ENUM(FaceDir)
explicit QFrontFace(QNode *parent = 0);
+ ~QFrontFace();
FaceDir direction() const;
void setDirection(FaceDir direction);
diff --git a/src/render/frontend/qlayer.cpp b/src/render/frontend/qlayer.cpp
index afef8df3f..979ef4b20 100644
--- a/src/render/frontend/qlayer.cpp
+++ b/src/render/frontend/qlayer.cpp
@@ -86,6 +86,11 @@ QLayer::QLayer(QNode *parent)
{
}
+QLayer::~QLayer()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QLayer::QLayer(QLayerPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/render/frontend/qlayer.h b/src/render/frontend/qlayer.h
index 1ebf6e8e6..7075eb592 100644
--- a/src/render/frontend/qlayer.h
+++ b/src/render/frontend/qlayer.h
@@ -53,6 +53,7 @@ class QT3DRENDERERSHARED_EXPORT QLayer : public QComponent
Q_PROPERTY(QStringList names READ names WRITE setNames NOTIFY namesChanged)
public:
explicit QLayer(QNode *parent = 0);
+ ~QLayer();
QStringList names() const;
void setNames(const QStringList &names);
diff --git a/src/render/frontend/qmaterial.cpp b/src/render/frontend/qmaterial.cpp
index 54efb6709..d54961de3 100644
--- a/src/render/frontend/qmaterial.cpp
+++ b/src/render/frontend/qmaterial.cpp
@@ -89,6 +89,11 @@ QMaterial::QMaterial(QNode *parent)
{
}
+QMaterial::~QMaterial()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QMaterial::QMaterial(QMaterialPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/render/frontend/qmaterial.h b/src/render/frontend/qmaterial.h
index 24206569b..c8cc89ab5 100644
--- a/src/render/frontend/qmaterial.h
+++ b/src/render/frontend/qmaterial.h
@@ -59,6 +59,7 @@ class QT3DRENDERERSHARED_EXPORT QMaterial : public QComponent
public:
explicit QMaterial(QNode *parent = 0);
+ ~QMaterial();
void setEffect(QEffect *effect);
QEffect *effect() const;
diff --git a/src/render/frontend/qmesh.cpp b/src/render/frontend/qmesh.cpp
index 660fd26e5..882fdb2a1 100644
--- a/src/render/frontend/qmesh.cpp
+++ b/src/render/frontend/qmesh.cpp
@@ -82,6 +82,11 @@ QMesh::QMesh(QNode *parent)
{
}
+QMesh::~QMesh()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QMesh::QMesh(QMeshPrivate &dd, QNode *parent)
: QAbstractMesh(dd, parent)
diff --git a/src/render/frontend/qmesh.h b/src/render/frontend/qmesh.h
index 770fda9e0..d087945e8 100644
--- a/src/render/frontend/qmesh.h
+++ b/src/render/frontend/qmesh.h
@@ -61,6 +61,7 @@ class QT3DRENDERERSHARED_EXPORT QMesh : public QAbstractMesh
public:
explicit QMesh(QNode *parent = 0);
+ ~QMesh();
void setSource(const QUrl &source);
QUrl source() const;
diff --git a/src/render/frontend/qparameter.cpp b/src/render/frontend/qparameter.cpp
index 92cb0d4d8..95d35d5c2 100644
--- a/src/render/frontend/qparameter.cpp
+++ b/src/render/frontend/qparameter.cpp
@@ -78,6 +78,11 @@ QParameter::QParameter(QNode *parent)
{
}
+QParameter::~QParameter()
+{
+ QNode::cleanup();
+}
+
QParameter::QParameter(const QString &name, const QVariant &value, QNode *parent)
: QNode(*new QParameterPrivate, parent)
{
diff --git a/src/render/frontend/qparameter.h b/src/render/frontend/qparameter.h
index 01268e15b..043b71414 100644
--- a/src/render/frontend/qparameter.h
+++ b/src/render/frontend/qparameter.h
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QParameter : public QNode
public:
explicit QParameter(QNode *parent = 0);
+ ~QParameter();
QParameter(const QString& name, const QVariant& value, QNode* parent = 0);
QParameter(const QString &name, QAbstractTextureProvider *texture, QNode *parent = 0);
diff --git a/src/render/frontend/qparametermapping.cpp b/src/render/frontend/qparametermapping.cpp
index e2b266f8d..c09a384a9 100644
--- a/src/render/frontend/qparametermapping.cpp
+++ b/src/render/frontend/qparametermapping.cpp
@@ -115,6 +115,11 @@ QParameterMapping::QParameterMapping(const QString &parameterName, const QString
d->m_bindingType = bindingType;
}
+QParameterMapping::~QParameterMapping()
+{
+ QNode::cleanup();
+}
+
/*!
\property Qt3D::QParameterMapping::parameterName
diff --git a/src/render/frontend/qparametermapping.h b/src/render/frontend/qparametermapping.h
index 024b5796a..25fcfc809 100644
--- a/src/render/frontend/qparametermapping.h
+++ b/src/render/frontend/qparametermapping.h
@@ -64,6 +64,7 @@ public:
explicit QParameterMapping(QNode *parent = 0);
QParameterMapping(const QString &parameterName, const QString &shaderParameterName, QParameterMapping::Binding bindingType, QNode *parent = 0);
+ ~QParameterMapping();
void setParameterName(const QString &name);
void setShaderVariableName(const QString &name);
diff --git a/src/render/frontend/qplanemesh.cpp b/src/render/frontend/qplanemesh.cpp
index 6aca02247..1bb06d79d 100644
--- a/src/render/frontend/qplanemesh.cpp
+++ b/src/render/frontend/qplanemesh.cpp
@@ -66,6 +66,11 @@ QPlaneMesh::QPlaneMesh(QNode *parent)
update();
}
+QPlaneMesh::~QPlaneMesh()
+{
+ QNode::cleanup();
+}
+
void QPlaneMesh::copy(const QNode *ref)
{
QAbstractMesh::copy(ref);
diff --git a/src/render/frontend/qplanemesh.h b/src/render/frontend/qplanemesh.h
index 47a3c79bf..c2346a1de 100644
--- a/src/render/frontend/qplanemesh.h
+++ b/src/render/frontend/qplanemesh.h
@@ -47,7 +47,7 @@ namespace Qt3D {
class QPlaneMeshPrivate;
-class QT3DRENDERERSHARED_EXPORT QPlaneMesh : public Qt3D::QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QPlaneMesh : public QAbstractMesh
{
Q_OBJECT
@@ -57,6 +57,7 @@ class QT3DRENDERERSHARED_EXPORT QPlaneMesh : public Qt3D::QAbstractMesh
public:
explicit QPlaneMesh(QNode *parent = 0);
+ ~QPlaneMesh();
void setWidth(float width);
float width() const;
diff --git a/src/render/frontend/qpolygonoffset.cpp b/src/render/frontend/qpolygonoffset.cpp
index 192e1ef02..d252d4893 100644
--- a/src/render/frontend/qpolygonoffset.cpp
+++ b/src/render/frontend/qpolygonoffset.cpp
@@ -62,6 +62,11 @@ QPolygonOffset::QPolygonOffset(QNode *parent)
{
}
+QPolygonOffset::~QPolygonOffset()
+{
+ QNode::cleanup();
+}
+
float QPolygonOffset::factor() const
{
Q_D(const QPolygonOffset);
diff --git a/src/render/frontend/qpolygonoffset.h b/src/render/frontend/qpolygonoffset.h
index 446febf4f..339437ae1 100644
--- a/src/render/frontend/qpolygonoffset.h
+++ b/src/render/frontend/qpolygonoffset.h
@@ -53,6 +53,7 @@ class QT3DRENDERERSHARED_EXPORT QPolygonOffset : public QRenderState
Q_PROPERTY(float units READ units WRITE setUnits NOTIFY unitsChanged)
public:
explicit QPolygonOffset(QNode *parent = Q_NULLPTR);
+ ~QPolygonOffset();
float factor() const;
void setFactor(float factor);
diff --git a/src/render/frontend/qrenderattachment.cpp b/src/render/frontend/qrenderattachment.cpp
index 8e3fd30af..35db47cc7 100644
--- a/src/render/frontend/qrenderattachment.cpp
+++ b/src/render/frontend/qrenderattachment.cpp
@@ -69,6 +69,11 @@ QRenderAttachment::QRenderAttachment(QNode *parent)
{
}
+QRenderAttachment::~QRenderAttachment()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QRenderAttachment::QRenderAttachment(QRenderAttachmentPrivate &dd, QNode *parent)
: QNode(dd, parent)
diff --git a/src/render/frontend/qrenderattachment.h b/src/render/frontend/qrenderattachment.h
index 5cdd8113b..15706fb1d 100644
--- a/src/render/frontend/qrenderattachment.h
+++ b/src/render/frontend/qrenderattachment.h
@@ -92,6 +92,7 @@ public:
Q_ENUM(CubeMapFace)
explicit QRenderAttachment(QNode *parent = 0);
+ ~QRenderAttachment();
void setType(RenderAttachmentType type);
RenderAttachmentType type() const;
diff --git a/src/render/frontend/qrenderpass.cpp b/src/render/frontend/qrenderpass.cpp
index b6b16dbd6..f6feba36a 100644
--- a/src/render/frontend/qrenderpass.cpp
+++ b/src/render/frontend/qrenderpass.cpp
@@ -77,6 +77,11 @@ QRenderPass::QRenderPass(QNode *parent)
{
}
+QRenderPass::~QRenderPass()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QRenderPass::QRenderPass(QRenderPassPrivate &dd, QNode *parent)
: QNode(dd, parent)
diff --git a/src/render/frontend/qrenderpass.h b/src/render/frontend/qrenderpass.h
index 1f401860d..d921829ac 100644
--- a/src/render/frontend/qrenderpass.h
+++ b/src/render/frontend/qrenderpass.h
@@ -65,6 +65,7 @@ class QT3DRENDERERSHARED_EXPORT QRenderPass : public QNode
public:
explicit QRenderPass(QNode *parent = 0);
+ ~QRenderPass();
QString glslNameForParameter(QString paramName) const;
diff --git a/src/render/frontend/qrenderstate.cpp b/src/render/frontend/qrenderstate.cpp
index 1b13b5d03..a572b5e06 100644
--- a/src/render/frontend/qrenderstate.cpp
+++ b/src/render/frontend/qrenderstate.cpp
@@ -52,6 +52,11 @@ QRenderStatePrivate::QRenderStatePrivate(QRenderState::Type type)
{
}
+QRenderState::~QRenderState()
+{
+ Q_ASSERT_X(QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3D::QRenderState subclass didn't call QNode::cleanup in its destructor");
+}
+
QRenderState::Type QRenderState::type() const
{
Q_D(const QRenderState);
diff --git a/src/render/frontend/qrenderstate.h b/src/render/frontend/qrenderstate.h
index 7f428b426..90290f8dc 100644
--- a/src/render/frontend/qrenderstate.h
+++ b/src/render/frontend/qrenderstate.h
@@ -70,10 +70,12 @@ public:
};
Q_ENUM(Type)
+ ~QRenderState();
+
Type type() const;
protected:
- QRenderState(QRenderStatePrivate &dd, QNode *parent = 0);
+ QRenderState(QRenderStatePrivate &dd, QNode *parent = Q_NULLPTR);
private:
Q_DECLARE_PRIVATE(QRenderState)
diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp
index 532a803c8..d6297d7de 100644
--- a/src/render/frontend/qrendertarget.cpp
+++ b/src/render/frontend/qrendertarget.cpp
@@ -65,6 +65,11 @@ QRenderTarget::QRenderTarget(QNode *parent)
{
}
+QRenderTarget::~QRenderTarget()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QRenderTarget::QRenderTarget(QRenderTargetPrivate &dd, QNode *parent)
: QComponent(dd, parent)
diff --git a/src/render/frontend/qrendertarget.h b/src/render/frontend/qrendertarget.h
index 169f7c882..8b2860bca 100644
--- a/src/render/frontend/qrendertarget.h
+++ b/src/render/frontend/qrendertarget.h
@@ -52,6 +52,7 @@ class QT3DRENDERERSHARED_EXPORT QRenderTarget : public QComponent
Q_OBJECT
public:
explicit QRenderTarget(QNode *parent = 0);
+ ~QRenderTarget();
void addAttachment(QRenderAttachment *attachment);
void removeAttachment(QRenderAttachment *attachment);
diff --git a/src/render/frontend/qsceneloader.cpp b/src/render/frontend/qsceneloader.cpp
index a5662a694..cc0a25afa 100644
--- a/src/render/frontend/qsceneloader.cpp
+++ b/src/render/frontend/qsceneloader.cpp
@@ -51,6 +51,11 @@ QSceneLoader::QSceneLoader(QNode *parent)
{
}
+QSceneLoader::~QSceneLoader()
+{
+ QNode::cleanup();
+}
+
// Called in main thread
void QSceneLoader::sceneChangeEvent(const QSceneChangePtr &change)
{
diff --git a/src/render/frontend/qsceneloader.h b/src/render/frontend/qsceneloader.h
index 2c3914811..8c0092beb 100644
--- a/src/render/frontend/qsceneloader.h
+++ b/src/render/frontend/qsceneloader.h
@@ -48,6 +48,7 @@ class QT3DRENDERERSHARED_EXPORT QSceneLoader : public Render::QAbstractSceneLoad
Q_OBJECT
public:
explicit QSceneLoader(QNode *parent = 0);
+ ~QSceneLoader();
void sceneChangeEvent(const QSceneChangePtr &change) Q_DECL_OVERRIDE;
protected:
diff --git a/src/render/frontend/qscissortest.cpp b/src/render/frontend/qscissortest.cpp
index 5c8922d5f..79ddd61bd 100644
--- a/src/render/frontend/qscissortest.cpp
+++ b/src/render/frontend/qscissortest.cpp
@@ -69,6 +69,11 @@ QScissorTest::QScissorTest(QNode *parent)
{
}
+QScissorTest::~QScissorTest()
+{
+ QNode::cleanup();
+}
+
void QScissorTest::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qscissortest.h b/src/render/frontend/qscissortest.h
index 136d06807..aae531cd3 100644
--- a/src/render/frontend/qscissortest.h
+++ b/src/render/frontend/qscissortest.h
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QScissorTest : public QRenderState
public:
explicit QScissorTest(QNode *parent = 0);
+ ~QScissorTest();
int left() const;
void setLeft(int left);
diff --git a/src/render/frontend/qshaderdata.cpp b/src/render/frontend/qshaderdata.cpp
index 6caf7e5b1..3ce956750 100644
--- a/src/render/frontend/qshaderdata.cpp
+++ b/src/render/frontend/qshaderdata.cpp
@@ -79,6 +79,11 @@ QShaderData::QShaderData(QNode *parent)
{
}
+QShaderData::~QShaderData()
+{
+ QNode::cleanup();
+}
+
PropertyReaderInterfacePtr QShaderData::propertyReader() const
{
Q_D(const QShaderData);
diff --git a/src/render/frontend/qshaderdata.h b/src/render/frontend/qshaderdata.h
index f526dcfc1..7c595f415 100644
--- a/src/render/frontend/qshaderdata.h
+++ b/src/render/frontend/qshaderdata.h
@@ -60,6 +60,7 @@ class QT3DRENDERERSHARED_EXPORT QShaderData : public QComponent
Q_OBJECT
public:
explicit QShaderData(QNode *parent = 0);
+ ~QShaderData();
enum TransformType {
ModelToEye = 0,
diff --git a/src/render/frontend/qshaderprogram.cpp b/src/render/frontend/qshaderprogram.cpp
index 7eb170b6b..5787825b8 100644
--- a/src/render/frontend/qshaderprogram.cpp
+++ b/src/render/frontend/qshaderprogram.cpp
@@ -73,6 +73,11 @@ QShaderProgram::QShaderProgram(QNode *parent)
{
}
+QShaderProgram::~QShaderProgram()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QShaderProgram::QShaderProgram(QShaderProgramPrivate &dd, QNode *parent)
: QNode(dd, parent)
diff --git a/src/render/frontend/qshaderprogram.h b/src/render/frontend/qshaderprogram.h
index 4023980a8..f2ca7bf74 100644
--- a/src/render/frontend/qshaderprogram.h
+++ b/src/render/frontend/qshaderprogram.h
@@ -58,6 +58,7 @@ class QT3DRENDERERSHARED_EXPORT QShaderProgram : public QNode
public:
explicit QShaderProgram(QNode *parent = 0);
+ ~QShaderProgram();
enum ShaderType {
Vertex = 0,
diff --git a/src/render/frontend/qspheremesh.cpp b/src/render/frontend/qspheremesh.cpp
index 7e103e8fe..0c6fdbaa3 100644
--- a/src/render/frontend/qspheremesh.cpp
+++ b/src/render/frontend/qspheremesh.cpp
@@ -89,6 +89,11 @@ QSphereMesh::QSphereMesh(QNode *parent)
update();
}
+QSphereMesh::~QSphereMesh()
+{
+ QNode::cleanup();
+}
+
void QSphereMesh::copy(const QNode *ref)
{
QAbstractMesh::copy(ref);
diff --git a/src/render/frontend/qspheremesh.h b/src/render/frontend/qspheremesh.h
index 567b1ed49..317a8fe8c 100644
--- a/src/render/frontend/qspheremesh.h
+++ b/src/render/frontend/qspheremesh.h
@@ -46,7 +46,7 @@ namespace Qt3D {
class QSphereMeshPrivate;
-class QT3DRENDERERSHARED_EXPORT QSphereMesh : public Qt3D::QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QSphereMesh : public QAbstractMesh
{
Q_OBJECT
Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged)
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QSphereMesh : public Qt3D::QAbstractMesh
public:
explicit QSphereMesh(QNode *parent = 0);
+ ~QSphereMesh();
void setRings(int rings);
void setSlices(int slices);
diff --git a/src/render/frontend/qstenciltest.cpp b/src/render/frontend/qstenciltest.cpp
index 2ff78625d..66b24dfed 100644
--- a/src/render/frontend/qstenciltest.cpp
+++ b/src/render/frontend/qstenciltest.cpp
@@ -67,6 +67,11 @@ QStencilTest::QStencilTest(QNode *parent)
{
}
+QStencilTest::~QStencilTest()
+{
+ QNode::cleanup();
+}
+
void QStencilTest::copy(const QNode *ref)
{
QRenderState::copy(ref);
diff --git a/src/render/frontend/qstenciltest.h b/src/render/frontend/qstenciltest.h
index fdc61037b..d05675a15 100644
--- a/src/render/frontend/qstenciltest.h
+++ b/src/render/frontend/qstenciltest.h
@@ -76,6 +76,7 @@ public:
Q_ENUM(StencilFunc)
explicit QStencilTest(QNode *parent = 0);
+ ~QStencilTest();
uint mask() const;
void setMask(uint mask);
diff --git a/src/render/frontend/qtechnique.cpp b/src/render/frontend/qtechnique.cpp
index dd72ec458..01699715e 100644
--- a/src/render/frontend/qtechnique.cpp
+++ b/src/render/frontend/qtechnique.cpp
@@ -65,6 +65,11 @@ QTechnique::QTechnique(QNode *parent)
QObject::connect(&d->m_openGLFilter, SIGNAL(openGLFilterChanged()), this, SLOT(_q_openGLFilterChanged()));
}
+QTechnique::~QTechnique()
+{
+ QNode::cleanup();
+}
+
/*! \internal */
QTechnique::QTechnique(QTechniquePrivate &dd, QNode *parent)
: QNode(dd, parent)
diff --git a/src/render/frontend/qtechnique.h b/src/render/frontend/qtechnique.h
index 199a7d57a..fd3225d62 100644
--- a/src/render/frontend/qtechnique.h
+++ b/src/render/frontend/qtechnique.h
@@ -59,6 +59,7 @@ class QT3DRENDERERSHARED_EXPORT QTechnique : public QNode
public:
explicit QTechnique(QNode *parent = 0);
+ ~QTechnique();
void addAnnotation(QAnnotation *criterion);
void removeAnnotation(QAnnotation *criterion);
diff --git a/src/render/frontend/qtextureimage.cpp b/src/render/frontend/qtextureimage.cpp
index e3ada359a..294f36a92 100644
--- a/src/render/frontend/qtextureimage.cpp
+++ b/src/render/frontend/qtextureimage.cpp
@@ -125,6 +125,7 @@ QTextureImage::QTextureImage(QNode *parent)
*/
QTextureImage::~QTextureImage()
{
+ QNode::cleanup();
}
/*!
diff --git a/src/render/frontend/qtextureproviders.cpp b/src/render/frontend/qtextureproviders.cpp
index eabcc2cf7..2852f5c32 100644
--- a/src/render/frontend/qtextureproviders.cpp
+++ b/src/render/frontend/qtextureproviders.cpp
@@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
/*!
- \class QT3D::QTexture1D
+ \class Qt3D::QTexture1D
\since 5.5
\brief A QAbstractTextureProvider with a Target1D target format.
*/
@@ -59,7 +59,7 @@ QTexture1D::~QTexture1D()
}
/*!
- \class QT3D::QTexture1DArray
+ \class Qt3D::QTexture1DArray
\since 5.5
\brief A QAbstractTextureProvider with a Target1DArray target format.
*/
@@ -77,7 +77,7 @@ QTexture1DArray::~QTexture1DArray()
}
/*!
- \class QT3D::QTexture2D
+ \class Qt3D::QTexture2D
\since 5.5
\brief A QAbstractTextureProvider with a Target2D target format.
*/
@@ -95,7 +95,7 @@ QTexture2D::~QTexture2D()
}
/*!
- \class QT3D::QTexture2DArray
+ \class Qt3D::QTexture2DArray
\since 5.5
\brief A QAbstractTextureProvider with a Target2DArray target format.
*/
@@ -114,7 +114,7 @@ QTexture2DArray::~QTexture2DArray()
/*!
- \class QT3D::QTexture3D
+ \class Qt3D::QTexture3D
\since 5.5
\brief A QAbstractTextureProvider with a Target3D target format.
*/
@@ -132,7 +132,7 @@ QTexture3D::~QTexture3D()
}
/*!
- \class QT3D::QTextureCubeMap
+ \class Qt3D::QTextureCubeMap
\since 5.5
\brief A QAbstractTextureProvider with a TargetCubeMap target format.
*/
@@ -150,7 +150,7 @@ QTextureCubeMap::~QTextureCubeMap()
}
/*!
- \class QT3D::QTextureCubeMapArray
+ \class Qt3D::QTextureCubeMapArray
\since 5.5
\brief A QAbstractTextureProvider with a TargetCubeMapArray target format.
*/
@@ -165,10 +165,11 @@ QTextureCubeMapArray::QTextureCubeMapArray(QNode *parent)
QTextureCubeMapArray::~QTextureCubeMapArray()
{
+ QNode::cleanup();
}
/*!
- \class QT3D::QTexture2DMultisample
+ \class Qt3D::QTexture2DMultisample
\since 5.5
\brief A QAbstractTextureProvider with a Target2DMultisample target format.
*/
@@ -186,7 +187,7 @@ QTexture2DMultisample::~QTexture2DMultisample()
}
/*!
- \class QT3D::QTexture2DMultisampleArray
+ \class Qt3D::QTexture2DMultisampleArray
\since 5.5
\brief A QAbstractTextureProvider with a Target2DMultisampleArray target format.
*/
@@ -204,7 +205,7 @@ QTexture2DMultisampleArray::~QTexture2DMultisampleArray()
}
/*!
- \class QT3D::QTextureRectangle
+ \class Qt3D::QTextureRectangle
\since 5.5
\brief A QAbstractTextureProvider with a TargetRectangle target format.
*/
@@ -222,7 +223,7 @@ QTextureRectangle::~QTextureRectangle()
}
/*!
- \class QT3D::QTextureBuffer
+ \class Qt3D::QTextureBuffer
\since 5.5
\brief A QAbstractTextureProvider with a TargetBuffer target format.
*/
diff --git a/src/render/frontend/qtorusmesh.cpp b/src/render/frontend/qtorusmesh.cpp
index 4a975d8d8..d4f3e3ba0 100644
--- a/src/render/frontend/qtorusmesh.cpp
+++ b/src/render/frontend/qtorusmesh.cpp
@@ -98,6 +98,12 @@ QTorusMesh::QTorusMesh(QNode *parent)
{
update();
}
+
+QTorusMesh::~QTorusMesh()
+{
+ QNode::cleanup();
+}
+
void QTorusMesh::setRings(int rings)
{
Q_D(QTorusMesh);
diff --git a/src/render/frontend/qtorusmesh.h b/src/render/frontend/qtorusmesh.h
index 0e0edacd9..a434008b5 100644
--- a/src/render/frontend/qtorusmesh.h
+++ b/src/render/frontend/qtorusmesh.h
@@ -47,7 +47,7 @@ namespace Qt3D {
class QTorusMeshPrivate;
-class QT3DRENDERERSHARED_EXPORT QTorusMesh : public Qt3D::QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QTorusMesh : public QAbstractMesh
{
Q_OBJECT
Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged)
@@ -56,6 +56,7 @@ class QT3DRENDERERSHARED_EXPORT QTorusMesh : public Qt3D::QAbstractMesh
Q_PROPERTY(float minorRadius READ minorRadius WRITE setMinorRadius NOTIFY minorRadiusChanged)
public:
explicit QTorusMesh(QNode *parent = 0);
+ ~QTorusMesh();
void setRings(int rings);
void setSlices(int slices);
diff --git a/src/render/frontend/qwrapmode.h b/src/render/frontend/qwrapmode.h
index d0333c749..faec41cae 100644
--- a/src/render/frontend/qwrapmode.h
+++ b/src/render/frontend/qwrapmode.h
@@ -46,7 +46,7 @@ namespace Qt3D {
class QTextureWrapModePrivate;
-class QT3DRENDERERSHARED_EXPORT QTextureWrapMode: public QObject
+class QT3DRENDERERSHARED_EXPORT QTextureWrapMode : public QObject
{
Q_OBJECT
Q_PROPERTY(WrapMode x READ x WRITE setX NOTIFY xChanged)
diff --git a/tests/auto/core/cloning/tst_cloning.cpp b/tests/auto/core/cloning/tst_cloning.cpp
index ad608730d..96e98f334 100644
--- a/tests/auto/core/cloning/tst_cloning.cpp
+++ b/tests/auto/core/cloning/tst_cloning.cpp
@@ -58,6 +58,11 @@ public:
explicit MyQNode(Qt3D::QNode *parent = 0) : QNode(parent)
{}
+ ~MyQNode()
+ {
+ QNode::cleanup();
+ }
+
void setCustomProperty(const QString &s) { m_customProperty = s; }
QString customProperty() const { return m_customProperty; }
@@ -85,17 +90,24 @@ public:
explicit MyQComponent(Qt3D::QNode *parent = 0) : QComponent(parent)
{}
+ ~MyQComponent()
+ {
+ QNode::cleanup();
+ }
+
QT3D_CLONEABLE(MyQComponent)
};
void tst_Cloning::checkEntityCloning()
{
+ // GIVEN
Qt3D::QScene *scene = new Qt3D::QScene();
MyQNode *root = new MyQNode();
Qt3D::QNodePrivate::get(root)->setScene(scene);
Qt3D::QEntity *entity = new Qt3D::QEntity(root);
+ // WHEN
MyQComponent *comp1 = new MyQComponent();
MyQComponent *comp2 = new MyQComponent();
MyQComponent *comp3 = new MyQComponent();
@@ -107,14 +119,16 @@ void tst_Cloning::checkEntityCloning()
root->setCustomProperty(QStringLiteral("Corvette"));
- // VERIFY Initial state
+ // THEN
QVERIFY(root->customProperty() == QStringLiteral("Corvette"));
QCOMPARE(root->children().count(), 1);
QCOMPARE(entity->children().count(), 4);
QCOMPARE(entity->components().count(), 3);
+ //WHEN
MyQNode *cloneRoot = qobject_cast<MyQNode *>(MyQNode::clone(root));
+ // THEN
QCOMPARE(cloneRoot->children().count(), 1);
QCOMPARE(cloneRoot->id(), root->id());
QVERIFY(cloneRoot->customProperty() == root->customProperty());
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 02268552c..05af6b615 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -55,14 +55,31 @@ private slots:
void defaultNodeConstruction();
void defaultComponentConstruction();
void defaultEntityConstrution();
- void appendChildNodesToNode();
- void removingChildNodesFromNode();
+
+ void appendSingleChildNodeToNodeNoSceneExplicitParenting();
+ void appendSingleChildNodeToNodeNoSceneImplicitParenting();
+ void appendMultipleChildNodesToNodeNoScene();
+
+ void appendSingleChildNodeToNodeSceneExplicitParenting();
+ void appendSingleChildNodeToNodeSceneImplicitParenting();
+ void appendMultipleChildNodesToNodeScene();
+
+ void checkParentChangeToNull();
+ void checkParentChangeToOtherParent();
+
+ void removingSingleChildNodeFromNode();
+ void removingMultipleChildNodesFromNode();
+
void appendingChildEntitiesToNode();
void removingChildEntitiesFromNode();
- void appendingComponentsToEntity();
- void removingComponentsFromEntity();
+
+ void appendingComponentToEntity();
+ void appendingParentlessComponentToEntity();
+ void removingComponentFromEntity();
+
void changeCustomProperty();
void checkDestruction();
+ void verifyCopy();
};
class ObserverSpy : public Qt3D::QLockableObserverInterface
@@ -82,10 +99,16 @@ public:
ObserverSpy(Qt3D::QNode *node)
: Qt3D::QLockableObserverInterface()
+ , m_node(node)
{
Qt3D::QNodePrivate::get(node)->setArbiter(this);
}
+ ~ObserverSpy()
+ {
+ Qt3D::QNodePrivate::get(m_node)->setArbiter(Q_NULLPTR);
+ }
+
void sceneChangeEventWithLock(const Qt3D::QSceneChangePtr &e) Q_DECL_OVERRIDE
{
events << ChangeRecord(e, true);
@@ -97,6 +120,7 @@ public:
}
QList<ChangeRecord> events;
+ Qt3D::QNode *m_node;
};
class MyQNode : public Qt3D::QNode
@@ -104,9 +128,17 @@ class MyQNode : public Qt3D::QNode
Q_OBJECT
Q_PROPERTY(QString customProperty READ customProperty WRITE setCustomProperty NOTIFY customPropertyChanged)
public:
- explicit MyQNode(Qt3D::QNode *parent = 0) : QNode(parent)
+ explicit MyQNode(Qt3D::QNode *parent = 0)
+ : QNode(parent)
+ , m_scene(Q_NULLPTR)
{}
+ ~MyQNode()
+ {
+ QNode::cleanup();
+ delete m_scene;
+ }
+
void setCustomProperty(const QString &s)
{
if (m_customProperty == s)
@@ -121,6 +153,18 @@ public:
return m_customProperty;
}
+ void assignScene()
+ {
+ if (!m_scene)
+ m_scene = new Qt3D::QScene();
+ Qt3D::QNodePrivate::get(this)->setScene(m_scene);
+ }
+
+ void makeCopyOf(QNode *other)
+ {
+ QNode::copy(other);
+ }
+
signals:
void customPropertyChanged();
@@ -128,7 +172,7 @@ protected:
QT3D_CLONEABLE(MyQNode)
QString m_customProperty;
-
+ Qt3D::QScene *m_scene;
};
class MyQComponent : public Qt3D::QComponent
@@ -138,6 +182,11 @@ public:
explicit MyQComponent(Qt3D::QNode *parent = 0) : QComponent(parent)
{}
+ ~MyQComponent()
+ {
+ QNode::cleanup();
+ }
+
// QNode interface
protected:
QT3D_CLONEABLE(MyQComponent)
@@ -185,204 +234,396 @@ void tst_Nodes::defaultEntityConstrution()
QCOMPARE(entity2->parent(), entity.data());
}
-void tst_Nodes::appendChildNodesToNode()
+void tst_Nodes::appendSingleChildNodeToNodeNoSceneExplicitParenting()
{
+ // Check nodes added when no scene is set
// GIVEN
- MyQNode *node = new MyQNode();
- ObserverSpy spy(node);
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
+ // THEN
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() == Q_NULLPTR);
// WHEN
- for (int i = 0; i < 10; ++i) {
- // GIVEN
- MyQNode *child = new MyQNode();
- // THEN
- QVERIFY(child->parent() == Q_NULLPTR);
+ QScopedPointer<MyQNode> child(new MyQNode());
- // WHEN
- child->setParent(node);
- // THEN
- QVERIFY(child->parent() == node);
- QVERIFY(child->parentNode() == node);
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::NodeCreated);
- QCOMPARE(event->propertyName(), "node");
- Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), child->id());
- QCOMPARE(clone->parentNode()->id(), node->id());
- }
// THEN
- QVERIFY(node->children().count() == 10);
+ QVERIFY(child->parent() == Q_NULLPTR);
// WHEN
- for (int i = 0; i < 10; ++i) {
- // GIVEN
- MyQNode *child = new MyQNode();
- // WHEN
- child->setParent(node);
- // THEN
- QVERIFY(child->parent() == node);
- QVERIFY(child->parentNode() == node);
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::NodeCreated);
- QCOMPARE(event->propertyName(), "node");
- Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), child->id());
- QCOMPARE(clone->parentNode()->id(), node->id());
- }
+ child->setParent(node.data());
+
+ // THEN
+ QVERIFY(child->parent() == node.data());
+ QVERIFY(child->parentNode() == node.data());
+ QCOMPARE(node->children().count(), 1);
+
+ // Events are only sent when a scene is set on the root node
+ QCOMPARE(spy.events.size(), 0);
+}
+
+void tst_Nodes::appendSingleChildNodeToNodeNoSceneImplicitParenting()
+{
+ // Check nodes added when no scene is set
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
+
// THEN
- QVERIFY(node->children().count() == 20);
- Qt3D::QNode *child = qobject_cast<Qt3D::QNode *>(node->children().first());
- QScopedPointer<ObserverSpy> childSpy(new ObserverSpy(child));
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() == Q_NULLPTR);
+ // WHEN
+ QScopedPointer<MyQNode> child(new MyQNode(node.data()));
+
+ // THEN
+ QVERIFY(child->parent() == node.data());
+ QVERIFY(child->parentNode() == node.data());
+ QCOMPARE(node->children().count(), 1);
+
+ // Events are only sent when a scene is set on the root node
+ QCOMPARE(spy.events.size(), 0);
+}
+
+void tst_Nodes::appendMultipleChildNodesToNodeNoScene()
+{
+ // Check multiple nodes added with no scene set
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
+
+ // THEN
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() == Q_NULLPTR);
// WHEN
- Qt3D::QNode *parent = node;
for (int i = 0; i < 10; i++) {
- // THEN
- QVERIFY(child->parent() == parent);
- QVERIFY(child->parentNode() == parent);
// WHEN
- (void) new MyQNode(child);
- parent = child;
- child = qobject_cast<Qt3D::QNode *>(child->children().first());
+ Qt3D::QNode *child = Q_NULLPTR;
+ if (i % 2 == 0) {
+ child = new MyQNode(node.data());
+ } else {
+ child = new MyQNode();
+ child->setParent(node.data());
+ }
// THEN
- QVERIFY(childSpy->events.isEmpty());
- childSpy.reset(new ObserverSpy(child));
+ QVERIFY(child->parent() == node.data());
}
+
+ // THEN
+ QCOMPARE(node->children().count(), 10);
+
+ // Events are only sent when a scene is set on the root node
+ QCOMPARE(spy.events.size(), 0);
+}
+
+void tst_Nodes::appendSingleChildNodeToNodeSceneExplicitParenting()
+{
+ // Check nodes added when scene is set
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
+ // WHEN
+ node->assignScene();
+ // THEN
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() != Q_NULLPTR);
+
+ // WHEN
+ QScopedPointer<MyQNode> child(new MyQNode());
+
+ // THEN
+ QVERIFY(child->parent() == Q_NULLPTR);
+
+ // WHEN
+ child->setParent(node.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(child->parent() == node.data());
+ QVERIFY(child->parentNode() == node.data());
+ QCOMPARE(spy.events.size(), 1);
+ QVERIFY(spy.events.first().wasLocked());
+ QCOMPARE(node->children().count(), 1);
+
+ Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeCreated);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QCOMPARE(clone->parentNode()->id(), node->id());
+}
+
+void tst_Nodes::appendSingleChildNodeToNodeSceneImplicitParenting()
+{
+ // Check nodes added when scene is set
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
+ // WHEN
+ node->assignScene();
// THEN
- QVERIFY(node->children().count() == 20);
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() != Q_NULLPTR);
+
+ // WHEN
+ QScopedPointer<MyQNode> child(new MyQNode(node.data()));
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(child->parent() == node.data());
+ QVERIFY(child->parentNode() == node.data());
+ QVERIFY(Qt3D::QNodePrivate::get(child.data())->scene() != Q_NULLPTR);
+
+ QCOMPARE(spy.events.size(), 1);
+ QVERIFY(spy.events.first().wasLocked());
+ QCOMPARE(node->children().count(), 1);
+
+ Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeCreated);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QCOMPARE(clone->parentNode()->id(), node->id());
+}
+
+void tst_Nodes::appendMultipleChildNodesToNodeScene()
+{
+ // Check nodes added when scene is set
+
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ // WHEN
+ node->assignScene();
+ ObserverSpy spy(node.data());
+ // THEN
+ QVERIFY(Qt3D::QNodePrivate::get(node.data())->scene() != Q_NULLPTR);
// WHEN
- child = qobject_cast<Qt3D::QNode *>(node->children().first());
- parent = node;
for (int i = 0; i < 10; i++) {
- // THEN
- QVERIFY(child->parent() == parent);
- QVERIFY(child->parentNode() == parent);
- QVERIFY(child->children().count() == 1);
// WHEN
- parent = child;
- child = qobject_cast<Qt3D::QNode *>(child->children().first());
+ Qt3D::QNode *child = Q_NULLPTR;
+ if (i % 2 == 0) {
+ child = new MyQNode(node.data());
+ QCoreApplication::processEvents();
+ QCOMPARE(spy.events.size(), i + 1);
+ } else {
+ child = new MyQNode();
+ child->setParent(node.data());
+ }
+ // THEN
+ QVERIFY(child->parent() == node.data());
+ QVERIFY(Qt3D::QNodePrivate::get(child)->scene() != Q_NULLPTR);
}
// THEN
- QVERIFY(child->children().count() == 0);
+ QCOMPARE(node->children().count(), 10);
+
+ // THEN
+ QCOMPARE(spy.events.size(), 10);
+ Q_FOREACH (const ObserverSpy::ChangeRecord &r, spy.events) {
+
+ QVERIFY(r.wasLocked());
+ Qt3D::QScenePropertyChangePtr event = r.change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeCreated);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+
+ bool found = false;
+ Q_FOREACH (QObject *c, node->children()) {
+ if (clone->id() == qobject_cast<Qt3D::QNode *>(c)->id()) {
+ found = true;
+ QCOMPARE(clone->parentNode()->id(), node->id());
+ break;
+ }
+ }
+ QVERIFY(found);
+ }
}
-void tst_Nodes::removingChildNodesFromNode()
+void tst_Nodes::checkParentChangeToNull()
{
// GIVEN
- MyQNode *root = new MyQNode();
- Qt3D::QNode *child = new MyQNode();
+ QScopedPointer<MyQNode> root(new MyQNode());
+ ObserverSpy spy(root.data());
// WHEN
- child->setParent(root);
+ root->assignScene();
+ QScopedPointer<Qt3D::QNode> child(new MyQNode(root.data()));
+ QCoreApplication::processEvents();
+
// THEN
- QVERIFY(root->children().count() == 1);
+ QVERIFY(child->parent() == root.data());
+ QCOMPARE(spy.events.size(), 1);
+ QCOMPARE(root->children().size(), 1);
// WHEN
- child->setParent(Q_NULLPTR);
+ spy.events.clear();
+ child->setParent(Q_NODE_NULLPTR);
+
// THEN
- QVERIFY(root->children().count() == 0);
QVERIFY(child->parent() == Q_NULLPTR);
+ QCOMPARE(root->children().size(), 0);
+ QCOMPARE(spy.events.size(), 1);
+ QVERIFY(spy.events.first().wasLocked());
+ Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeAboutToBeDeleted);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QVERIFY(!clone->parentNode());
+}
+
+void tst_Nodes::checkParentChangeToOtherParent()
+{
// GIVEN
- for (int i = 0; i < 10; i++) {
- // WHEN
- (void) new MyQNode(root);
- }
+ QScopedPointer<MyQNode> root(new MyQNode());
+ root->assignScene();
+ ObserverSpy spy(root.data());
+ QScopedPointer<MyQNode> parent1(new MyQNode(root.data()));
+ QScopedPointer<MyQNode> parent2(new MyQNode(root.data()));
+ QCoreApplication::processEvents();
// THEN
- QVERIFY(root->children().count() == 10);
+ QCOMPARE(spy.events.size(), 2);
// WHEN
- Q_FOREACH (QObject *c, root->children())
- c->setParent(Q_NULLPTR);
+ ObserverSpy spyParent1(parent1.data());
+ ObserverSpy spyParent2(parent2.data());
+ QScopedPointer<Qt3D::QNode> child(new MyQNode(parent1.data()));
+ QCoreApplication::processEvents();
// THEN
- QVERIFY(root->children().count() == 0);
+ QVERIFY(child->parent() == parent1.data());
+ QCOMPARE(parent1->children().size(), 1);
+ QCOMPARE(parent2->children().size(), 0);
+ QVERIFY(Qt3D::QNodePrivate::get(child.data())->scene() != Q_NULLPTR);
+ QCOMPARE(spyParent1.events.size(), 1);
- // GIVEN
- Qt3D::QNode *firstChild = child;
- for (int i = 0; i < 10; i++) {
- // WHEN
- (void) new MyQNode(child);
- child = qobject_cast<Qt3D::QNode *>(child->children().first());
- }
+ // WHEN
+ spyParent1.events.clear();
+ child->setParent(parent2.data());
// THEN
- QVERIFY(root->children().count() == 0);
+ QVERIFY(child->parent() == parent2.data());
+ QCOMPARE(parent1->children().size(), 0);
+ QCOMPARE(parent2->children().size(), 1);
+ QCOMPARE(spyParent1.events.size(), 1);
+ QCOMPARE(spyParent2.events.size(), 1);
+
+ // CHECK event 1 is a Node Deleted event
+ QVERIFY(spyParent1.events.first().wasLocked());
+ Qt3D::QScenePropertyChangePtr event = spyParent1.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeAboutToBeDeleted);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QVERIFY(!clone->parentNode());
+
+ // CHECK event 2 is a Node Added event
+ QVERIFY(spyParent2.events.last().wasLocked());
+ event = spyParent2.events.last().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeCreated);
+ QCOMPARE(event->propertyName(), "node");
+ clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QVERIFY(clone->parentNode());
+}
+
+
+void tst_Nodes::removingSingleChildNodeFromNode()
+{
+ // GIVEN
+ QScopedPointer<MyQNode> root(new MyQNode());
+ QScopedPointer<Qt3D::QNode> child(new MyQNode());
// WHEN
- firstChild->setParent(root);
+ child->setParent(root.data());
+
// THEN
QVERIFY(root->children().count() == 1);
+ QVERIFY(child->parentNode() == root.data());
+
+ // WHEN
+ ObserverSpy spy(root.data());
+ child->setParent(Q_NODE_NULLPTR);
+
+ // THEN
+ QVERIFY(child->parent() == Q_NULLPTR);
+ QVERIFY(root->children().count() == 0);
+
+ QCOMPARE(spy.events.size(), 1);
+ QVERIFY(spy.events.first().wasLocked());
+ Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ QCOMPARE(event->type(), Qt3D::NodeAboutToBeDeleted);
+ QCOMPARE(event->propertyName(), "node");
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), child->id());
+ QVERIFY(!clone->parentNode());
+}
+void tst_Nodes::removingMultipleChildNodesFromNode()
+{
// GIVEN
- Qt3D::QNode *parent = child->parentNode();
+ QScopedPointer<MyQNode> root(new MyQNode());
+
// WHEN
- for (int i = 0; i < 10; i++) {
- // THEN
- QVERIFY(parent->children().count() == 1);
- QVERIFY(child->parentNode() == parent);
+ root->assignScene();
+ ObserverSpy spy(root.data());
- // WHEN
- ObserverSpy spy(parent);
- child->setParent(Q_NULLPTR);
+ // THEN
+ QVERIFY(Qt3D::QNodePrivate::get(root.data())->scene() != Q_NULLPTR);
- // THEN
- QVERIFY(child->parent() == Q_NULLPTR);
- QVERIFY(parent->children().count() == 0);
+ // WHEN
+ for (int i = 0; i < 10; i++)
+ (void) new MyQNode(root.data());
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(root->children().count(), 10);
+ QCOMPARE(spy.events.size(), 10);
+
+ // WHEN
+ spy.events.clear();
+ Q_FOREACH (QObject *c, root->children())
+ delete c;
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ // THEN
+ QVERIFY(root->children().count() == 0);
+ QCOMPARE(spy.events.size(), 10);
+ Q_FOREACH (const ObserverSpy::ChangeRecord &r, spy.events) {
+ QVERIFY(r.wasLocked());
+ Qt3D::QScenePropertyChangePtr event = r.change().dynamicCast<Qt3D::QScenePropertyChange>();
QCOMPARE(event->type(), Qt3D::NodeAboutToBeDeleted);
QCOMPARE(event->propertyName(), "node");
Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), child->id());
QVERIFY(!clone->parentNode());
-
- // WHEN
- child = parent;
- parent = parent->parentNode();
}
- // THEN
- QVERIFY(parent == root);
- QVERIFY(parent->children().first() == firstChild);
- QVERIFY(firstChild->children().isEmpty());
}
void tst_Nodes::appendingChildEntitiesToNode()
{
// GIVEN
- MyQNode *root = new MyQNode();
+ QScopedPointer<MyQNode> root(new MyQNode());
// WHEN
- Qt3D::QEntity *childEntity = new Qt3D::QEntity(root);
+ Qt3D::QEntity *childEntity = new Qt3D::QEntity(root.data());
// THEN
QVERIFY(root->children().first() == childEntity);
QVERIFY(childEntity->parentEntity() == Q_NULLPTR);
- QVERIFY(childEntity->parentNode() == root);
+ QVERIFY(childEntity->parentNode() == root.data());
}
void tst_Nodes::removingChildEntitiesFromNode()
{
// GIVEN
- MyQNode *root = new MyQNode();
+ QScopedPointer<MyQNode> root(new MyQNode());
// WHEN
- Qt3D::QEntity *childEntity = new Qt3D::QEntity(root);
+ Qt3D::QEntity *childEntity = new Qt3D::QEntity(root.data());
// THEN
QVERIFY(root->children().first() == childEntity);
QVERIFY(childEntity->parentEntity() == Q_NULLPTR);
- QVERIFY(childEntity->parentNode() == root);
+ QVERIFY(childEntity->parentNode() == root.data());
// WHEN
- childEntity->setParent(Q_NULLPTR);
+ childEntity->setParent(Q_NODE_NULLPTR);
// THEN
QVERIFY(root->children().isEmpty());
@@ -390,174 +631,111 @@ void tst_Nodes::removingChildEntitiesFromNode()
QVERIFY(childEntity->parent() == Q_NULLPTR);
}
-void tst_Nodes::appendingComponentsToEntity()
+void tst_Nodes::appendingParentlessComponentToEntity()
{
// GIVEN
- MyQNode *root = new MyQNode();
-
- Qt3D::QEntity *entity = new Qt3D::QEntity(root);
-
- MyQComponent *comp1 = new MyQComponent(root);
-
- MyQComponent *comp2 = new MyQComponent(entity);
- MyQComponent *comp3 = new MyQComponent();
+ QScopedPointer<Qt3D::QEntity> entity(new Qt3D::QEntity());
+ MyQComponent *comp = new MyQComponent();
// THEN
- QVERIFY(entity->parentNode() == root);
- QVERIFY(root->children().count() == 2);
- QVERIFY(entity->children().count() == 1);
+ QVERIFY(entity->parentNode() == Q_NULLPTR);
+ QVERIFY(entity->children().count() == 0);
QVERIFY(entity->components().empty());
- QVERIFY(comp3->parentNode() == Q_NULLPTR);
-
- ObserverSpy spy(entity);
+ QVERIFY(comp->parentNode() == Q_NULLPTR);
// WHEN
- entity->addComponent(comp1);
+ ObserverSpy spy(entity.data());
+ entity->addComponent(comp);
+
// THEN
QVERIFY(entity->components().count() == 1);
- QVERIFY(entity->components().first() == comp1);
- QVERIFY(comp1->parentNode() == root);
- QVERIFY(comp2->parentNode() == entity);
- QVERIFY(comp3->parentNode() == Q_NULLPTR);
+ QVERIFY(entity->components().first() == comp);
+ QVERIFY(comp->parentNode() == entity.data());
QCOMPARE(spy.events.size(), 1);
QVERIFY(spy.events.first().wasLocked());
+
+ // Note: since QEntity has no scene in this test case, we only have the
+ // ComponentAdded event In theory we should also get the NodeCreated event
+ // when setting the parent but that doesn't happen since no scene is
+ // actually set on the entity and that QNodePrivate::_q_addChild will
+ // return early in such a case.
+
+ // Check that we received ComponentAdded
Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
QCOMPARE(event->type(), Qt3D::ComponentAdded);
QCOMPARE(event->propertyName(), "component");
Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), comp1->id());
+ QCOMPARE(clone->id(), comp->id());
QVERIFY(!clone->parentNode());
+}
- // WHEN
- entity->addComponent(comp2);
- // THEN
- QVERIFY(entity->components().count() == 2);
- QVERIFY(entity->components().first() == comp1);
- QVERIFY(entity->components().last() == comp2);
- QVERIFY(comp1->parentNode() == root);
- QVERIFY(comp2->parentNode() == entity);
- QVERIFY(comp3->parentNode() == Q_NULLPTR);
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::ComponentAdded);
- QCOMPARE(event->propertyName(), "component");
- clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), comp2->id());
- QVERIFY(!clone->parentNode());
+void tst_Nodes::appendingComponentToEntity()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity(new Qt3D::QEntity());
+ MyQComponent *comp = new MyQComponent(entity.data());
+ QCoreApplication::processEvents();
- // WHEN
- entity->addComponent(comp3);
// THEN
- QVERIFY(entity->components().count() == 3);
- QVERIFY(entity->components().first() == comp1);
- QVERIFY(entity->components().last() == comp3);
- QVERIFY(comp1->parentNode() == root);
- QVERIFY(comp2->parentNode() == entity);
- QVERIFY(comp3->parentNode() == entity);
- QCOMPARE(entity->children().count(), 2);
-
- QCOMPARE(spy.events.size(), 2);
+ QVERIFY(entity->parentNode() == Q_NULLPTR);
+ QVERIFY(entity->children().count() == 1);
+ QVERIFY(entity->components().empty());
+ QVERIFY(comp->parentNode() == entity.data());
- QVERIFY(spy.events.first().wasLocked());
- event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::NodeCreated);
- QCOMPARE(event->propertyName(), "node");
- clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), comp3->id());
- QCOMPARE(clone->parentNode()->id(), entity->id());
+ // WHEN
+ ObserverSpy spy(entity.data());
+ entity->addComponent(comp);
+ // THEN
+ QVERIFY(entity->components().count() == 1);
+ QVERIFY(entity->components().first() == comp);
+ QVERIFY(comp->parentNode() == entity.data());
+ QCOMPARE(spy.events.size(), 1);
QVERIFY(spy.events.first().wasLocked());
- event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
+ Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
QCOMPARE(event->type(), Qt3D::ComponentAdded);
QCOMPARE(event->propertyName(), "component");
- clone = event->value().value<Qt3D::QNodePtr>();
- QCOMPARE(clone->id(), comp3->id());
+ Qt3D::QNodePtr clone = event->value().value<Qt3D::QNodePtr>();
+ QCOMPARE(clone->id(), comp->id());
QVERIFY(!clone->parentNode());
}
-void tst_Nodes::removingComponentsFromEntity()
+void tst_Nodes::removingComponentFromEntity()
{
// GIVEN
- MyQNode *root = new MyQNode();
- Qt3D::QEntity *entity = new Qt3D::QEntity(root);
-
- MyQComponent *comp1 = new MyQComponent(root);
- MyQComponent *comp2 = new MyQComponent(entity);
- MyQComponent *comp3 = new MyQComponent();
+ QScopedPointer<Qt3D::QEntity> entity(new Qt3D::QEntity());
+ MyQComponent *comp = new MyQComponent();
// WHEN
- entity->addComponent(comp1);
- entity->addComponent(comp2);
- entity->addComponent(comp3);
+ entity->addComponent(comp);
// THEN
- QVERIFY(entity->components().count() == 3);
- QCOMPARE(entity->children().count(), 2);
+ QVERIFY(entity->components().count() == 1);
+ QCOMPARE(entity->children().count(), 1);
+ QVERIFY(comp->parent() == entity.data());
- ObserverSpy spy(entity);
+ ObserverSpy spy(entity.data());
// WHEN
- entity->removeComponent(comp2);
+ entity->removeComponent(comp);
// THEN
- QVERIFY(entity->components().count() == 2);
- QVERIFY(comp2->parent() == entity);
- QVERIFY(entity->children().count() == 2);
+ QVERIFY(entity->components().count() == 0);
+ QVERIFY(comp->parent() == entity.data());
+ QVERIFY(entity->children().count() == 1);
QCOMPARE(spy.events.size(), 1);
QVERIFY(spy.events.first().wasLocked());
Qt3D::QScenePropertyChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
QCOMPARE(event->type(), Qt3D::ComponentRemoved);
QCOMPARE(event->propertyName(), "componentId");
Qt3D::QNodeId nodeId = event->value().value<Qt3D::QNodeId>();
- QCOMPARE(nodeId, comp2->id());
-
- // WHEN
- entity->removeComponent(comp1);
- // THEN
- QVERIFY(entity->components().count() == 1);
- QVERIFY(comp1->parentNode() == root);
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::ComponentRemoved);
- QCOMPARE(event->propertyName(), "componentId");
- nodeId = event->value().value<Qt3D::QNodeId>();
- QCOMPARE(nodeId, comp1->id());
-
- // WHEN
- entity->removeComponent(comp3);
- // THEN
- QVERIFY(entity->components().count() == 0);
- QVERIFY(comp3->parentNode() == entity);
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- event = spy.events.takeFirst().change().dynamicCast<Qt3D::QScenePropertyChange>();
- QCOMPARE(event->type(), Qt3D::ComponentRemoved);
- QCOMPARE(event->propertyName(), "componentId");
- nodeId = event->value().value<Qt3D::QNodeId>();
- QCOMPARE(nodeId, comp3->id());
-
- // WHEN
- entity->addComponent(comp1);
- entity->addComponent(comp2);
- entity->addComponent(comp3);
- // THEN
- QVERIFY(entity->components().count() == 3);
- QCOMPARE(entity->children().count(), 2);
-
- // WHEN
- Q_FOREACH (QObject *c, entity->children())
- c->setParent(Q_NULLPTR);
- // THEN
- QCOMPARE(entity->components().count(), 3);
- QCOMPARE(entity->children().count(), 0);
+ QCOMPARE(nodeId, comp->id());
}
void tst_Nodes::changeCustomProperty()
{
// GIVEN
- MyQNode *node = new MyQNode();
- ObserverSpy spy(node);
+ QScopedPointer<MyQNode> node(new MyQNode());
+ ObserverSpy spy(node.data());
// WHEN
node->setCustomProperty(QStringLiteral("foo"));
// THEN
@@ -572,8 +750,8 @@ void tst_Nodes::changeCustomProperty()
void tst_Nodes::checkDestruction()
{
// GIVEN
- MyQNode *root = new MyQNode();
- Qt3D::QEntity *entity = new Qt3D::QEntity(root);
+ QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3D::QEntity *entity = new Qt3D::QEntity(root.data());
MyQComponent *comp1 = new MyQComponent();
MyQComponent *comp2 = new MyQComponent();
@@ -593,6 +771,32 @@ void tst_Nodes::checkDestruction()
QVERIFY(root->children().isEmpty());
}
-QTEST_GUILESS_MAIN(tst_Nodes)
+void tst_Nodes::verifyCopy()
+{
+ // GIVEN
+ QScopedPointer<MyQNode> root(new MyQNode());
+ MyQNode *other1 = new MyQNode();
+ MyQNode *other2 = new MyQNode();
+
+ // THEN
+ QVERIFY(root->id() != other1->id());
+ QVERIFY(root->id() != other2->id());
+ QVERIFY(other1->id() != other2->id());
+
+ // WHEN
+ other1->makeCopyOf(root.data());
+
+ // THEN
+ QVERIFY(root->id() == other1->id());
+ QVERIFY(root->id() != other2->id());
+
+ // WHEN
+ other2->makeCopyOf(other1);
+
+ // THEN
+ QVERIFY(root->id() == other1->id() && root->id() == other2->id());
+}
+
+QTEST_MAIN(tst_Nodes)
#include "tst_nodes.moc"
diff --git a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
index 5dd229a50..d405358fd 100644
--- a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
+++ b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
@@ -528,7 +528,7 @@ void tst_QChangeArbiter::unregisterSceneObservers()
QVERIFY(s->lastChange()->type() == Qt3D::NodeCreated);
}
- child->setParent(Q_NULLPTR);
+ child->setParent(Q_NODE_NULLPTR);
arbiter->syncChanges();
Q_FOREACH (tst_SimpleObserver *o, observers) {
diff --git a/tests/auto/core/qentity/tst_qentity.cpp b/tests/auto/core/qentity/tst_qentity.cpp
index 4c207ed3f..2f7ebf314 100644
--- a/tests/auto/core/qentity/tst_qentity.cpp
+++ b/tests/auto/core/qentity/tst_qentity.cpp
@@ -36,6 +36,7 @@
#include <QtTest/QtTest>
#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qcomponent.h>
#include <QtCore/qscopedpointer.h>
using namespace Qt3D;
@@ -50,21 +51,554 @@ public:
private slots:
void constructionDestruction();
- // TODO: Add more entity tests
+ void addComponentSingleParentSingleAggregation();
+ void addComponentSingleParentSeveralAggregations();
+ void addComponentsSeveralParentsSingleAggregations();
+ void addComponentsSeveralParentsSeveralAggregations();
+
+ void removeComponentSingleParentSingleAggregation();
+ void removeComponentSingleParentSeveralAggregations();
+ void removeComponentsSeveralParentsSingleAggreation();
+ void removeComponentsSeveralParentsSeveralAggregations();
+
+ void addSeveralTimesSameComponent();
+ void removeSeveralTimesSameComponent();
+ void verifyCopy();
+};
+
+class MyQComponent : public Qt3D::QComponent
+{
+ Q_OBJECT
+public:
+ explicit MyQComponent(Qt3D::QNode *parent = 0)
+ : QComponent(parent)
+ {}
+
+ ~MyQComponent()
+ {
+ QNode::cleanup();
+ }
+
+protected:
+ QT3D_CLONEABLE(MyQComponent)
+};
+
+
+class MyEntity : public Qt3D::QEntity
+{
+public:
+ explicit MyEntity(Qt3D::QNode *parent = 0)
+ : QEntity(parent)
+ {}
+
+ void makeCopyOf(Qt3D::QEntity *other)
+ {
+ QEntity::copy(other);
+ }
};
void tst_Entity::constructionDestruction()
{
+ // GIVEN
QEntity *entity = Q_NULLPTR;
+ // WHEN
entity = new QEntity;
+ // THEN
QVERIFY(entity != Q_NULLPTR);
delete entity;
+ // GIVEN
QScopedPointer<QEntity> entity2(new QEntity);
+ // WHEN
entity2.reset(Q_NULLPTR);
+ // THEN
+ // this should not crash
}
-QTEST_APPLESS_MAIN(tst_Entity)
+void tst_Entity::addComponentSingleParentSingleAggregation()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity(new QEntity());
+ MyQComponent *comp = new MyQComponent(entity.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 0);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 0);
+
+ // WHEN
+ entity->addComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 1);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 1);
+}
+
+void tst_Entity::addComponentSingleParentSeveralAggregations()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity1.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity1.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 3);
+ QCOMPARE(entity2->children().size(), 0);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+
+ // WHEN
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+ entity1->addComponent(comp3);
+
+ entity2->addComponent(comp1);
+ entity2->addComponent(comp2);
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity1.data());
+
+ QCOMPARE(entity1->components().size(), 3);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 3);
+ QCOMPARE(entity2->children().size(), 0);
+
+ QCOMPARE(comp1->entities().size(), 2);
+ QCOMPARE(comp2->entities().size(), 2);
+ QCOMPARE(comp3->entities().size(), 2);
+}
+
+void tst_Entity::addComponentsSeveralParentsSingleAggregations()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity2.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+
+ // WHEN
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 2);
+ QCOMPARE(entity2->components().size(), 1);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 1);
+ QCOMPARE(comp2->entities().size(), 1);
+ QCOMPARE(comp3->entities().size(), 1);
+}
+
+void tst_Entity::addComponentsSeveralParentsSeveralAggregations()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity2.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+
+ // WHEN
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+ entity1->addComponent(comp3);
+
+ entity2->addComponent(comp1);
+ entity2->addComponent(comp2);
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 3);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 2);
+ QCOMPARE(comp2->entities().size(), 2);
+ QCOMPARE(comp3->entities().size(), 2);
+}
+
+void tst_Entity::removeComponentSingleParentSingleAggregation()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity(new QEntity());
+ MyQComponent *comp = new MyQComponent(entity.data());
+ QCoreApplication::processEvents();
+ entity->addComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 1);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 1);
+
+ // WHEN
+ entity->removeComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 0);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 0);
+}
+
+void tst_Entity::removeComponentSingleParentSeveralAggregations()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity1.data());
+ QCoreApplication::processEvents();
+
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+ entity1->addComponent(comp3);
+
+ entity2->addComponent(comp1);
+ entity2->addComponent(comp2);
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity1.data());
+
+ QCOMPARE(entity1->components().size(), 3);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 3);
+ QCOMPARE(entity2->children().size(), 0);
+
+ QCOMPARE(comp1->entities().size(), 2);
+ QCOMPARE(comp2->entities().size(), 2);
+ QCOMPARE(comp3->entities().size(), 2);
+
+ // WHEN
+ entity1->removeComponent(comp1);
+ entity1->removeComponent(comp2);
+ entity1->removeComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity1.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 3);
+ QCOMPARE(entity2->children().size(), 0);
+
+ QCOMPARE(comp1->entities().size(), 1);
+ QCOMPARE(comp2->entities().size(), 1);
+ QCOMPARE(comp3->entities().size(), 1);
+
+ // WHEN
+ entity2->removeComponent(comp1);
+ entity2->removeComponent(comp2);
+ entity2->removeComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity1.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 3);
+ QCOMPARE(entity2->children().size(), 0);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+}
+
+void tst_Entity::removeComponentsSeveralParentsSingleAggreation()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity2.data());
+ QCoreApplication::processEvents();
+
+ // WHEN
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 2);
+ QCOMPARE(entity2->components().size(), 1);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 1);
+ QCOMPARE(comp2->entities().size(), 1);
+ QCOMPARE(comp3->entities().size(), 1);
+
+ // WHEN
+ entity1->removeComponent(comp1);
+ entity1->removeComponent(comp2);
+ entity2->removeComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+}
+
+void tst_Entity::removeComponentsSeveralParentsSeveralAggregations()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity1(new QEntity());
+ QScopedPointer<Qt3D::QEntity> entity2(new QEntity());
+
+ MyQComponent *comp1 = new MyQComponent(entity1.data());
+ MyQComponent *comp2 = new MyQComponent(entity1.data());
+ MyQComponent *comp3 = new MyQComponent(entity2.data());
+ QCoreApplication::processEvents();
+
+ // WHEN
+ entity1->addComponent(comp1);
+ entity1->addComponent(comp2);
+ entity1->addComponent(comp3);
+
+ entity2->addComponent(comp1);
+ entity2->addComponent(comp2);
+ entity2->addComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 3);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 2);
+ QCOMPARE(comp2->entities().size(), 2);
+ QCOMPARE(comp3->entities().size(), 2);
+
+ // WHEN
+ entity1->removeComponent(comp1);
+ entity1->removeComponent(comp2);
+ entity1->removeComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 3);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 1);
+ QCOMPARE(comp2->entities().size(), 1);
+ QCOMPARE(comp3->entities().size(), 1);
+
+ // WHEN
+ entity2->removeComponent(comp1);
+ entity2->removeComponent(comp2);
+ entity2->removeComponent(comp3);
+
+ // THEN
+ QVERIFY(comp1->parent() == entity1.data());
+ QVERIFY(comp2->parent() == entity1.data());
+ QVERIFY(comp3->parent() == entity2.data());
+
+ QCOMPARE(entity1->components().size(), 0);
+ QCOMPARE(entity2->components().size(), 0);
+
+ QCOMPARE(entity1->children().size(), 2);
+ QCOMPARE(entity2->children().size(), 1);
+
+ QCOMPARE(comp1->entities().size(), 0);
+ QCOMPARE(comp2->entities().size(), 0);
+ QCOMPARE(comp3->entities().size(), 0);
+}
+
+void tst_Entity::addSeveralTimesSameComponent()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity(new QEntity());
+ MyQComponent *comp = new MyQComponent(entity.data());
+ QCoreApplication::processEvents();
+ entity->addComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 1);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 1);
+
+ // WHEN
+ entity->addComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 1);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 1);
+}
+
+void tst_Entity::removeSeveralTimesSameComponent()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> entity(new QEntity());
+ MyQComponent *comp = new MyQComponent(entity.data());
+ QCoreApplication::processEvents();
+ entity->addComponent(comp);
+ entity->removeComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 0);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 0);
+
+ // WHEN
+ entity->removeComponent(comp);
+
+ // THEN
+ QVERIFY(comp->parent() == entity.data());
+ QCOMPARE(entity->components().size(), 0);
+ QCOMPARE(entity->children().size(), 1);
+ QCOMPARE(comp->entities().size(), 0);
+}
+
+void tst_Entity::verifyCopy()
+{
+ // GIVEN
+ QScopedPointer<Qt3D::QEntity> root(new Qt3D::QEntity());
+ MyEntity *parentLessEntity = new MyEntity();
+ MyEntity *parentedEntity = new MyEntity(root.data());
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(root->id() != parentLessEntity->id());
+ QVERIFY(root->id() != parentedEntity->id());
+ QVERIFY(root->parentEntityId().isNull());
+ QVERIFY(!parentedEntity->parentEntityId().isNull());
+ QVERIFY(parentLessEntity->parentEntityId().isNull());
+
+ // WHEN
+ MyEntity *parentedEntityCopy = new MyEntity();
+ parentedEntityCopy->makeCopyOf(parentedEntity);
+
+ // THEN
+ QVERIFY(parentedEntityCopy->id() == parentedEntity->id());
+ QVERIFY(parentedEntityCopy->parentEntityId() == parentedEntity->parentEntityId());
+
+ // WHEN
+ MyEntity *parentLessEntityCopy = new MyEntity();
+ parentLessEntityCopy->makeCopyOf(parentLessEntity);
+
+ // THEN
+ QVERIFY(parentLessEntityCopy->id() == parentLessEntity->id());
+ QVERIFY(parentLessEntityCopy->parentEntityId() == parentLessEntity->parentEntityId());
+}
+
+
+QTEST_MAIN(tst_Entity)
#include "tst_qentity.moc"
diff --git a/tests/auto/core/qscene/tst_qscene.cpp b/tests/auto/core/qscene/tst_qscene.cpp
index fd7be1fcd..51a469836 100644
--- a/tests/auto/core/qscene/tst_qscene.cpp
+++ b/tests/auto/core/qscene/tst_qscene.cpp
@@ -88,6 +88,12 @@ class tst_Node : public Qt3D::QNode
public:
tst_Node() : Qt3D::QNode()
{}
+
+ ~tst_Node()
+ {
+ QNode::cleanup();
+ }
+
protected:
QT3D_CLONEABLE(tst_Node)
};
@@ -97,12 +103,19 @@ class tst_Component : public Qt3D::QComponent
public:
tst_Component() : Qt3D::QComponent()
{}
+
+ ~tst_Component()
+ {
+ QNode::cleanup();
+ }
+
protected:
QT3D_CLONEABLE(tst_Component)
};
void tst_QScene::addObservable()
{
+ // GIVEN
Qt3D::QNode *node1 = new tst_Node();
Qt3D::QNode *node2 = new tst_Node();
@@ -114,6 +127,7 @@ void tst_QScene::addObservable()
Qt3D::QScene *scene = new Qt3D::QScene;
scene->setArbiter(new tst_LockableObserver);
+ // WHEN
for (int i = 0; i < 5; i++)
scene->addObservable(observables.at(i), node1->id());
@@ -123,6 +137,7 @@ void tst_QScene::addObservable()
Qt3D::QObservableList obs1 = scene->lookupObservables(node1->id());
Qt3D::QObservableList obs2 = scene->lookupObservables(node2->id());
+ // THEN
QCOMPARE(obs1.count(), 5);
QCOMPARE(obs2.count(), obs1.count());
@@ -138,6 +153,7 @@ void tst_QScene::addObservable()
void tst_QScene::addNodeObservable()
{
+ // GIBEN
QList<Qt3D::QNode *> nodes;
for (int i = 0; i < 10; i++)
@@ -146,9 +162,11 @@ void tst_QScene::addNodeObservable()
Qt3D::QScene *scene = new Qt3D::QScene;
scene->setArbiter(new tst_LockableObserver);
+ // WHEN
for (int i = 0; i < 10; i++)
scene->addObservable(nodes.at(i));
+ // THEN
Q_FOREACH (Qt3D::QNode *n, nodes) {
QVERIFY(n == scene->lookupNode(n->id()));
QVERIFY(scene->lookupObservables(n->id()).isEmpty());
@@ -157,6 +175,7 @@ void tst_QScene::addNodeObservable()
void tst_QScene::removeObservable()
{
+ // GIVEN
Qt3D::QNode *node1 = new tst_Node();
Qt3D::QNode *node2 = new tst_Node();
@@ -168,6 +187,7 @@ void tst_QScene::removeObservable()
Qt3D::QScene *scene = new Qt3D::QScene;
scene->setArbiter(new tst_LockableObserver);
+ // WHEN
for (int i = 0; i < 5; i++)
scene->addObservable(observables.at(i), node1->id());
@@ -177,27 +197,36 @@ void tst_QScene::removeObservable()
Qt3D::QObservableList obs1 = scene->lookupObservables(node1->id());
Qt3D::QObservableList obs2 = scene->lookupObservables(node2->id());
+ // THEN
QCOMPARE(obs1.count(), 5);
QCOMPARE(obs2.count(), obs1.count());
+ // WHEN
scene->removeObservable(observables.at(0), node1->id());
+ // THEN
QCOMPARE(scene->lookupObservables(node1->id()).count(), 4);
+ // WHEN
scene->removeObservable(observables.at(0), node1->id());
+ // THEN
QCOMPARE(scene->lookupObservables(node1->id()).count(), 4);
+ // WHEN
scene->removeObservable(observables.at(6), node1->id());
+ // THEN
QCOMPARE(scene->lookupObservables(node1->id()).count(), 4);
QCOMPARE(scene->lookupObservables(node2->id()).count(), 5);
+ // WHEN
scene->removeObservable(observables.at(0), node2->id());
+ // THEN
QCOMPARE(scene->lookupObservables(node2->id()).count(), 5);
-
QVERIFY(scene->nodeIdFromObservable(observables.at(0)) == Qt3D::QNodeId());
}
void tst_QScene::removeNodeObservable()
{
+ // GIVEN
Qt3D::QNode *node1 = new tst_Node();
Qt3D::QNode *node2 = new tst_Node();
@@ -209,6 +238,7 @@ void tst_QScene::removeNodeObservable()
Qt3D::QScene *scene = new Qt3D::QScene;
scene->setArbiter(new tst_LockableObserver);
+ // WHEN
scene->addObservable(node1);
scene->addObservable(node2);
@@ -218,14 +248,17 @@ void tst_QScene::removeNodeObservable()
for (int i = 0; i < 5; i++)
scene->addObservable(observables.at(i + 5), node2->id());
+ // THEN
Qt3D::QObservableList obs1 = scene->lookupObservables(node1->id());
Qt3D::QObservableList obs2 = scene->lookupObservables(node2->id());
QCOMPARE(obs1.count(), 5);
QCOMPARE(obs2.count(), obs1.count());
+ // WHEN
scene->removeObservable(node1);
+ // THEN
QVERIFY(scene->lookupNode(node1->id()) == Q_NULLPTR);
QVERIFY(scene->lookupObservables(node1->id()).empty());
QVERIFY(scene->nodeIdFromObservable(observables.at(0)) == Qt3D::QNodeId());
@@ -237,13 +270,20 @@ void tst_QScene::removeNodeObservable()
void tst_QScene::addChildNode()
{
+ // GIVEN
Qt3D::QScene *scene = new Qt3D::QScene;
QList<Qt3D::QNode *> nodes;
Qt3D::QNode *root = new tst_Node();
Qt3D::QNodePrivate::get(root)->setScene(scene);
+
+ // WHEN
scene->addObservable(root);
+ // THEN
+ QVERIFY(scene->lookupNode(root->id()) == root);
+
+ // WHEN
for (int i = 0; i < 10; i++) {
Qt3D::QNode *child = new tst_Node();
if (nodes.isEmpty())
@@ -252,10 +292,9 @@ void tst_QScene::addChildNode()
child->setParent(nodes.last());
nodes.append(child);
}
-
- QVERIFY(scene->lookupNode(root->id()) == root);
QCoreApplication::processEvents();
+ // THEN
Q_FOREACH (Qt3D::QNode *n, nodes) {
QVERIFY(scene->lookupNode(n->id()) == n);
}
@@ -263,6 +302,7 @@ void tst_QScene::addChildNode()
void tst_QScene::removeChildNode()
{
+ // GIVEN
Qt3D::QScene *scene = new Qt3D::QScene;
QList<Qt3D::QNode *> nodes;
@@ -270,6 +310,8 @@ void tst_QScene::removeChildNode()
Qt3D::QNode *root = new tst_Node;
Qt3D::QNodePrivate::get(root)->setScene(scene);
scene->addObservable(root);
+
+ // WHEN
for (int i = 0; i < 10; i++) {
Qt3D::QNode *child = new tst_Node;
if (nodes.isEmpty())
@@ -279,11 +321,12 @@ void tst_QScene::removeChildNode()
nodes.append(child);
}
+ // THEN
while (!nodes.isEmpty()) {
Qt3D::QNode *lst = nodes.takeLast();
QVERIFY(scene->lookupNode(lst->id()) == lst);
if (lst->parentNode() != Q_NULLPTR) {
- lst->setParent(Q_NULLPTR);
+ lst->setParent(Q_NODE_NULLPTR);
QCoreApplication::processEvents();
QVERIFY(scene->lookupNode(lst->id()) == Q_NULLPTR);
}
@@ -292,6 +335,7 @@ void tst_QScene::removeChildNode()
void tst_QScene::addEntityForComponent()
{
+ // GIVEN
Qt3D::QScene *scene = new Qt3D::QScene;
QList<Qt3D::QEntity *> entities;
@@ -307,6 +351,7 @@ void tst_QScene::addEntityForComponent()
components << comp;
}
+ // WHEN
for (int i = 0; i < 10; i++) {
Qt3D::QEntity *e = entities.at(i);
for (int j = 0; j < 10; j++) {
@@ -314,6 +359,7 @@ void tst_QScene::addEntityForComponent()
}
}
+ // THEN
for (int i = 0; i < 10; i++) {
QList<Qt3D::QNodeId> ids = scene->entitiesForComponent(components.at(i)->id());
QCOMPARE(ids.count(), 10);
@@ -322,6 +368,7 @@ void tst_QScene::addEntityForComponent()
void tst_QScene::removeEntityForComponent()
{
+ // GIVEN
Qt3D::QScene *scene = new Qt3D::QScene;
QList<Qt3D::QEntity *> entities;
@@ -337,6 +384,7 @@ void tst_QScene::removeEntityForComponent()
components << comp;
}
+ // WHEN
for (int i = 0; i < 10; i++) {
Qt3D::QEntity *e = entities.at(i);
for (int j = 0; j < 10; j++) {
@@ -344,6 +392,7 @@ void tst_QScene::removeEntityForComponent()
}
}
+ // THEN
for (int i = 0; i < 10; i++) {
Qt3D::QEntity *e = entities.at(i);
for (int j = 0; j < 10; j++) {