summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2018-01-30 22:13:14 +0000
committerSean Harmer <sean.harmer@kdab.com>2018-02-05 09:12:47 +0000
commitc8a48a9a28889598cb2a06fc8d5deb9b803509ca (patch)
tree686fb006c636a0a7ea5fe1ba78457aa02fd6f8b6 /src
parentba8e3dc09a772faaeb08aa652e59c49cf175040e (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.cpp42
-rw-r--r--src/quick3d/quick3drender/items/quick3draycaster_p.h2
-rw-r--r--src/quick3d/quick3drender/items/quick3draycaster_p_p.h4
-rw-r--r--src/quick3d/quick3drender/items/quick3dscreenraycaster.cpp9
-rw-r--r--src/quick3d/quick3drender/items/quick3dscreenraycaster_p.h2
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp2
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp106
-rw-r--r--src/render/jobs/pickboundingvolumeutils_p.h7
-rw-r--r--src/render/jobs/raycastingjob.cpp3
-rw-r--r--src/render/picking/qabstractraycaster.cpp65
-rw-r--r--src/render/picking/qabstractraycaster.h22
-rw-r--r--src/render/picking/qabstractraycaster_p.h10
-rw-r--r--src/render/picking/raycaster.cpp49
-rw-r--r--src/render/picking/raycaster_p.h7
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