diff options
author | Mike Krus <mike.krus@kdab.com> | 2018-01-30 22:13:14 +0000 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2018-02-05 09:12:47 +0000 |
commit | c8a48a9a28889598cb2a06fc8d5deb9b803509ca (patch) | |
tree | 686fb006c636a0a7ea5fe1ba78457aa02fd6f8b6 /src | |
parent | ba8e3dc09a772faaeb08aa652e59c49cf175040e (diff) |
Add support for layers to control ray casting
RayCaster and ScreenRayCaster can have a number of layers which are
used to control how entities with the matching layers are handled
for ray casting. Similar rules apply as for LayerFilter in the frame
graph.
Change-Id: I9f666563a686ac99d7f178da33a539ba9edef51b
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick3d/quick3drender/items/quick3draycaster.cpp | 42 | ||||
-rw-r--r-- | src/quick3d/quick3drender/items/quick3draycaster_p.h | 2 | ||||
-rw-r--r-- | src/quick3d/quick3drender/items/quick3draycaster_p_p.h | 4 | ||||
-rw-r--r-- | src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp | 9 | ||||
-rw-r--r-- | src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h | 2 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob.cpp | 2 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils.cpp | 106 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils_p.h | 7 | ||||
-rw-r--r-- | src/render/jobs/raycastingjob.cpp | 3 | ||||
-rw-r--r-- | src/render/picking/qabstractraycaster.cpp | 65 | ||||
-rw-r--r-- | src/render/picking/qabstractraycaster.h | 22 | ||||
-rw-r--r-- | src/render/picking/qabstractraycaster_p.h | 10 | ||||
-rw-r--r-- | src/render/picking/raycaster.cpp | 49 | ||||
-rw-r--r-- | src/render/picking/raycaster_p.h | 7 |
14 files changed, 309 insertions, 21 deletions
diff --git a/src/quick3d/quick3drender/items/quick3draycaster.cpp b/src/quick3d/quick3drender/items/quick3draycaster.cpp index fa05b67d6..55c08a806 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster.cpp +++ b/src/quick3d/quick3drender/items/quick3draycaster.cpp @@ -115,6 +115,39 @@ QJSValue Quick3DRayCasterPrivate::convertHits(const QAbstractRayCaster::Hits &hi return jsHits; } +void Quick3DRayCasterPrivate::appendLayer(QQmlListProperty<QLayer> *list, QLayer *layer) +{ + QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); + if (filter) + filter->addLayer(layer); +} + +QLayer *Quick3DRayCasterPrivate::layerAt(QQmlListProperty<QLayer> *list, int index) +{ + QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); + if (filter) + return filter->layers().at(index); + return nullptr; +} + +int Quick3DRayCasterPrivate::layerCount(QQmlListProperty<QLayer> *list) +{ + QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); + if (filter) + return filter->layers().count(); + return 0; +} + +void Quick3DRayCasterPrivate::clearLayers(QQmlListProperty<QLayer> *list) +{ + QAbstractRayCaster *filter = qobject_cast<QAbstractRayCaster *>(list->object); + if (filter) { + const auto layers = filter->layers(); + for (QLayer *layer : layers) + filter->removeLayer(layer); + } +} + Quick3DRayCaster::Quick3DRayCaster(QObject *parent) : QRayCaster(*new Quick3DRayCasterPrivate(), qobject_cast<Qt3DCore::QNode *>(parent)) { @@ -126,6 +159,15 @@ QJSValue Quick3DRayCaster::hits() const return d->m_jsHits; } +QQmlListProperty<Qt3DRender::QLayer> Qt3DRender::Render::Quick::Quick3DRayCaster::qmlLayers() +{ + return QQmlListProperty<QLayer>(this, 0, + &Quick3DRayCasterPrivate::appendLayer, + &Quick3DRayCasterPrivate::layerCount, + &Quick3DRayCasterPrivate::layerAt, + &Quick3DRayCasterPrivate::clearLayers); +} + } // namespace Quick } // namespace Render } // namespace Qt3DRender diff --git a/src/quick3d/quick3drender/items/quick3draycaster_p.h b/src/quick3d/quick3drender/items/quick3draycaster_p.h index 682cee7f7..9be11f534 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster_p.h +++ b/src/quick3d/quick3drender/items/quick3draycaster_p.h @@ -70,10 +70,12 @@ class QT3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DRayCaster : public QRayCaster { Q_OBJECT Q_PROPERTY(QJSValue hits READ hits NOTIFY hitsChanged) + Q_PROPERTY(QQmlListProperty<Qt3DRender::QLayer> layers READ qmlLayers) public: explicit Quick3DRayCaster(QObject *parent = 0); QJSValue hits() const; + QQmlListProperty<QLayer> qmlLayers(); Q_SIGNALS: void hitsChanged(const QJSValue &hits); diff --git a/src/quick3d/quick3drender/items/quick3draycaster_p_p.h b/src/quick3d/quick3drender/items/quick3draycaster_p_p.h index d1bef5be3..0098634bc 100644 --- a/src/quick3d/quick3drender/items/quick3draycaster_p_p.h +++ b/src/quick3d/quick3drender/items/quick3draycaster_p_p.h @@ -75,6 +75,10 @@ public: void dispatchHits(const QAbstractRayCaster::Hits &hits) override; static QJSValue convertHits(const QAbstractRayCaster::Hits &hits, QQmlEngine *engine); + static void appendLayer(QQmlListProperty<QLayer> *list, QLayer *bar); + static QLayer *layerAt(QQmlListProperty<QLayer> *list, int index); + static int layerCount(QQmlListProperty<QLayer> *list); + static void clearLayers(QQmlListProperty<QLayer> *list); Q_DECLARE_PUBLIC(Quick3DRayCaster) }; diff --git a/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp b/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp index 629acf0f3..dd3d1f758 100644 --- a/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp +++ b/src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp @@ -77,6 +77,15 @@ QJSValue Quick3DScreenRayCaster::hits() const return d->m_jsHits; } +QQmlListProperty<Qt3DRender::QLayer> Qt3DRender::Render::Quick::Quick3DScreenRayCaster::qmlLayers() +{ + return QQmlListProperty<QLayer>(this, 0, + &Quick3DRayCasterPrivate::appendLayer, + &Quick3DRayCasterPrivate::layerCount, + &Quick3DRayCasterPrivate::layerAt, + &Quick3DRayCasterPrivate::clearLayers); +} + } // namespace Quick } // namespace Render } // namespace Qt3DRender diff --git a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h index 5d9b157cd..b337163c5 100644 --- a/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h +++ b/src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h @@ -70,10 +70,12 @@ class QT3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DScreenRayCaster : public QScre { Q_OBJECT Q_PROPERTY(QJSValue hits READ hits NOTIFY hitsChanged) + Q_PROPERTY(QQmlListProperty<Qt3DRender::QLayer> layers READ qmlLayers) public: explicit Quick3DScreenRayCaster(QObject *parent = 0); QJSValue hits() const; + QQmlListProperty<QLayer> qmlLayers(); Q_SIGNALS: void hitsChanged(const QJSValue &hits); diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index f75e47839..1805f6d43 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -225,7 +225,7 @@ bool PickBoundingVolumeJob::runHelper() QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); PickingUtils::HierarchicalEntityPicker entityPicker(ray); - if (entityPicker.collectHits(m_node)) { + if (entityPicker.collectHits(m_manager, m_node)) { if (trianglePickingRequested) { PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; gathererFunctor.m_frontFaceRequested = frontFaceRequested; diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index 719dcc6b7..ba88e5691 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/private/trianglesvisitor_p.h> #include <Qt3DRender/private/segmentsvisitor_p.h> #include <Qt3DRender/private/pointsvisitor_p.h> +#include <Qt3DRender/private/layer_p.h> #include <vector> @@ -560,40 +561,125 @@ HitList PointCollisionGathererFunctor::pick(const Entity *entity) const HierarchicalEntityPicker::HierarchicalEntityPicker(const QRay3D &ray, bool requireObjectPicker) : m_ray(ray) , m_objectPickersRequired(requireObjectPicker) + , m_filterMode(QAbstractRayCaster::AcceptAnyMatchingLayers) { } -bool HierarchicalEntityPicker::collectHits(Entity *root) +void HierarchicalEntityPicker::setFilterLayers(const Qt3DCore::QNodeIdVector &layerIds, QAbstractRayCaster::FilterMode mode) +{ + m_filterMode = mode; + m_layerIds = layerIds; + std::sort(m_layerIds.begin(), m_layerIds.end()); +} + +bool HierarchicalEntityPicker::collectHits(NodeManagers *manager, Entity *root) { m_hits.clear(); m_entities.clear(); QRayCastingService rayCasting; - std::vector<std::pair<Entity *, bool>> worklist; - worklist.push_back({root, !root->componentHandle<ObjectPicker>().isNull()}); + struct EntityData { + Entity* entity; + bool hasObjectPicker; + Qt3DCore::QNodeIdVector recursiveLayers; + }; + std::vector<EntityData> worklist; + worklist.push_back({root, !root->componentHandle<ObjectPicker>().isNull(), {}}); + + LayerManager *layerManager = manager->layerManager(); while (!worklist.empty()) { - auto current = worklist.back(); + EntityData current = worklist.back(); worklist.pop_back(); + if (m_layerIds.size()) { + // TODO investigate reusing logic from LayerFilter job + bool accepted = false; + Qt3DCore::QNodeIdVector filterLayers = current.recursiveLayers + current.entity->componentsUuid<Layer>(); + + // remove disabled layers + filterLayers.erase(std::remove_if(filterLayers.begin(), filterLayers.end(), + [layerManager](const Qt3DCore::QNodeId layerId) { + Layer *layer = layerManager->lookupResource(layerId); + return !layer || !layer->isEnabled(); + }), filterLayers.end()); + + switch (m_filterMode) { + case QAbstractRayCaster::AcceptAnyMatchingLayers: { + for (auto id: qAsConst(filterLayers)) { + if (m_layerIds.contains(id)) { + accepted = true; + break; + } + } + break; + } + case QAbstractRayCaster::AcceptAllMatchingLayers: { + accepted = true; + for (auto id: qAsConst(filterLayers)) { + if (!m_layerIds.contains(id)) { + accepted = false; + break; + } + } + break; + } + case QAbstractRayCaster::DiscardAnyMatchingLayers: { + accepted = true; + for (auto id: qAsConst(filterLayers)) { + if (m_layerIds.contains(id)) { + accepted = false; + break; + } + } + break; + } + case QAbstractRayCaster::DiscardAllMatchingLayers: { + accepted = false; + for (auto id: qAsConst(filterLayers)) { + if (!m_layerIds.contains(id)) { + accepted = true; + break; + } + } + break; + } + default: + Q_UNREACHABLE(); + break; + } + + if (!accepted) + continue; + } + // first pick entry sub-scene-graph QCollisionQueryResult::Hit queryResult = - rayCasting.query(m_ray, current.first->worldBoundingVolumeWithChildren()); + rayCasting.query(m_ray, current.entity->worldBoundingVolumeWithChildren()); if (queryResult.m_distance < 0.f) continue; // if we get a hit, we check again for this specific entity - queryResult = rayCasting.query(m_ray, current.first->worldBoundingVolume()); - if (queryResult.m_distance >= 0.f && (current.second || !m_objectPickersRequired)) { - m_entities.push_back(current.first); + queryResult = rayCasting.query(m_ray, current.entity->worldBoundingVolume()); + if (queryResult.m_distance >= 0.f && (current.hasObjectPicker || !m_objectPickersRequired)) { + m_entities.push_back(current.entity); m_hits.push_back(queryResult); } + Qt3DCore::QNodeIdVector recursiveLayers; + const Qt3DCore::QNodeIdVector entityLayers = current.entity->componentsUuid<Layer>(); + for (const Qt3DCore::QNodeId layerId : entityLayers) { + Layer *layer = layerManager->lookupResource(layerId); + if (layer->recursive()) + recursiveLayers << layerId; + } + // and pick children - const auto children = current.first->children(); + const auto children = current.entity->children(); for (auto child: children) - worklist.push_back({child, current.second || !child->componentHandle<ObjectPicker>().isNull()}); + worklist.push_back({child, current.hasObjectPicker || !child->componentHandle<ObjectPicker>().isNull(), + current.recursiveLayers + recursiveLayers}); } return !m_hits.empty(); diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h index 9eed0bc69..47ab6c3bd 100644 --- a/src/render/jobs/pickboundingvolumeutils_p.h +++ b/src/render/jobs/pickboundingvolumeutils_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/QNodeId> +#include <Qt3DRender/QAbstractRayCaster> #include <Qt3DRender/private/qray3d_p.h> #include <Qt3DRender/private/qraycastingservice_p.h> @@ -115,7 +116,9 @@ class Q_AUTOTEST_EXPORT HierarchicalEntityPicker public: explicit HierarchicalEntityPicker(const RayCasting::QRay3D &ray, bool requireObjectPicker = true); - bool collectHits(Entity *root); + void setFilterLayers(const Qt3DCore::QNodeIdVector &layerIds, QAbstractRayCaster::FilterMode mode); + + bool collectHits(NodeManagers *manager, Entity *root); inline HitList hits() const { return m_hits; } inline QVector<Entity *> entities() const { return m_entities; } @@ -124,6 +127,8 @@ private: HitList m_hits; QVector<Entity *> m_entities; bool m_objectPickersRequired; + Qt3DCore::QNodeIdVector m_layerIds; + QAbstractRayCaster::FilterMode m_filterMode; }; struct Q_AUTOTEST_EXPORT AbstractCollisionGathererFunctor diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index 3a44cd113..c9fe5cac0 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -169,7 +169,8 @@ bool RayCastingJob::runHelper() for (const QRay3D &ray: qAsConst(rays)) { PickingUtils::HitList sphereHits; PickingUtils::HierarchicalEntityPicker entityPicker(ray, false); - if (entityPicker.collectHits(m_node)) { + entityPicker.setFilterLayers(pair.second->layerIds(), pair.second->filterMode()); + if (entityPicker.collectHits(m_manager, m_node)) { if (trianglePickingRequested) { PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; gathererFunctor.m_frontFaceRequested = frontFaceRequested; diff --git a/src/render/picking/qabstractraycaster.cpp b/src/render/picking/qabstractraycaster.cpp index 5f29b1956..e08bea3ca 100644 --- a/src/render/picking/qabstractraycaster.cpp +++ b/src/render/picking/qabstractraycaster.cpp @@ -41,8 +41,11 @@ #include "qabstractraycaster_p.h" #include <Qt3DCore/qentity.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qpropertynodeaddedchange.h> +#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> +#include <Qt3DRender/qlayer.h> QT_BEGIN_NAMESPACE @@ -111,12 +114,72 @@ void QAbstractRayCaster::setRunMode(QAbstractRayCaster::RunMode runMode) } } +QAbstractRayCaster::FilterMode QAbstractRayCaster::filterMode() const +{ + Q_D(const QAbstractRayCaster); + return d->m_filterMode; +} + +void QAbstractRayCaster::setFilterMode(QAbstractRayCaster::FilterMode filterMode) +{ + Q_D(QAbstractRayCaster); + if (d->m_filterMode != filterMode) { + d->m_filterMode = filterMode; + emit filterModeChanged(d->m_filterMode); + } +} + QAbstractRayCaster::Hits QAbstractRayCaster::hits() const { Q_D(const QAbstractRayCaster); return d->m_hits; } +void QAbstractRayCaster::addLayer(QLayer *layer) +{ + Q_ASSERT(layer); + Q_D(QAbstractRayCaster); + if (!d->m_layers.contains(layer)) { + d->m_layers.append(layer); + + // Ensures proper bookkeeping + d->registerDestructionHelper(layer, &QAbstractRayCaster::removeLayer, d->m_layers); + + // We need to add it as a child of the current node if it has been declared inline + // Or not previously added as a child of the current node so that + // 1) The backend gets notified about it's creation + // 2) When the current node is destroyed, it gets destroyed as well + if (!layer->parent()) + layer->setParent(this); + + if (d->m_changeArbiter != nullptr) { + const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), layer); + change->setPropertyName("layer"); + d->notifyObservers(change); + } + } +} + +void QAbstractRayCaster::removeLayer(QLayer *layer) +{ + Q_ASSERT(layer); + Q_D(QAbstractRayCaster); + if (d->m_changeArbiter != nullptr) { + const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), layer); + change->setPropertyName("layer"); + d->notifyObservers(change); + } + d->m_layers.removeOne(layer); + // Remove bookkeeping connection + d->unregisterDestructionHelper(layer); +} + +QVector<QLayer *> QAbstractRayCaster::layers() const +{ + Q_D(const QAbstractRayCaster); + return d->m_layers; +} + /*! \internal */ void QAbstractRayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) { @@ -145,6 +208,8 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractRayCaster::createNodeCreationChange data.direction = d->m_direction; data.length = d->m_length; data.position = d->m_position; + data.filterMode = d->m_filterMode; + data.layerIds = qIdsForNodes(d->m_layers); return creationChange; } diff --git a/src/render/picking/qabstractraycaster.h b/src/render/picking/qabstractraycaster.h index 3d6357ce8..c706a7bd2 100644 --- a/src/render/picking/qabstractraycaster.h +++ b/src/render/picking/qabstractraycaster.h @@ -51,13 +51,14 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { class QAbstractRayCasterPrivate; +class QLayer; class QT3DRENDERSHARED_EXPORT QAbstractRayCaster : public Qt3DCore::QComponent { Q_OBJECT Q_PROPERTY(RunMode runMode READ runMode WRITE setRunMode NOTIFY runModeChanged) + Q_PROPERTY(FilterMode filterMode READ filterMode WRITE setFilterMode NOTIFY filterModeChanged) Q_PROPERTY(Hits hits READ hits NOTIFY hitsChanged) - public: enum RunMode { Continuous, @@ -65,20 +66,35 @@ public: }; Q_ENUM(RunMode) + enum FilterMode { + AcceptAnyMatchingLayers = 0, + AcceptAllMatchingLayers, + DiscardAnyMatchingLayers, + DiscardAllMatchingLayers, + }; + Q_ENUM(FilterMode) // LOVC_EXLC_LINE + using Hits = QVector<QRayCasterHit>; explicit QAbstractRayCaster(QNode *parent = nullptr); ~QAbstractRayCaster(); RunMode runMode() const; + FilterMode filterMode() const; Hits hits() const; + void addLayer(QLayer *layer); + void removeLayer(QLayer *layer); + QVector<QLayer *> layers() const; + public Q_SLOTS: void setRunMode(RunMode runMode); + void setFilterMode(FilterMode filterMode); Q_SIGNALS: - void runModeChanged(RunMode runMode); - void hitsChanged(const Hits &hits); + void runModeChanged(Qt3DRender::QAbstractRayCaster::RunMode runMode); + void hitsChanged(const Qt3DRender::QAbstractRayCaster::Hits &hits); + void filterModeChanged(Qt3DRender::QAbstractRayCaster::FilterMode filterMode); protected: explicit QAbstractRayCaster(QAbstractRayCasterPrivate &dd, QNode *parent = nullptr); diff --git a/src/render/picking/qabstractraycaster_p.h b/src/render/picking/qabstractraycaster_p.h index cca95b4d6..2c4006e70 100644 --- a/src/render/picking/qabstractraycaster_p.h +++ b/src/render/picking/qabstractraycaster_p.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +class QLayer; + /*! \internal */ @@ -82,7 +84,9 @@ public: QPoint m_position; QVector3D m_origin; QVector3D m_direction = QVector3D(0., 0., 1.f); - float m_length = 0.f; + float m_length = 1.f; + QAbstractRayCaster::FilterMode m_filterMode = QAbstractRayCaster::AcceptAnyMatchingLayers; + QVector<QLayer*> m_layers; virtual void dispatchHits(const QAbstractRayCaster::Hits &hits); @@ -96,7 +100,9 @@ struct QAbstractRayCasterData QPoint position; QVector3D origin; QVector3D direction; - float length = 0.f; + float length = 1.f; + QAbstractRayCaster::FilterMode filterMode; + Qt3DCore::QNodeIdVector layerIds; }; } // namespace Qt3DRender diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp index f203a9d53..d62bdab09 100644 --- a/src/render/picking/raycaster.cpp +++ b/src/render/picking/raycaster.cpp @@ -43,11 +43,14 @@ #include <Qt3DRender/qabstractraycaster.h> #include <Qt3DRender/private/qabstractraycaster_p.h> #include <Qt3DRender/private/raycastingjob_p.h> -#include <Qt3DRender/qattribute.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qpropertynodeaddedchange.h> +#include <Qt3DCore/qpropertynoderemovedchange.h> QT_BEGIN_NAMESPACE +using namespace Qt3DCore; + namespace Qt3DRender { namespace Render { @@ -92,6 +95,16 @@ QPoint RayCaster::position() const return m_position; } +Qt3DCore::QNodeIdVector RayCaster::layerIds() const +{ + return m_layerIds; +} + +QAbstractRayCaster::FilterMode RayCaster::filterMode() const +{ + return m_filterMode; +} + void RayCaster::cleanup() { BackendNode::setEnabled(false); @@ -101,6 +114,8 @@ void RayCaster::cleanup() m_origin = {}; m_length = 0.f; m_position = {}; + m_filterMode = QAbstractRayCaster::AcceptAllMatchingLayers; + m_layerIds.clear(); notifyJob(); } @@ -114,11 +129,34 @@ void RayCaster::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &ch m_direction = data.direction; m_length = data.length; m_position = data.position; + m_filterMode = data.filterMode; + m_layerIds = data.layerIds; } void RayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { - if (e->type() == Qt3DCore::PropertyUpdated) { + switch (e->type()) { + case PropertyValueAdded: { + const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); + if (change->propertyName() == QByteArrayLiteral("layer")) { + m_layerIds.append(change->addedNodeId()); + markDirty(AbstractRenderer::LayersDirty); + notifyJob(); + } + break; + } + + case PropertyValueRemoved: { + const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); + if (change->propertyName() == QByteArrayLiteral("layer")) { + m_layerIds.removeOne(change->removedNodeId()); + markDirty(AbstractRenderer::LayersDirty); + notifyJob(); + } + break; + } + + case PropertyUpdated: { const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); if (propertyChange->propertyName() == QByteArrayLiteral("origin")) { @@ -131,10 +169,17 @@ void RayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) m_position = propertyChange->value().toPoint(); } else if (propertyChange->propertyName() == QByteArrayLiteral("runMode")) { m_runMode = propertyChange->value().value<QAbstractRayCaster::RunMode>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("filterMode")) { + m_filterMode = propertyChange->value().value<QAbstractRayCaster::FilterMode>(); } notifyJob(); markDirty(AbstractRenderer::AllDirty); + break; + } + + default: + break; } BackendNode::sceneChangeEvent(e); diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h index ff577a565..6fe6ee322 100644 --- a/src/render/picking/raycaster_p.h +++ b/src/render/picking/raycaster_p.h @@ -77,6 +77,9 @@ public: float length() const; QPoint position() const; + Qt3DCore::QNodeIdVector layerIds() const; + QAbstractRayCaster::FilterMode filterMode() const; + void cleanup(); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; @@ -90,8 +93,10 @@ private: QAbstractRayCaster::RunMode m_runMode = QAbstractRayCaster::SingleShot; QVector3D m_origin; QVector3D m_direction = {0.f, 0.f, 1.f}; - float m_length = 0.f; + float m_length = 1.f; QPoint m_position; + Qt3DCore::QNodeIdVector m_layerIds; + QAbstractRayCaster::FilterMode m_filterMode = QAbstractRayCaster::AcceptAnyMatchingLayers; }; } // Render |