summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuan José Casafranca <juan.casafranca@kdab.com>2017-05-23 23:38:53 +0200
committerSean Harmer <sean.harmer@kdab.com>2017-08-02 17:56:42 +0000
commitafd242a810612341a37d496007ad79317d2efbea (patch)
treed260149db9753cb2d05e8374f6aa137f0d4852be
parent4392fa4df4a8f4623dd3ff881f2dd03c94b50c30 (diff)
Accept/Drop entities and filter recursively
The layer now may specify if a subtree must be completely accepted recursively. The layerfilter can specify if the entities must be accepted or dropped. Task-number: QTBUG-59814 Change-Id: I7beff9e036d5de8b128cf960ba5f11477e5784e1 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/render/backend/layer.cpp31
-rw-r--r--src/render/backend/layer_p.h11
-rw-r--r--src/render/backend/renderview_p.h5
-rw-r--r--src/render/backend/renderviewbuilder.cpp1
-rw-r--r--src/render/framegraph/layerfilternode.cpp15
-rw-r--r--src/render/framegraph/layerfilternode_p.h6
-rw-r--r--src/render/framegraph/qlayerfilter.cpp39
-rw-r--r--src/render/framegraph/qlayerfilter.h15
-rw-r--r--src/render/framegraph/qlayerfilter_p.h4
-rw-r--r--src/render/frontend/qlayer.cpp45
-rw-r--r--src/render/frontend/qlayer.h8
-rw-r--r--src/render/frontend/qlayer_p.h6
-rw-r--r--src/render/jobs/filterlayerentityjob.cpp89
-rw-r--r--src/render/jobs/filterlayerentityjob_p.h5
-rw-r--r--src/render/jobs/renderviewjobutils.cpp1
-rw-r--r--tests/auto/render/layerfiltering/tst_layerfiltering.cpp135
-rw-r--r--tests/manual/layerfilter-qml/layerfilter-qml.pro14
-rw-r--r--tests/manual/layerfilter-qml/layerfilter-qml.qrc5
-rw-r--r--tests/manual/layerfilter-qml/main.cpp63
-rw-r--r--tests/manual/layerfilter-qml/main.qml221
-rw-r--r--tests/manual/manual.pro3
21 files changed, 711 insertions, 11 deletions
diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp
index 14c0317f8..6f50d071d 100644
--- a/src/render/backend/layer.cpp
+++ b/src/render/backend/layer.cpp
@@ -53,6 +53,7 @@ namespace Render {
Layer::Layer()
: BackendNode()
+ , m_recursive(false)
{
}
@@ -66,6 +67,36 @@ void Layer::cleanup()
QBackendNode::setEnabled(false);
}
+void Layer::sceneChangeEvent(const QSceneChangePtr &e)
+{
+ if (e->type() == PropertyUpdated) {
+ QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
+ QByteArray propertyName = propertyChange->propertyName();
+ if (propertyName == QByteArrayLiteral("recursive")) {
+ m_recursive = propertyChange->value().toBool();
+ }
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ BackendNode::sceneChangeEvent(e);
+}
+
+void Layer::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerData>>(change);
+ const auto &data = typedChange->data;
+ m_recursive = data.m_recursive;
+}
+
+bool Layer::recursive() const
+{
+ return m_recursive;
+}
+
+void Layer::setRecursive(bool recursive)
+{
+ m_recursive = recursive;
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/layer_p.h b/src/render/backend/layer_p.h
index b6a78a1cf..2ba3532d2 100644
--- a/src/render/backend/layer_p.h
+++ b/src/render/backend/layer_p.h
@@ -71,6 +71,17 @@ public:
Layer();
~Layer();
void cleanup();
+
+ // QBackendNode interface
+ bool recursive() const;
+ void setRecursive(bool recursive);
+
+protected:
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e);
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change);
+ bool m_recursive;
};
} // namespace Render
diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h
index b65e7d4fa..1f4a920c8 100644
--- a/src/render/backend/renderview_p.h
+++ b/src/render/backend/renderview_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qclearbuffers.h>
+#include <Qt3DRender/qlayerfilter.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/clearbuffers_p.h>
#include <Qt3DRender/private/cameralens_p.h>
@@ -153,6 +154,8 @@ public:
inline bool hasLayerFilter() const Q_DECL_NOTHROW { return m_data.m_hasLayerFilter; }
inline void appendLayerFilter(const Qt3DCore::QNodeIdVector &layerIds) Q_DECL_NOTHROW { m_data.m_layerIds << layerIds; }
inline Qt3DCore::QNodeIdVector layerFilter() const Q_DECL_NOTHROW { return m_data.m_layerIds; }
+ inline QLayerFilter::FilterMode layerFilterFilterMode() const Q_DECL_NOTHROW { return m_data.m_layerFilterFilterMode; }
+ inline void setLayerFilterFilterMode(QLayerFilter::FilterMode filterMode) Q_DECL_NOTHROW { m_data.m_layerFilterFilterMode = filterMode; }
inline void setRenderPassFilter(const RenderPassFilter *rpFilter) Q_DECL_NOTHROW { m_data.m_passFilter = rpFilter; }
inline const RenderPassFilter *renderPassFilter() const Q_DECL_NOTHROW { return m_data.m_passFilter; }
@@ -238,6 +241,7 @@ public:
, m_techniqueFilter(nullptr)
, m_passFilter(nullptr)
, m_hasLayerFilter(false)
+ , m_layerFilterFilterMode(QLayerFilter::AcceptMatchingLayers)
{
}
CameraLens *m_renderCameraLens;
@@ -247,6 +251,7 @@ public:
QMatrix4x4 m_viewMatrix;
QMatrix4x4 m_viewProjectionMatrix;
bool m_hasLayerFilter;
+ QLayerFilter::FilterMode m_layerFilterFilterMode;
Qt3DCore::QNodeIdVector m_layerIds;
QVector<Qt3DRender::QSortPolicy::SortType> m_sortingTypes;
QVector3D m_eyePos;
diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp
index 06cf1d22e..d24f42efc 100644
--- a/src/render/backend/renderviewbuilder.cpp
+++ b/src/render/backend/renderviewbuilder.cpp
@@ -139,6 +139,7 @@ public:
// Layer filtering
m_filterEntityByLayerJob->setHasLayerFilter(rv->hasLayerFilter());
m_filterEntityByLayerJob->setLayers(rv->layerFilter());
+ m_filterEntityByLayerJob->setFilterMode(rv->layerFilterFilterMode());
// Material Parameter building
for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp
index 17693eb83..6223543c6 100644
--- a/src/render/framegraph/layerfilternode.cpp
+++ b/src/render/framegraph/layerfilternode.cpp
@@ -53,6 +53,7 @@ namespace Render {
LayerFilterNode::LayerFilterNode()
: FrameGraphNode(FrameGraphNode::LayerFilter)
+ , m_filterMode(QLayerFilter::AcceptMatchingLayers)
{
}
@@ -62,6 +63,7 @@ void LayerFilterNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBaseP
const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerFilterData>>(change);
const auto &data = typedChange->data;
setLayerIds(data.layerIds);
+ m_filterMode = data.filterMode;
}
void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
@@ -81,6 +83,14 @@ void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
break;
}
+ case PropertyUpdated: {
+ const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
+ if (change->propertyName() == QByteArrayLiteral("filterMode")) {
+ m_filterMode = static_cast<QLayerFilter::FilterMode>(change->value().value<int>());
+ break;
+ }
+ }
+
default:
break;
}
@@ -99,6 +109,11 @@ void LayerFilterNode::setLayerIds(const QNodeIdVector &list)
m_layerIds = list;
}
+QLayerFilter::FilterMode LayerFilterNode::filterMode() const
+{
+ return m_filterMode;
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/layerfilternode_p.h b/src/render/framegraph/layerfilternode_p.h
index ef443dfd0..59e16c934 100644
--- a/src/render/framegraph/layerfilternode_p.h
+++ b/src/render/framegraph/layerfilternode_p.h
@@ -52,14 +52,13 @@
//
#include <Qt3DRender/private/framegraphnode_p.h>
+#include <Qt3DRender/QLayerFilter>
#include <QStringList>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QLayerFilter;
-
namespace Render {
class Renderer;
@@ -73,10 +72,13 @@ public:
Qt3DCore::QNodeIdVector layerIds() const;
void setLayerIds(const Qt3DCore::QNodeIdVector &list);
+ QLayerFilter::FilterMode filterMode() const;
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
Qt3DCore::QNodeIdVector m_layerIds;
+ QLayerFilter::FilterMode m_filterMode;
};
} // namespace Render
diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp
index 2d4653fcb..f6520a1b6 100644
--- a/src/render/framegraph/qlayerfilter.cpp
+++ b/src/render/framegraph/qlayerfilter.cpp
@@ -51,6 +51,7 @@ namespace Qt3DRender {
QLayerFilterPrivate::QLayerFilterPrivate()
: QFrameGraphNodePrivate()
+ , m_filterMode(QLayerFilter::AcceptMatchingLayers)
{
}
@@ -64,6 +65,17 @@ QLayerFilterPrivate::QLayerFilterPrivate()
to draw in that branch of the frame graph. The Qt3DRender::QLayerFilter selects which
entities to draw based on the Qt3DRender::QLayer instances added to the QLayerFilter
and as components to the \l Qt3DCore::QEntity.
+
+ The Qt3DRender::QLayerFilter can be configured to select entities with a specific
+ Qt3DRender::QLayer or to discard entities with a specific Qt3DRender::QLayer
+ depending on the property discard. By default, entities referencing a Qt3DRender::QLayer
+ component also added to the QLayerFilter are selected.
+*/
+
+/*!
+ \property bool Qt3DRender::QLayerFilter::discards
+ Specifies if the entities should be selected or discarded.
+ By default, entities are selected.
*/
/*!
@@ -78,6 +90,11 @@ QLayerFilterPrivate::QLayerFilterPrivate()
to draw in that branch of the frame graph. The LayerFilter selects which
entities to draw based on the \l Layer instances added to the LayerFilter
and as components to the \l Entity.
+
+ The LayerFilter can be configured to select entities with a specific
+ \l Layer or to discard entities with a specific \l Layer
+ depending on the property discard. By default, entities referencing a \Layer
+ component also added to the LayerFilter are selected.
*/
/*!
@@ -87,6 +104,12 @@ QLayerFilterPrivate::QLayerFilterPrivate()
*/
/*!
+ \qmlproperty bool Qt3DRender::LayerFilter::discard
+ Specifies if entities should be selected or discarded.
+ By default, entities are selected.
+*/
+
+/*!
The constructor creates an instance with the specified \a parent.
*/
QLayerFilter::QLayerFilter(QNode *parent)
@@ -159,12 +182,28 @@ QVector<QLayer *> QLayerFilter::layers() const
return d->m_layers;
}
+QLayerFilter::FilterMode QLayerFilter::filterMode() const
+{
+ Q_D(const QLayerFilter);
+ return d->m_filterMode;
+}
+
+void QLayerFilter::setFilterMode(QLayerFilter::FilterMode filterMode)
+{
+ Q_D(QLayerFilter);
+ if (d->m_filterMode != filterMode) {
+ d->m_filterMode = filterMode;
+ emit filterModeChanged(filterMode);
+ }
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QLayerFilter::createNodeCreationChange() const
{
auto creationChange = QFrameGraphNodeCreatedChangePtr<QLayerFilterData>::create(this);
auto &data = creationChange->data;
Q_D(const QLayerFilter);
data.layerIds = qIdsForNodes(d->m_layers);
+ data.filterMode = d->m_filterMode;
return creationChange;
}
diff --git a/src/render/framegraph/qlayerfilter.h b/src/render/framegraph/qlayerfilter.h
index 61eac5773..243ae7165 100644
--- a/src/render/framegraph/qlayerfilter.h
+++ b/src/render/framegraph/qlayerfilter.h
@@ -53,7 +53,15 @@ class QLayerFilterPrivate;
class QT3DRENDERSHARED_EXPORT QLayerFilter : public QFrameGraphNode
{
Q_OBJECT
+ Q_PROPERTY(FilterMode filterMode READ filterMode WRITE setFilterMode NOTIFY filterModeChanged)
public:
+ enum FilterMode
+ {
+ AcceptMatchingLayers = 0,
+ DiscardMatchingLayers
+ };
+ Q_ENUM(FilterMode) // LOVC_EXLC_LINE
+
explicit QLayerFilter(Qt3DCore::QNode *parent = nullptr);
~QLayerFilter();
@@ -61,6 +69,13 @@ public:
void removeLayer(QLayer *layer);
QVector<QLayer *> layers() const;
+ FilterMode filterMode() const;
+ void setFilterMode(FilterMode filterMode);
+
+Q_SIGNALS:
+ void filterModeChanged(FilterMode filterMode);
+
+
protected:
explicit QLayerFilter(QLayerFilterPrivate &dd, Qt3DCore::QNode *parent = nullptr);
diff --git a/src/render/framegraph/qlayerfilter_p.h b/src/render/framegraph/qlayerfilter_p.h
index 8ad7d3301..97469bda0 100644
--- a/src/render/framegraph/qlayerfilter_p.h
+++ b/src/render/framegraph/qlayerfilter_p.h
@@ -52,13 +52,13 @@
//
#include <private/qframegraphnode_p.h>
+#include <Qt3DRender/qlayerfilter.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
class QLayer;
-class QLayerFilter;
class QLayerFilterPrivate : public QFrameGraphNodePrivate
{
@@ -67,11 +67,13 @@ public:
Q_DECLARE_PUBLIC(QLayerFilter)
QVector<QLayer*> m_layers;
+ QLayerFilter::FilterMode m_filterMode;
};
struct QLayerFilterData
{
Qt3DCore::QNodeIdVector layerIds;
+ QLayerFilter::FilterMode filterMode;
};
} // namespace Qt3DRender
diff --git a/src/render/frontend/qlayer.cpp b/src/render/frontend/qlayer.cpp
index cd7d92caf..416525360 100644
--- a/src/render/frontend/qlayer.cpp
+++ b/src/render/frontend/qlayer.cpp
@@ -46,6 +46,7 @@ namespace Qt3DRender {
QLayerPrivate::QLayerPrivate()
: QComponentPrivate()
+ , m_recursive(false)
{
}
@@ -58,7 +59,7 @@ QLayerPrivate::QLayerPrivate()
Qt3DRender::QLayer works in conjunction with the Qt3DRender::QLayerFilter in the FrameGraph.
\sa Qt3DRender::QLayerFilter
- Qt3DRender::QLayer doesn't define any new properties but is supposed to only be referenced.
+ A QLayer can be applied to a subtree of entities by setting the recursive property to true.
\code
#include <Qt3DCore/QEntity>
@@ -73,6 +74,7 @@ QLayerPrivate::QLayerPrivate()
Qt3DCore::QEntity *renderableEntity = new Qt3DCore::Qt3DCore::QEntity(rootEntity);
Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DCore::QGeometryRenderer(renderableEntity);
Qt3DRender::QLayer *layer1 = new Qt3DCore::QLayer(renderableEntity);
+ layer1->setRecursive(true);
renderableEntity->addComponent(geometryRenderer);
renderableEntity->addComponent(layer1);
@@ -86,6 +88,10 @@ QLayerPrivate::QLayerPrivate()
...
\endcode
*/
+/*!
+ \property QLayer::recursive
+ Specifies if the layer is also applied to the entity subtree.
+*/
/*!
\qmltype Layer
@@ -98,7 +104,7 @@ QLayerPrivate::QLayerPrivate()
Layer works in conjunction with the LayerFilter in the FrameGraph.
- Layer doesn't define any new properties but is supposed to only be referenced.
+ A Layer can be applied to a subtree of entities by setting the recursive property to true.
\code
import Qt3D.Core 2.0
@@ -125,7 +131,10 @@ QLayerPrivate::QLayerPrivate()
// Scene
Camera { id: mainCamera }
- Layer { id: layer1 }
+ Layer {
+ id: layer1
+ recursive: true
+ }
GeometryRenderer { id: mesh }
@@ -137,6 +146,12 @@ QLayerPrivate::QLayerPrivate()
\endcode
*/
+/*!
+ \qmlproperty bool Layer::recursive
+
+ Specifies if the layer is also applied to the entity subtree.
+*/
+
/*! \fn Qt3DRender::QLayer::QLayer(Qt3DCore::QNode *parent)
Constructs a new QLayer with the specified \a parent.
*/
@@ -151,12 +166,36 @@ QLayer::~QLayer()
{
}
+bool QLayer::recursive() const
+{
+ Q_D(const QLayer);
+ return d->m_recursive;
+}
+
+void QLayer::setRecursive(bool recursive)
+{
+ Q_D(QLayer);
+ if (d->m_recursive != recursive) {
+ d->m_recursive = recursive;
+ emit recursiveChanged();
+ }
+}
+
/*! \internal */
QLayer::QLayer(QLayerPrivate &dd, QNode *parent)
: QComponent(dd, parent)
{
}
+Qt3DCore::QNodeCreatedChangeBasePtr QLayer::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QLayerData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QLayer);
+ data.m_recursive = d->m_recursive;
+ return creationChange;
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/frontend/qlayer.h b/src/render/frontend/qlayer.h
index f44685d7e..c57a6fe03 100644
--- a/src/render/frontend/qlayer.h
+++ b/src/render/frontend/qlayer.h
@@ -53,15 +53,23 @@ class QLayerPrivate;
class QT3DRENDERSHARED_EXPORT QLayer : public Qt3DCore::QComponent
{
Q_OBJECT
+ Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
public:
explicit QLayer(Qt3DCore::QNode *parent = nullptr);
~QLayer();
+ bool recursive() const;
+ void setRecursive(bool recursive);
+
+Q_SIGNALS:
+ void recursiveChanged();
+
protected:
explicit QLayer(QLayerPrivate &dd, Qt3DCore::QNode *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QLayer)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const;
};
} // namespace Qt3DRender
diff --git a/src/render/frontend/qlayer_p.h b/src/render/frontend/qlayer_p.h
index 998dcce86..1c01955f7 100644
--- a/src/render/frontend/qlayer_p.h
+++ b/src/render/frontend/qlayer_p.h
@@ -64,9 +64,15 @@ class QT3DRENDERSHARED_PRIVATE_EXPORT QLayerPrivate : public Qt3DCore::QComponen
public:
QLayerPrivate();
+ bool m_recursive;
+
Q_DECLARE_PUBLIC(QLayer)
};
+struct QLayerData {
+ bool m_recursive;
+};
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp
index 5e1add275..1193c4552 100644
--- a/src/render/jobs/filterlayerentityjob.cpp
+++ b/src/render/jobs/filterlayerentityjob.cpp
@@ -57,6 +57,7 @@ FilterLayerEntityJob::FilterLayerEntityJob()
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
, m_hasLayerFilter(false)
+ , m_filterMode(QLayerFilter::AcceptMatchingLayers)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++);
}
@@ -81,11 +82,17 @@ void FilterLayerEntityJob::run()
}
}
+void FilterLayerEntityJob::setFilterMode(QLayerFilter::FilterMode filterMode)
+{
+ m_filterMode = filterMode;
+}
+
// Note: we assume that m_layerIds contains only enabled layers
// -> meaning that if an Entity references such a layer, it's enabled
void FilterLayerEntityJob::filterLayerAndEntity()
{
EntityManager *entityManager = m_manager->renderNodesManager();
+ LayerManager *layerManager = m_manager->layerManager();
const QVector<HEntity> handles = entityManager->activeHandles();
for (const HEntity handle : handles) {
@@ -99,11 +106,87 @@ void FilterLayerEntityJob::filterLayerAndEntity()
// An Entity is positively filtered if it contains at least one Layer component with the same id as the
// layers selected by the LayerFilter
- for (const Qt3DCore::QNodeId id : entityLayers) {
- if (m_layerIds.contains(id)) {
+ // If !discard, as soon as one entity layer is managed by the FilterLayer, accept the entity
+ switch (m_filterMode) {
+ case QLayerFilter::AcceptMatchingLayers: {
+ // Be aware that the same entity may appear in the filteredEntities vector, is this a problem?
+ for (const Qt3DCore::QNodeId id : entityLayers) {
+ bool entityIsAlreadyAccepted = false;
+ if (m_layerIds.contains(id)) {
+ // When we found a layer in the entity that matches a layer in the LayerFilter
+
+ // If the entity hasn't been already accepted, accept it
+ if (!entityIsAlreadyAccepted) {
+ m_filteredEntities.push_back(entity);
+ entityIsAlreadyAccepted = true;
+ }
+
+ Layer *layer = layerManager->lookupResource(id);
+
+ // If the found layer is recursive, accept children and break
+ if (layer->recursive()) {
+ QVector<Entity*> childEntities = entity->children();
+ for (int i = 0; i < childEntities.size(); ++i) {
+ Entity *childEntity = childEntities[i];
+ if (childEntity->isTreeEnabled()) {
+ m_filteredEntities.push_back(childEntity);
+
+ // Add children of the child entity (so that is recursive in the tree)
+ const QVector<Entity*> childChildEntities = childEntity->children();
+ for (Entity *childChildEntity : childChildEntities)
+ childEntities.push_back(childChildEntity);
+ }
+ }
+ break;
+ }
+
+ // If the layer is not recursive, maybe another one in the same entity it is, so continue searching
+ }
+ }
+ break;
+ }
+ case QLayerFilter::DiscardMatchingLayers: {
+ // If discard, the entity must not contain any of the layers managed by the FilterLayer
+
+ // Bootstrap accepting the entity and the children
+ bool acceptEntity = true;
+ bool acceptRecursively = true;
+ bool entityHasLayer = entityLayers.size() != 0;
+
+ // Check if the entity must be dropped and if it must drop also its children
+ for (const Qt3DCore::QNodeId id : entityLayers) {
+ if (m_layerIds.contains(id)) {
+ acceptEntity = false;
+
+ Layer *layer = layerManager->lookupResource(id);
+ if (layer->recursive()) {
+ acceptRecursively = false;
+ break;
+ }
+ }
+ }
+
+ if (entityHasLayer && acceptEntity)
m_filteredEntities.push_back(entity);
- break;
+
+ if (acceptRecursively) {
+ QVector<Entity*> childEntities = entity->children();
+ for (int i = 0; i < childEntities.size(); ++i) {
+ Entity *childEntity = childEntities[i];
+ if (childEntity->isTreeEnabled()) {
+ m_filteredEntities.push_back(childEntity);
+
+ // Add children of the child entity (so that is recursive in the tree)
+ const QVector<Entity*> childChildEntities = childEntity->children();
+ for (Entity *childChildEntity : childChildEntities)
+ childEntities.push_back(childChildEntity);
+ }
+ }
}
+ break;
+ }
+ default:
+ break;
}
}
}
diff --git a/src/render/jobs/filterlayerentityjob_p.h b/src/render/jobs/filterlayerentityjob_p.h
index 50b988ce4..59be53a14 100644
--- a/src/render/jobs/filterlayerentityjob_p.h
+++ b/src/render/jobs/filterlayerentityjob_p.h
@@ -54,6 +54,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <Qt3DRender/qlayerfilter.h>
QT_BEGIN_NAMESPACE
@@ -80,6 +81,9 @@ public:
// QAspectJob interface
void run() Q_DECL_FINAL;
+ void setFilterMode(QLayerFilter::FilterMode filterMode);
+ bool filterMode() const {return m_filterMode;}
+
private:
void filterLayerAndEntity();
void selectAllEntities();
@@ -88,6 +92,7 @@ private:
Qt3DCore::QNodeIdVector m_layerIds;
QVector<Entity *> m_filteredEntities;
bool m_hasLayerFilter;
+ QLayerFilter::FilterMode m_filterMode;
};
typedef QSharedPointer<FilterLayerEntityJob> FilterLayerEntityJobPtr;
diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp
index d7d277f7f..b9959fe47 100644
--- a/src/render/jobs/renderviewjobutils.cpp
+++ b/src/render/jobs/renderviewjobutils.cpp
@@ -120,6 +120,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
case FrameGraphNode::LayerFilter: // Can be set multiple times in the tree
rv->setHasLayerFilter(true);
rv->appendLayerFilter(static_cast<const LayerFilterNode *>(node)->layerIds());
+ rv->setLayerFilterFilterMode(static_cast<const LayerFilterNode *>(node)->filterMode());
break;
case FrameGraphNode::RenderPassFilter:
diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
index c66b85c8c..ed61fce87 100644
--- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
+++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
@@ -34,6 +34,7 @@
#include <Qt3DRender/private/filterlayerentityjob_p.h>
#include <Qt3DRender/private/updatetreeenabledjob_p.h>
#include <Qt3DRender/qlayer.h>
+#include <Qt3DRender/qlayerfilter.h>
#include "testaspect.h"
class tst_LayerFiltering : public QObject
@@ -45,11 +46,14 @@ private Q_SLOTS:
{
// GIVEN
Qt3DRender::Render::FilterLayerEntityJob filterJob;
+ Qt3DRender::QLayer frontendLayer;
// THEN
QCOMPARE(filterJob.hasLayerFilter(), false);
QCOMPARE(filterJob.filteredEntities().size(), 0);
QCOMPARE(filterJob.layers().size(), 0);
+ QCOMPARE(filterJob.filterMode(), Qt3DRender::QLayerFilter::AcceptMatchingLayers);
+ QCOMPARE(frontendLayer.recursive(), false);
}
void filterEntities_data()
@@ -57,6 +61,8 @@ private Q_SLOTS:
QTest::addColumn<Qt3DCore::QEntity *>("entitySubtree");
QTest::addColumn<Qt3DCore::QNodeIdVector>("layerIds");
QTest::addColumn<bool>("hasLayerFilter");
+ QTest::addColumn<Qt3DRender::QLayerFilter::FilterMode>("filterMode");
+ QTest::addColumn<bool>("recursive");
QTest::addColumn<Qt3DCore::QNodeIdVector>("expectedSelectedEntities");
@@ -70,9 +76,34 @@ private Q_SLOTS:
Q_UNUSED(childEntity2);
Q_UNUSED(childEntity3);
- QTest::newRow("EntitiesNoLayerNoLayerFilter-ShouldSelectAll") << rootEntity
+ QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity
<< Qt3DCore::QNodeIdVector()
<< false
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
+ << (Qt3DCore::QNodeIdVector()
+ << rootEntity->id()
+ << childEntity1->id()
+ << childEntity2->id()
+ << childEntity3->id()
+ );
+ }
+
+ {
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+ Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+
+ Q_UNUSED(childEntity1);
+ Q_UNUSED(childEntity2);
+ Q_UNUSED(childEntity3);
+
+ QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity
+ << Qt3DCore::QNodeIdVector()
+ << false
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< (Qt3DCore::QNodeIdVector()
<< rootEntity->id()
<< childEntity1->id()
@@ -87,6 +118,28 @@ private Q_SLOTS:
Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+ Q_UNUSED(childEntity1);
+ Q_UNUSED(childEntity2);
+ Q_UNUSED(childEntity3);
+
+ QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity
+ << Qt3DCore::QNodeIdVector()
+ << false
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
+ << (Qt3DCore::QNodeIdVector()
+ << rootEntity->id()
+ << childEntity1->id()
+ << childEntity2->id()
+ << childEntity3->id()
+ );
+ }
+ {
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+ Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+
Q_UNUSED(childEntity1);
Q_UNUSED(childEntity2);
@@ -95,6 +148,8 @@ private Q_SLOTS:
QTest::newRow("EntityNoLayerWithLayerFilterWithNoFilter-ShouldSelectNone") << rootEntity
<< Qt3DCore::QNodeIdVector()
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< Qt3DCore::QNodeIdVector();
}
@@ -114,6 +169,8 @@ private Q_SLOTS:
QTest::newRow("NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity
<< (Qt3DCore::QNodeIdVector() << layer->id())
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< Qt3DCore::QNodeIdVector();
}
@@ -132,6 +189,8 @@ private Q_SLOTS:
QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity
<< (Qt3DCore::QNodeIdVector() << layer->id())
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id());
}
@@ -151,6 +210,8 @@ private Q_SLOTS:
QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity
<< (Qt3DCore::QNodeIdVector() << layer->id() << layer2->id())
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id());
}
@@ -170,6 +231,8 @@ private Q_SLOTS:
QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity
<< (Qt3DCore::QNodeIdVector() << layer2->id())
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< Qt3DCore::QNodeIdVector();
}
@@ -189,9 +252,74 @@ private Q_SLOTS:
QTest::newRow("LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity
<< (Qt3DCore::QNodeIdVector() << layer->id())
<< true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << false
<< (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id());
}
+ {
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+ Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+
+ Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity);
+ layer->setRecursive(true);
+ rootEntity->addComponent(layer);
+
+ QTest::newRow("RecursiveLayerOnRoot-ShouldSelectAll") << rootEntity
+ << (Qt3DCore::QNodeIdVector() << layer->id())
+ << true
+ << Qt3DRender::QLayerFilter::AcceptMatchingLayers
+ << true
+ << (Qt3DCore::QNodeIdVector()
+ << rootEntity->id()
+ << childEntity1->id()
+ << childEntity2->id()
+ << childEntity3->id());
+ }
+
+ {
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+ Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+
+ Q_UNUSED(childEntity1);
+ Q_UNUSED(childEntity2);
+ Q_UNUSED(childEntity3);
+
+ Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity);
+ layer->setRecursive(true);
+ rootEntity->addComponent(layer);
+
+ QTest::newRow("RecursiveLayerLayerFilterDiscardOnRoot-ShouldSelectNone") << rootEntity
+ << (Qt3DCore::QNodeIdVector() << layer->id())
+ << true
+ << Qt3DRender::QLayerFilter::DiscardMatchingLayers
+ << true
+ << (Qt3DCore::QNodeIdVector());
+ }
+
+ {
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+ Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+
+ Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity);
+ rootEntity->addComponent(layer);
+
+ QTest::newRow("LayerLayerFilterDiscardOnRoot-ShouldSelectAllButRoot") << rootEntity
+ << (Qt3DCore::QNodeIdVector() << layer->id())
+ << true
+ << Qt3DRender::QLayerFilter::DiscardMatchingLayers
+ << false
+ << (Qt3DCore::QNodeIdVector()
+ << childEntity1->id()
+ << childEntity2->id()
+ << childEntity3->id());
+ }
}
void filterEntities()
@@ -200,8 +328,12 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity *, entitySubtree);
QFETCH(Qt3DCore::QNodeIdVector, layerIds);
QFETCH(bool, hasLayerFilter);
+ QFETCH(Qt3DRender::QLayerFilter::FilterMode, filterMode);
+ QFETCH(bool, recursive);
QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities);
+ Q_UNUSED(recursive);
+
// GIVEN
QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree));
@@ -215,6 +347,7 @@ private Q_SLOTS:
Qt3DRender::Render::FilterLayerEntityJob filterJob;
filterJob.setHasLayerFilter(hasLayerFilter);
filterJob.setLayers(layerIds);
+ filterJob.setFilterMode(filterMode);
filterJob.setManager(aspect->nodeManagers());
filterJob.run();
diff --git a/tests/manual/layerfilter-qml/layerfilter-qml.pro b/tests/manual/layerfilter-qml/layerfilter-qml.pro
new file mode 100644
index 000000000..edeb4c6e2
--- /dev/null
+++ b/tests/manual/layerfilter-qml/layerfilter-qml.pro
@@ -0,0 +1,14 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ layerfilter-qml.qrc
diff --git a/tests/manual/layerfilter-qml/layerfilter-qml.qrc b/tests/manual/layerfilter-qml/layerfilter-qml.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/layerfilter-qml/layerfilter-qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/layerfilter-qml/main.cpp b/tests/manual/layerfilter-qml/main.cpp
new file mode 100644
index 000000000..dba6e0bff
--- /dev/null
+++ b/tests/manual/layerfilter-qml/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <QGuiApplication>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/layerfilter-qml/main.qml b/tests/manual/layerfilter-qml/main.qml
new file mode 100644
index 000000000..8a5977faa
--- /dev/null
+++ b/tests/manual/layerfilter-qml/main.qml
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.0
+
+Entity {
+ id: sceneRoot
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 3.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ Camera {
+ id: backgroundCamera
+ projectionType: CameraLens.OrthographicProjection
+ left: -0.25
+ bottom: -0.25
+ top: 0.25
+ right: 0.25
+ nearPlane: 0.1
+ farPlane: 1.5
+ position: Qt.vector3d( 0.0, 0.0, 1.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ Layer {
+ id: backgroundLayer
+ recursive: true
+ }
+
+ Layer {
+ id: sceneLayer
+ recursive: true
+ }
+
+ Layer {
+ id: secondBackgroundLayer
+ }
+
+ RenderSettings {
+ id : external_forward_renderer
+ activeFrameGraph :
+
+ RenderSurfaceSelector {
+ Viewport {
+ normalizedRect: Qt.rect(0,0,1,1)
+
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthStencilBuffer
+ clearColor: "white"
+
+ LayerFilter {
+ layers: [
+ backgroundLayer,
+ secondBackgroundLayer
+ ]
+
+ CameraSelector {
+ camera: backgroundCamera
+ }
+ }
+ }
+
+ ClearBuffers {
+ buffers: ClearBuffers.DepthStencilBuffer
+
+ LayerFilter {
+ layers: [
+ backgroundLayer,
+ ]
+ discard: true
+
+ CameraSelector {
+ camera: camera
+ }
+ }
+ }
+ }
+ }
+ }
+
+ OrbitCameraController {
+ camera: camera
+ }
+
+ InputSettings {
+ id: inputSettings
+ }
+
+ components: [external_forward_renderer, inputSettings]
+
+ PlaneMesh {
+ id: backgroundMesh
+ width: 0.5
+ height: 0.5
+ }
+
+ Transform {
+ id: backgroundTransform
+ rotation: fromAxisAndAngle(Qt.vector3d(1,0,0), 90)
+ }
+
+ Transform {
+ id: smallBackgroundTransform
+ translation: Qt.vector3d(0,0.5,0)
+ scale: 0.5
+ }
+
+ PhongMaterial {
+ id: backgroundMaterial
+ ambient: "black"
+ }
+
+ PhongMaterial {
+ id: smallBackgroundMaterial
+ ambient: "red"
+ }
+
+ PlaneMesh {
+ id: mesh
+ width: 1
+ height: 1
+ }
+
+ Transform {
+ id: transform
+ translation: Qt.vector3d(0,0,-1)
+ rotation: fromAxisAndAngle(Qt.vector3d(1,0,0), 90)
+ }
+
+ PhongMaterial {
+ id: material
+ ambient: "blue"
+ }
+
+ Entity {
+ id: backgroundFilterEntity
+ components: [backgroundLayer]
+
+ Entity {
+ id: backgroundEntity
+ objectName: "backgroundEntity"
+ components: [backgroundMesh, backgroundMaterial, backgroundTransform]
+
+ Entity {
+ id: smallBackground
+ objectName: "smallBackground"
+ components: [backgroundMesh, smallBackgroundMaterial, smallBackgroundTransform]
+ }
+ }
+ }
+
+ Entity {
+ components: [sceneLayer]
+
+ Entity {
+ id: mainEntity
+ objectName: "mainEntity"
+ components: [ mesh, material, transform ]
+ }
+ }
+}
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index e1e592fe5..0e6659c5e 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -50,7 +50,8 @@ SUBDIRS += \
distancefieldtext \
mesh-morphing \
anim-viewer \
- animation-keyframe-programmatic
+ animation-keyframe-programmatic \
+ layerfilter-qml
qtHaveModule(widgets): {
SUBDIRS += \