/**************************************************************************** ** ** 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 "qscene_p.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3DCore { class QScenePrivate { public: QScenePrivate(QAspectEngine *engine) : m_engine(engine) , m_arbiter(nullptr) , m_postConstructorInit(new NodePostConstructorInit) , m_rootNode(nullptr) { } QAspectEngine *m_engine; QHash m_nodeLookupTable; QMultiHash m_componentToEntities; QMultiHash m_observablesLookupTable; QHash m_observableToUuid; QHash m_nodePropertyTrackModeLookupTable; QAbstractArbiter *m_arbiter; QScopedPointer m_postConstructorInit; mutable QReadWriteLock m_lock; mutable QReadWriteLock m_nodePropertyTrackModeLock; QNode *m_rootNode; }; QScene::QScene(QAspectEngine *engine) : d_ptr(new QScenePrivate(engine)) { } QScene::~QScene() { } QAspectEngine *QScene::engine() const { Q_D(const QScene); return d->m_engine; } // Called by any thread void QScene::addObservable(QObservableInterface *observable, QNodeId id) { Q_D(QScene); QWriteLocker lock(&d->m_lock); d->m_observablesLookupTable.insert(id, observable); d->m_observableToUuid.insert(observable, id); if (d->m_arbiter != nullptr) observable->setArbiter(d->m_arbiter); } // Called by main thread only void QScene::addObservable(QNode *observable) { Q_D(QScene); if (observable != nullptr) { QWriteLocker lock(&d->m_lock); d->m_nodeLookupTable.insert(observable->id(), observable); if (d->m_arbiter != nullptr) observable->d_func()->setArbiter(d->m_arbiter); } } // Called by any thread void QScene::removeObservable(QObservableInterface *observable, QNodeId id) { Q_D(QScene); QWriteLocker lock(&d->m_lock); d->m_observablesLookupTable.remove(id, observable); d->m_observableToUuid.remove(observable); observable->setArbiter(nullptr); } // Called by main thread void QScene::removeObservable(QNode *observable) { Q_D(QScene); if (observable != nullptr) { QWriteLocker lock(&d->m_lock); QNodeId nodeUuid = observable->id(); const auto p = d->m_observablesLookupTable.equal_range(nodeUuid); // must be non-const equal_range to ensure p.second stays valid auto it = p.first; while (it != p.second) { it.value()->setArbiter(nullptr); d->m_observableToUuid.remove(it.value()); it = d->m_observablesLookupTable.erase(it); } d->m_nodeLookupTable.remove(nodeUuid); observable->d_func()->setArbiter(nullptr); } } // Called by any thread QObservableList QScene::lookupObservables(QNodeId id) const { Q_D(const QScene); QReadLocker lock(&d->m_lock); return d->m_observablesLookupTable.values(id); } // Called by any thread QNode *QScene::lookupNode(QNodeId id) const { Q_D(const QScene); QReadLocker lock(&d->m_lock); return d->m_nodeLookupTable.value(id); } QVector QScene::lookupNodes(const QVector &ids) const { Q_D(const QScene); QReadLocker lock(&d->m_lock); QVector nodes(ids.size()); int index = 0; for (QNodeId id : ids) nodes[index++] = d->m_nodeLookupTable.value(id); return nodes; } QNodeId QScene::nodeIdFromObservable(QObservableInterface *observable) const { Q_D(const QScene); QReadLocker lock(&d->m_lock); return d->m_observableToUuid.value(observable); } QNode *QScene::rootNode() const { Q_D(const QScene); return d->m_rootNode; } void QScene::setArbiter(QAbstractArbiter *arbiter) { Q_D(QScene); d->m_arbiter = arbiter; } QAbstractArbiter *QScene::arbiter() const { Q_D(const QScene); return d->m_arbiter; } QVector QScene::entitiesForComponent(QNodeId id) const { Q_D(const QScene); QReadLocker lock(&d->m_lock); QVector result; const auto p = d->m_componentToEntities.equal_range(id); for (auto it = p.first; it != p.second; ++it) result.push_back(*it); return result; } void QScene::addEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) { Q_D(QScene); QWriteLocker lock(&d->m_lock); d->m_componentToEntities.insert(componentUuid, entityUuid); } void QScene::removeEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) { Q_D(QScene); QWriteLocker lock(&d->m_lock); d->m_componentToEntities.remove(componentUuid, entityUuid); } bool QScene::hasEntityForComponent(QNodeId componentUuid, QNodeId entityUuid) { Q_D(QScene); QReadLocker lock(&d->m_lock); const auto range = d->m_componentToEntities.equal_range(componentUuid); return std::find(range.first, range.second, entityUuid) != range.second; } QScene::NodePropertyTrackData QScene::lookupNodePropertyTrackData(QNodeId id) const { Q_D(const QScene); QReadLocker lock(&d->m_nodePropertyTrackModeLock); return d->m_nodePropertyTrackModeLookupTable.value(id); } void QScene::setPropertyTrackDataForNode(QNodeId nodeId, const QScene::NodePropertyTrackData &data) { Q_D(QScene); QWriteLocker lock(&d->m_nodePropertyTrackModeLock); d->m_nodePropertyTrackModeLookupTable.insert(nodeId, data); } void QScene::removePropertyTrackDataForNode(QNodeId nodeId) { Q_D(QScene); QWriteLocker lock(&d->m_nodePropertyTrackModeLock); d->m_nodePropertyTrackModeLookupTable.remove(nodeId); } NodePostConstructorInit *QScene::postConstructorInit() const { Q_D(const QScene); return d->m_postConstructorInit.get(); } void QScene::setRootNode(QNode *root) { Q_D(QScene); d->m_rootNode = root; } } // Qt3D QT_END_NAMESPACE