diff options
Diffstat (limited to 'src/core')
25 files changed, 213 insertions, 421 deletions
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp index 2ad3248e5..866a0ce25 100644 --- a/src/core/aspects/qabstractaspect.cpp +++ b/src/core/aspects/qabstractaspect.cpp @@ -191,12 +191,6 @@ void QAbstractAspect::unregisterBackendType(const QMetaObject &obj) d->m_backendCreatorFunctors.remove(&obj); } -void QAbstractAspectPrivate::sceneNodeRemoved(QSceneChangePtr &change) -{ - QNodeDestroyedChangePtr destructionChange = qSharedPointerCast<QNodeDestroyedChange>(change); - clearBackendNode(destructionChange); -} - QVariant QAbstractAspect::executeCommand(const QStringList &args) { Q_UNUSED(args); @@ -215,9 +209,9 @@ void QAbstractAspect::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes) d->syncDirtyFrontEndNodes(nodes); } -QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(QNode *n) const +QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(const QMetaObject *metaObj) const { - const QMetaObject *metaObj = n->metaObject(); + Q_ASSERT(metaObj); BackendNodeMapperAndInfo info; while (metaObj != nullptr && info.first.isNull()) { @@ -230,7 +224,8 @@ QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperF void QAbstractAspectPrivate::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes) { for (auto node: qAsConst(nodes)) { - const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(node); + const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo; + const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj); const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first; if (!backendNodeMapper) @@ -300,42 +295,37 @@ void QAbstractAspectPrivate::sendPropertyMessages(QNode *node, QBackendNode *bac } } -QBackendNode *QAbstractAspectPrivate::createBackendNode(const QNodeCreatedChangeBasePtr &change) const +QBackendNode *QAbstractAspectPrivate::createBackendNode(const NodeTreeChange &change) const { - Q_UNUSED(change); - Q_ASSERT(false); // should not be here - return nullptr; -} - -QBackendNode *QAbstractAspectPrivate::createBackendNode(QNode *node) const -{ - const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(node); + const QMetaObject *metaObj = change.metaObj; + const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj); const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first; if (!backendNodeMapper) return nullptr; - QBackendNode *backend = backendNodeMapper->get(node->id()); + QBackendNode *backend = backendNodeMapper->get(change.id); if (backend != nullptr) return backend; - QNodeCreatedChangeBasePtr change; + QNode *node = change.node; + QNodeCreatedChangeBasePtr creationChange; const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing; if (supportsSyncing) { // All objects modified to use syncing should only use the id in the creation functor QNodeCreatedChangeBase changeObj(node); - change = QNodeCreatedChangeBasePtr(&changeObj, [](QNodeCreatedChangeBase *) {}); - backend = backendNodeMapper->create(change); + creationChange = QNodeCreatedChangeBasePtr(&changeObj, [](QNodeCreatedChangeBase *) {}); + backend = backendNodeMapper->create(creationChange); } else { - change = node->createNodeCreationChange(); - backend = backendNodeMapper->create(change); + creationChange = node->createNodeCreationChange(); + backend = backendNodeMapper->create(creationChange); } if (!backend) return nullptr; // TODO: Find some place else to do all of this function from the arbiter - backend->setPeerId(node->id()); + backend->setPeerId(change.id); // Backend could be null if the user decides that his functor should only // perform some action when encountering a given type of item but doesn't need to @@ -348,7 +338,7 @@ QBackendNode *QAbstractAspectPrivate::createBackendNode(QNode *node) const // Register backendNode with QChangeArbiter if (m_arbiter != nullptr) { // Unit tests may not have the arbiter registered qCDebug(Nodes) << q_func()->objectName() << "Creating backend node for node id" - << node->id() << "of type" << node->metaObject()->className(); + << node->id() << "of type" << QNodePrivate::get(node)->m_typeInfo->className(); m_arbiter->registerObserver(backendPriv, backend->peerId(), AllChanges); if (backend->mode() == QBackendNode::ReadWrite) m_arbiter->scene()->addObservable(backendPriv, backend->peerId()); @@ -357,44 +347,34 @@ QBackendNode *QAbstractAspectPrivate::createBackendNode(QNode *node) const if (supportsSyncing) syncDirtyFrontEndNode(node, backend, true); else - backend->initializeFromPeer(change); + backend->initializeFromPeer(creationChange); return backend; } -void QAbstractAspectPrivate::clearBackendNode(const QNodeDestroyedChangePtr &change) const +void QAbstractAspectPrivate::clearBackendNode(const NodeTreeChange &change) const { - // Each QNodeDestroyedChange may contain info about a whole sub-tree of nodes that - // are being destroyed. Iterate over them and process each in turn - const auto subTree = change->subtreeIdsAndTypes(); - for (const auto &idAndType : subTree) { - const QMetaObject *metaObj = idAndType.type; - QBackendNodeMapperPtr backendNodeMapper; - - // Find backend node mapper for this type - while (metaObj != nullptr && backendNodeMapper.isNull()) { - backendNodeMapper = m_backendCreatorFunctors.value(metaObj).first; - metaObj = metaObj->superClass(); - } + const QMetaObject *metaObj = change.metaObj; + const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj); + const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first; - if (!backendNodeMapper) - continue; + if (!backendNodeMapper) + return; - // Request the mapper to destroy the corresponding backend node - QBackendNode *backend = backendNodeMapper->get(idAndType.id); - if (backend) { - qCDebug(Nodes) << q_func()->objectName() << "Deleting backend node for node id" - << idAndType.id << "of type" << idAndType.type->className(); - QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend); - m_arbiter->unregisterObserver(backendPriv, backend->peerId()); - if (backend->mode() == QBackendNode::ReadWrite) - m_arbiter->scene()->removeObservable(backendPriv, backend->peerId()); - backendNodeMapper->destroy(idAndType.id); - } + // Request the mapper to destroy the corresponding backend node + QBackendNode *backend = backendNodeMapper->get(change.id); + if (backend) { + qCDebug(Nodes) << "Deleting backend node for node id" + << change.id << "of type" << metaObj->className(); + QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend); + m_arbiter->unregisterObserver(backendPriv, backend->peerId()); + if (backend->mode() == QBackendNode::ReadWrite) + m_arbiter->scene()->removeObservable(backendPriv, backend->peerId()); + backendNodeMapper->destroy(change.id); } } -void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QVector<QNode *> &nodes) +void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QVector<NodeTreeChange> &nodesChanges) { qCDebug(Aspects) << Q_FUNC_INFO << "rootObject =" << rootObject; if (rootObject == m_root) @@ -403,14 +383,10 @@ void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QV m_root = rootObject; m_rootId = rootObject->id(); - createNodes(nodes); + for (const NodeTreeChange &change : nodesChanges) + createBackendNode(change); } -void QAbstractAspectPrivate::createNodes(const QVector<QNode *> &nodes) -{ - for (const auto node : nodes) - createBackendNode(node); -} QServiceLocator *QAbstractAspectPrivate::services() const { diff --git a/src/core/aspects/qabstractaspect_p.h b/src/core/aspects/qabstractaspect_p.h index ea2712fe5..8bd26cf00 100644 --- a/src/core/aspects/qabstractaspect_p.h +++ b/src/core/aspects/qabstractaspect_p.h @@ -56,8 +56,6 @@ #include <Qt3DCore/private/qaspectjobproviderinterface_p.h> #include <Qt3DCore/private/qbackendnode_p.h> -#include <Qt3DCore/private/qbackendnodefactory_p.h> -#include <Qt3DCore/private/qsceneobserverinterface_p.h> #include <Qt3DCore/private/qt3dcore_global_p.h> #include <QtCore/private/qobject_p.h> @@ -102,33 +100,39 @@ private: } // Debug +struct NodeTreeChange +{ + enum NodeTreeChangeType { + Added = 0, + Removed = 1 + }; + Qt3DCore::QNodeId id; + const QMetaObject *metaObj; + NodeTreeChangeType type; + Qt3DCore::QNode *node; +}; + class Q_3DCORE_PRIVATE_EXPORT QAbstractAspectPrivate : public QObjectPrivate - , public QBackendNodeFactory - , public QSceneObserverInterface , public QAspectJobProviderInterface { public: QAbstractAspectPrivate(); ~QAbstractAspectPrivate(); - void setRootAndCreateNodes(QEntity *rootObject, const QVector<QNode *> &nodes); - void createNodes(const QVector<QNode *> &nodes); + void setRootAndCreateNodes(QEntity *rootObject, const QVector<NodeTreeChange> &nodesTreeChanges); QServiceLocator *services() const; QAbstractAspectJobManager *jobManager() const; QVector<QAspectJobPtr> jobsToExecute(qint64 time) override; - QBackendNode *createBackendNode(const QNodeCreatedChangeBasePtr &change) const override; - QBackendNode *createBackendNode(QNode *node) const; - void clearBackendNode(const QNodeDestroyedChangePtr &change) const; + QBackendNode *createBackendNode(const NodeTreeChange &change) const; + void clearBackendNode(const NodeTreeChange &change) const; void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes); virtual void syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const; void sendPropertyMessages(QNode *node, QBackendNode *backend) const; - void sceneNodeRemoved(Qt3DCore::QSceneChangePtr &e) override; - virtual void onEngineAboutToShutdown(); // TODO: Make these public in 5.8 @@ -143,7 +147,7 @@ public: SupportsSyncing = 1 << 0 }; using BackendNodeMapperAndInfo = QPair<QBackendNodeMapperPtr, NodeMapperInfo>; - BackendNodeMapperAndInfo mapperForNode(QNode *n) const; + BackendNodeMapperAndInfo mapperForNode(const QMetaObject *metaObj) const; QEntity *m_root; QNodeId m_rootId; diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index 41662e2a3..426741a61 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -89,6 +89,23 @@ QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root) return nodes; } +QVector<Qt3DCore::QNode *> getNodesForRemoval(Qt3DCore::QNode *root) +{ + using namespace Qt3DCore; + + QVector<QNode *> nodes; + QNodeVisitor visitor; + visitor.traverse(root, [&nodes](QNode *node) { + nodes.append(node); + + // Mark this node as having been handled for destruction so we don't + // repeat it unnecessarily in an O(n^2) manner + QNodePrivate::get(node)->m_hasBackendNode = false; + }); + + return nodes; +} + } namespace Qt3DCore { @@ -152,6 +169,11 @@ void QAspectEnginePrivate::addNode(QNode *node) m_aspectManager->addNodes(getNodesForCreation(node)); } +void QAspectEnginePrivate::removeNode(QNode *node) +{ + m_aspectManager->removeNodes(getNodesForRemoval(node)); +} + /*! * \class Qt3DCore::QAspectEngine * \inheaderfile Qt3DCore/QAspectEngine @@ -253,6 +275,7 @@ void QAspectEnginePrivate::initialize() arbiter->setPostman(m_postman); arbiter->setScene(m_scene); m_initialized = true; + m_aspectManager->setPostConstructorInit(m_scene->postConstructorInit()); #if QT_CONFIG(qt3d_profile_jobs) m_commandDebugger->setAspectEngine(q_func()); m_commandDebugger->initialize(); diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h index 3e68a2caa..c83940435 100644 --- a/src/core/aspects/qaspectengine_p.h +++ b/src/core/aspects/qaspectengine_p.h @@ -106,6 +106,7 @@ public: void initNode(QNode *node); void initEntity(QEntity *entity); void addNode(QNode *node); + void removeNode(QNode *node); static QAspectEnginePrivate *get(QAspectEngine *engine); }; diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp index b6e6122a1..a33f771e9 100644 --- a/src/core/aspects/qaspectmanager.cpp +++ b/src/core/aspects/qaspectmanager.cpp @@ -61,6 +61,7 @@ #include <Qt3DCore/private/qtickclock_p.h> #include <Qt3DCore/private/qtickclockservice_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> +#include <Qt3DCore/private/qnode_p.h> #include <QtCore/QCoreApplication> @@ -224,9 +225,6 @@ void QAspectManager::shutdown() { qCDebug(Aspects) << Q_FUNC_INFO; - for (QAbstractAspect *aspect : qAsConst(m_aspects)) - m_changeArbiter->unregisterSceneObserver(aspect->d_func()); - // Aspects must be deleted in the Thread they were created in } @@ -246,15 +244,71 @@ void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<QNode m_root = root; if (m_root) { + + QVector<NodeTreeChange> nodeTreeChanges; + nodeTreeChanges.reserve(nodes.size()); + + for (QNode *n : nodes) { + nodeTreeChanges.push_back({ + n->id(), + QNodePrivate::get(n)->m_typeInfo, + NodeTreeChange::Added, + n + }); + } + for (QAbstractAspect *aspect : qAsConst(m_aspects)) - aspect->d_func()->setRootAndCreateNodes(m_root, nodes); + aspect->d_func()->setRootAndCreateNodes(m_root, nodeTreeChanges); } } + +// Main Thread -> immediately following node insertion void QAspectManager::addNodes(const QVector<QNode *> &nodes) { - for (QAbstractAspect *aspect : qAsConst(m_aspects)) - aspect->d_func()->createNodes(nodes); + // We record the nodes added information, which we will actually use when + // processFrame is called (later but within the same loop of the even loop + // as this call) The idea is we want to avoid modifying the backend tree if + // the Renderer hasn't allowed processFrame to continue yet + + QVector<NodeTreeChange> treeChanges; + treeChanges.reserve(nodes.size()); + + for (QNode *node : nodes) { + treeChanges.push_back({ node->id(), + QNodePrivate::get(node)->m_typeInfo, + NodeTreeChange::Added, + node }); + } + + m_nodeTreeChanges += treeChanges; +} + +// Main Thread -> immediately following node destruction (call from QNode dtor) +void QAspectManager::removeNodes(const QVector<QNode *> &nodes) +{ + // We record the nodes removed information, which we will actually use when + // processFrame is called (later but within the same loop of the even loop + // as this call) The idea is we want to avoid modifying the backend tree if + // the Renderer hasn't allowed processFrame to continue yet The drawback is + // that when processFrame is processed, the QNode* pointer might be invalid by + // that point. Therefore we record all we need to remove the object. + + for (QNode *node : nodes) { + // In addition, we check if we contain an Added change for a given node + // that is now about to be destroyed. If so we remove the Added change + // entirely + + m_nodeTreeChanges.erase(std::remove_if(m_nodeTreeChanges.begin(), + m_nodeTreeChanges.end(), + [&node] (const NodeTreeChange &change) { return change.id == node->id(); }), + m_nodeTreeChanges.end()); + + m_nodeTreeChanges.push_back({ node->id(), + QNodePrivate::get(node)->m_typeInfo, + NodeTreeChange::Removed, + nullptr }); + } } /*! @@ -271,8 +325,6 @@ void QAspectManager::registerAspect(QAbstractAspect *aspect) QAbstractAspectPrivate::get(aspect)->m_aspectManager = this; QAbstractAspectPrivate::get(aspect)->m_jobManager = m_jobManager; QAbstractAspectPrivate::get(aspect)->m_arbiter = m_changeArbiter; - // Register sceneObserver with the QChangeArbiter - m_changeArbiter->registerSceneObserver(aspect->d_func()); // Allow the aspect to do some work now that it is registered aspect->onRegistered(); @@ -295,7 +347,6 @@ void QAspectManager::unregisterAspect(Qt3DCore::QAbstractAspect *aspect) qCDebug(Aspects) << "Unregistering aspect"; Q_ASSERT(aspect); aspect->onUnregistered(); - m_changeArbiter->unregisterSceneObserver(aspect->d_func()); QAbstractAspectPrivate::get(aspect)->m_arbiter = nullptr; QAbstractAspectPrivate::get(aspect)->m_jobManager = nullptr; QAbstractAspectPrivate::get(aspect)->m_aspectManager = nullptr; @@ -323,6 +374,11 @@ QServiceLocator *QAspectManager::serviceLocator() const return m_serviceLocator.data(); } +void QAspectManager::setPostConstructorInit(NodePostConstructorInit *postConstructorInit) +{ + m_postConstructorInit = postConstructorInit; +} + /*! \internal \brief Drives the Qt3D simulation loop in the main thread @@ -377,6 +433,30 @@ void QAspectManager::processFrame() changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); #endif + + // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of + // tree changes + m_postConstructorInit->processNodes(); + + // Add and Remove Nodes + const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges); + for (const NodeTreeChange &change : nodeTreeChanges) { + // Buckets ensure that even if we have intermingled node added / removed + // buckets, we preserve the order of the sequences + + for (QAbstractAspect *aspect : qAsConst(m_aspects)) { + switch (change.type) { + case NodeTreeChange::Added: + aspect->d_func()->createBackendNode(change); + break; + case NodeTreeChange::Removed: + aspect->d_func()->clearBackendNode(change); + break; + } + } + } + + // Sync property updates const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes(); if (dirtyFrontEndNodes.size()) for (QAbstractAspect *aspect : qAsConst(m_aspects)) diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h index e984244ff..38ddbc55d 100644 --- a/src/core/aspects/qaspectmanager_p.h +++ b/src/core/aspects/qaspectmanager_p.h @@ -73,14 +73,15 @@ class QScheduler; class QChangeArbiter; class QAbstractAspect; class QAbstractAspectJobManager; -class QSceneObserverInterface; class QServiceLocator; +class NodePostConstructorInit; +struct NodeTreeChange; class Q_3DCORE_PRIVATE_EXPORT QAspectManager : public QObject { Q_OBJECT public: - explicit QAspectManager(QObject *parent = 0); + explicit QAspectManager(QObject *parent = nullptr); ~QAspectManager(); void setRunMode(QAspectEngine::RunMode mode); @@ -96,6 +97,7 @@ public Q_SLOTS: void setRootEntity(Qt3DCore::QEntity *root, const QVector<QNode *> &nodes); void addNodes(const QVector<QNode *> &nodes); + void removeNodes(const QVector<QNode *> &nodes); void registerAspect(Qt3DCore::QAbstractAspect *aspect); void unregisterAspect(Qt3DCore::QAbstractAspect *aspect); @@ -104,6 +106,7 @@ public: QAbstractAspectJobManager *jobManager() const; QChangeArbiter *changeArbiter() const; QServiceLocator *serviceLocator() const; + void setPostConstructorInit(NodePostConstructorInit *postConstructorInit); private: bool event(QEvent *event) override; @@ -119,6 +122,8 @@ private: bool m_mainLoopRunning; bool m_simulationLoopRunning; QAspectEngine::RunMode m_driveMode; + QVector<NodeTreeChange> m_nodeTreeChanges; + NodePostConstructorInit* m_postConstructorInit; }; diff --git a/src/core/core.pri b/src/core/core.pri index 458a0328d..ea95ab10d 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -5,13 +5,11 @@ HEADERS += \ $$PWD/qtickclock_p.h \ $$PWD/qscheduler_p.h \ $$PWD/corelogging_p.h \ - $$PWD/qsceneobserverinterface_p.h \ $$PWD/qpostman_p.h \ $$PWD/qobservableinterface_p.h \ $$PWD/qobserverinterface_p.h \ $$PWD/qlockableobserverinterface_p.h \ $$PWD/qchangearbiter_p.h \ - $$PWD/qbackendnodefactory_p.h \ $$PWD/qt3dcore_global_p.h \ $$PWD/qscene_p.h \ $$PWD/qpostman_p_p.h @@ -24,7 +22,5 @@ SOURCES += \ $$PWD/qobservableinterface.cpp \ $$PWD/qobserverinterface.cpp \ $$PWD/qlockableobserverinterface.cpp \ - $$PWD/qsceneobserverinterface.cpp \ $$PWD/qpostman.cpp \ - $$PWD/qscene.cpp \ - $$PWD/qbackendnodefactory.cpp + $$PWD/qscene.cpp diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp index 0e9af58dd..a9f4e7a31 100644 --- a/src/core/jobs/qthreadpooler.cpp +++ b/src/core/jobs/qthreadpooler.cpp @@ -183,7 +183,7 @@ int QThreadPooler::currentCount() const { // The caller have to set the mutex - return m_taskCount.load(); + return m_taskCount.loadRelaxed(); } int QThreadPooler::maxThreadCount() const diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp index 4291a4779..091aabfd6 100644 --- a/src/core/jobs/task.cpp +++ b/src/core/jobs/task.cpp @@ -118,7 +118,7 @@ void SyncTaskRunnable::run() m_atomicCount->deref(); // Wait for the other worker threads to be done - while (m_atomicCount->load() > 0) + while (m_atomicCount->loadRelaxed() > 0) QThread::currentThread()->yieldCurrentThread(); if (m_pooler) diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp index 546f1d670..0ff8c4646 100644 --- a/src/core/nodes/qentity.cpp +++ b/src/core/nodes/qentity.cpp @@ -295,13 +295,7 @@ void QEntity::onParentChanged(QObject *) if (!d->m_hasBackendNode) return; - const auto parentID = parentEntity() ? parentEntity()->id() : Qt3DCore::QNodeId(); - auto parentChange = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); - parentChange->setPropertyName("parentEntityUpdated"); - parentChange->setValue(QVariant::fromValue(parentID)); - const bool blocked = blockNotifications(false); - notifyObservers(parentChange); - blockNotifications(blocked); + d->update(); } } // namespace Qt3DCore diff --git a/src/core/nodes/qentity.h b/src/core/nodes/qentity.h index f1a369c48..62398faa1 100644 --- a/src/core/nodes/qentity.h +++ b/src/core/nodes/qentity.h @@ -66,8 +66,8 @@ public: QVector<T *> componentsOfType() const { QVector<T*> matchComponents; - const QComponentVector components = this->components(); - for (QComponent *component : components) { + const QComponentVector comps = this->components(); + for (QComponent *component : comps) { T *typedComponent = qobject_cast<T*>(component); if (typedComponent != nullptr) matchComponents.append(typedComponent); diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index 5f9468124..5c37e337e 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -149,11 +149,8 @@ void QNodePrivate::notifyDestructionChangesAndRemoveFromScene() } // Tell the backend we are about to be destroyed - if (m_hasBackendNode) { - const QDestructionIdAndTypeCollector collector(q); - const auto destroyedChange = QNodeDestroyedChangePtr::create(q, collector.subtreeIdsAndTypes()); - notifyObservers(destroyedChange); - } + if (m_hasBackendNode && m_scene && m_scene->engine()) + QAspectEnginePrivate::get(m_scene->engine())->removeNode(q); // We unset the scene from the node as its backend node was/is about to be destroyed QNodeVisitor visitor; @@ -690,6 +687,11 @@ QNodePrivate *QNodePrivate::get(QNode *q) return q->d_func(); } +const QNodePrivate *QNodePrivate::get(const QNode *q) +{ + return q->d_func(); +} + /*! \internal */ diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index 491059ff9..839751a5e 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -108,6 +108,7 @@ public: QHash<QString, QNode::PropertyTrackingMode> m_trackedPropertiesOverrides; static QNodePrivate *get(QNode *q); + static const QNodePrivate *get(const QNode *q); static void nodePtrDeleter(QNode *q); template<typename Caller, typename NodeType> @@ -194,7 +195,7 @@ public: void removeNode(QNode *node); void addNode(QNode *node); -private Q_SLOTS: +public Q_SLOTS: void processNodes(); private: diff --git a/src/core/qbackendnodefactory.cpp b/src/core/qbackendnodefactory.cpp deleted file mode 100644 index 6fd5b33d1..000000000 --- a/src/core/qbackendnodefactory.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbackendnodefactory_p.h" - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -QBackendNodeFactory::~QBackendNodeFactory() -{ -} - -} // namespace Qt3DCore - -QT_END_NAMESPACE diff --git a/src/core/qbackendnodefactory_p.h b/src/core/qbackendnodefactory_p.h deleted file mode 100644 index 5752205c0..000000000 --- a/src/core/qbackendnodefactory_p.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DCORE_QBACKENDNODEFACTORY_P_H -#define QT3DCORE_QBACKENDNODEFACTORY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DCore/qnodecreatedchange.h> - -#include <Qt3DCore/private/qt3dcore_global_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -class QBackendNode; - -class Q_3DCORE_PRIVATE_EXPORT QBackendNodeFactory -{ -public: - virtual ~QBackendNodeFactory(); - virtual QBackendNode *createBackendNode(const QNodeCreatedChangeBasePtr &change) const = 0; -}; - -} // namespace Qt3DCore - -QT_END_NAMESPACE - -#endif // QT3DCORE_QBACKENDNODEFACTORY_P_H diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp index 34e773f59..60cdc3bd2 100644 --- a/src/core/qchangearbiter.cpp +++ b/src/core/qchangearbiter.cpp @@ -49,7 +49,6 @@ #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> #include <Qt3DCore/private/qpostman_p.h> #include <Qt3DCore/private/qscene_p.h> -#include <Qt3DCore/private/qsceneobserverinterface_p.h> #include <mutex> @@ -117,11 +116,8 @@ void QChangeArbiter::distributeQueueChanges(QChangeQueue *changeQueue) if (change.isNull()) continue; - if (change->type() == NodeCreated) { + if (change->type() == NodeCreated || change->type() == NodeDeleted) { Q_ASSERT(false); // messages no longer used - } else if (change->type() == NodeDeleted) { - for (QSceneObserverInterface *observer : qAsConst(m_sceneObservers)) - observer->sceneNodeRemoved(change); } const QNodeId nodeId = change->subjectId(); @@ -207,13 +203,6 @@ void QChangeArbiter::registerObserver(QObserverInterface *observer, observerList.append(QObserverPair(changeFlags, observer)); } -// Called from the QAspectThread context, no need to lock -void QChangeArbiter::registerSceneObserver(QSceneObserverInterface *observer) -{ - if (!m_sceneObservers.contains(observer)) - m_sceneObservers << observer; -} - void QChangeArbiter::unregisterObserver(QObserverInterface *observer, QNodeId nodeId) { const std::lock_guard<QRecursiveMutex> locker(m_mutex);; @@ -229,13 +218,6 @@ void QChangeArbiter::unregisterObserver(QObserverInterface *observer, QNodeId no } } -// Called from the QAspectThread context, no need to lock -void QChangeArbiter::unregisterSceneObserver(QSceneObserverInterface *observer) -{ - if (observer != nullptr) - m_sceneObservers.removeOne(observer); -} - void QChangeArbiter::sceneChangeEvent(const QSceneChangePtr &e) { // qCDebug(ChangeArbiter) << Q_FUNC_INFO << QThread::currentThread(); diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h index 48fc4ca8c..0a6196756 100644 --- a/src/core/qchangearbiter_p.h +++ b/src/core/qchangearbiter_p.h @@ -104,9 +104,6 @@ public: void unregisterObserver(QObserverInterface *observer, QNodeId nodeId); - void registerSceneObserver(QSceneObserverInterface *observer); - void unregisterSceneObserver(QSceneObserverInterface *observer); - void sceneChangeEvent(const QSceneChangePtr &e) override; // QLockableObserverInterface impl void sceneChangeEventWithLock(const QSceneChangePtr &e) override; // QLockableObserverInterface impl void sceneChangeEventWithLock(const QSceneChangeList &e) override; // QLockableObserverInterface impl @@ -149,7 +146,6 @@ private: // The lists of observers indexed by observable (QNodeId). // m_nodeObservations is for observables in the main thread's object tree QHash<QNodeId, QObserverList> m_nodeObservations; - QList<QSceneObserverInterface *> m_sceneObservers; // Each thread has a TLS ChangeQueue so we never need to lock whilst // receiving a QSceneChange. diff --git a/src/core/qsceneobserverinterface.cpp b/src/core/qsceneobserverinterface.cpp deleted file mode 100644 index 784ff654e..000000000 --- a/src/core/qsceneobserverinterface.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsceneobserverinterface_p.h" - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -QSceneObserverInterface::~QSceneObserverInterface() -{ -} - -} // Qt3D - -QT_END_NAMESPACE diff --git a/src/core/qsceneobserverinterface_p.h b/src/core/qsceneobserverinterface_p.h deleted file mode 100644 index db6c68b73..000000000 --- a/src/core/qsceneobserverinterface_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DCORE_QSCENEOBSERVERINTERFACE_P_H -#define QT3DCORE_QSCENEOBSERVERINTERFACE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DCore/qscenechange.h> - -#include <Qt3DCore/private/qt3dcore_global_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -class QChangeArbiter; - -class Q_3DCORE_PRIVATE_EXPORT QSceneObserverInterface -{ -public: - virtual ~QSceneObserverInterface(); - -private: - virtual void sceneNodeRemoved(QSceneChangePtr &e) = 0; - - friend class QChangeArbiter; -}; - -} // Qt3D - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(Qt3DCore::QSceneObserverInterface *) // LCOV_EXCL_LINE - -#endif // QT3DCORE_QSCENEOBSERVERINTERFACE_P_H diff --git a/src/core/transforms/matrix4x4_avx2_p.h b/src/core/transforms/matrix4x4_avx2_p.h index 74e7c911c..63858b35c 100644 --- a/src/core/transforms/matrix4x4_avx2_p.h +++ b/src/core/transforms/matrix4x4_avx2_p.h @@ -473,15 +473,13 @@ public: Vector3D_SSE mapVector(const Vector3D_SSE &vector) const { - const __m128 row1 = _mm_set_ps(0.0f, m13(), m12(), m11()); - const __m128 row2 = _mm_set_ps(0.0f, m23(), m22(), m21()); - const __m128 row3 = _mm_set_ps(0.0f, m33(), m32(), m31()); + const Vector3D_SSE row1(m11(), m12(), m13()); + const Vector3D_SSE row2(m21(), m22(), m23()); + const Vector3D_SSE row3(m31(), m32(), m33()); - const __m128 tmp = _mm_add_ps(_mm_mul_ps(vector.m_xyzw, row1), _mm_mul_ps(vector.m_xyzw, row2)); - - Vector3D_SSE v(Qt::Uninitialized); - v.m_xyzw = _mm_add_ps(tmp, _mm_mul_ps(vector.m_xyzw, row3)); - return v; + return Vector3D(Vector3D_SSE::dotProduct(row1, vector), + Vector3D_SSE::dotProduct(row2, vector), + Vector3D_SSE::dotProduct(row3, vector)); } friend Vector4D operator*(const Vector4D &vector, const Matrix4x4_AVX2 &matrix); diff --git a/src/core/transforms/matrix4x4_sse_p.h b/src/core/transforms/matrix4x4_sse_p.h index 287094be5..0ea2e37ad 100644 --- a/src/core/transforms/matrix4x4_sse_p.h +++ b/src/core/transforms/matrix4x4_sse_p.h @@ -356,15 +356,13 @@ public: Q_ALWAYS_INLINE Vector3D_SSE mapVector(const Vector3D_SSE &vector) const { - const __m128 row1 = _mm_set_ps(0.0f, m13(), m12(), m11()); - const __m128 row2 = _mm_set_ps(0.0f, m23(), m22(), m21()); - const __m128 row3 = _mm_set_ps(0.0f, m33(), m32(), m31()); + const Vector3D_SSE row1(m11(), m12(), m13()); + const Vector3D_SSE row2(m21(), m22(), m23()); + const Vector3D_SSE row3(m31(), m32(), m33()); - const __m128 tmp = _mm_add_ps(_mm_mul_ps(vector.m_xyzw, row1), _mm_mul_ps(vector.m_xyzw, row2)); - - Vector3D_SSE v(Qt::Uninitialized); - v.m_xyzw = _mm_add_ps(tmp, _mm_mul_ps(vector.m_xyzw, row3)); - return v; + return Vector3D(Vector3D_SSE::dotProduct(row1, vector), + Vector3D_SSE::dotProduct(row2, vector), + Vector3D_SSE::dotProduct(row3, vector)); } friend Q_ALWAYS_INLINE Vector4D operator*(const Vector4D &vector, const Matrix4x4_SSE &matrix); diff --git a/src/core/transforms/qjoint.cpp b/src/core/transforms/qjoint.cpp index 017773ff6..553fbd654 100644 --- a/src/core/transforms/qjoint.cpp +++ b/src/core/transforms/qjoint.cpp @@ -352,11 +352,8 @@ void QJoint::addChildJoint(QJoint *joint) // Ensures proper bookkeeping d->registerDestructionHelper(joint, &QJoint::removeChildJoint, d->m_childJoints); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), joint); - change->setPropertyName("childJoint"); - d->notifyObservers(change); - } + if (d->m_changeArbiter != nullptr) + d->update(); } } @@ -369,11 +366,8 @@ void QJoint::removeChildJoint(QJoint *joint) Q_D(QJoint); if (d->m_childJoints.contains(joint)) { - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), joint); - change->setPropertyName("childJoint"); - d->notifyObservers(change); - } + if (d->m_changeArbiter != nullptr) + d->update(); d->m_childJoints.removeOne(joint); diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp index bedf108f2..e5902f11f 100644 --- a/src/core/transforms/qtransform.cpp +++ b/src/core/transforms/qtransform.cpp @@ -239,12 +239,13 @@ QTransform::QTransform(QTransformPrivate &dd, QNode *parent) */ void QTransform::sceneChangeEvent(const QSceneChangePtr &change) { + Q_D(QTransform); switch (change->type()) { case PropertyUpdated: { Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); if (propertyChange->propertyName() == QByteArrayLiteral("worldMatrix")) { const bool blocked = blockNotifications(true); - setWorldMatrix(propertyChange->value().value<QMatrix4x4>()); + d->setWorldMatrix(propertyChange->value().value<QMatrix4x4>()); blockNotifications(blocked); } break; @@ -254,13 +255,13 @@ void QTransform::sceneChangeEvent(const QSceneChangePtr &change) } } -void QTransform::setWorldMatrix(const QMatrix4x4 &worldMatrix) +void QTransformPrivate::setWorldMatrix(const QMatrix4x4 &worldMatrix) { - Q_D(QTransform); - if (d->m_worldMatrix == worldMatrix) + Q_Q(QTransform); + if (m_worldMatrix == worldMatrix) return; - d->m_worldMatrix = worldMatrix; - emit worldMatrixChanged(worldMatrix); + m_worldMatrix = worldMatrix; + emit q->worldMatrixChanged(worldMatrix); } void QTransform::setMatrix(const QMatrix4x4 &m) diff --git a/src/core/transforms/qtransform.h b/src/core/transforms/qtransform.h index 527760df7..503ea4d4a 100644 --- a/src/core/transforms/qtransform.h +++ b/src/core/transforms/qtransform.h @@ -120,7 +120,6 @@ Q_SIGNALS: protected: explicit QTransform(QTransformPrivate &dd, QNode *parent = nullptr); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; - void setWorldMatrix(const QMatrix4x4 &worldMatrix); private: Q_DECLARE_PRIVATE(QTransform) diff --git a/src/core/transforms/qtransform_p.h b/src/core/transforms/qtransform_p.h index d44e5e157..028a9aba7 100644 --- a/src/core/transforms/qtransform_p.h +++ b/src/core/transforms/qtransform_p.h @@ -77,6 +77,8 @@ public: mutable bool m_matrixDirty; QMatrix4x4 m_worldMatrix; + + void setWorldMatrix(const QMatrix4x4 &worldMatrix); }; struct QTransformData |