diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2015-06-09 15:26:58 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2015-06-11 19:27:56 +0000 |
commit | 3fc58a37f50cbae3d3e551dc6311771b561175cd (patch) | |
tree | f85094e6b55b450f2a2656427f07cf82f7b7d6a9 | |
parent | 1d2818870034eacb1b0b6de3df279284d3ad24c3 (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>
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 ¶meterName, 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 ¶meterName, 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++) { |