summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-10-19 03:04:04 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-10-19 03:04:04 +0200
commitb0bbbfbe3a3e3dd769e1664ce7bb4b44bed3ec6a (patch)
tree10c04d4e920a38c3828e9cb64084fd122052579a
parent3c551b2e2f4f433894d5c70de6e260fddadbb12d (diff)
parent683151c338046621d239ac0d9b597171c56e3991 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.15
-rw-r--r--src/animation/frontend/qabstractclipanimator.cpp22
-rw-r--r--src/animation/frontend/qblendedclipanimator.cpp1
-rw-r--r--src/animation/frontend/qchannelmapper.cpp5
-rw-r--r--src/animation/frontend/qclipanimator.cpp1
-rw-r--r--src/core/aspects/qabstractaspect.h2
-rw-r--r--src/input/frontend/qabstractphysicaldevice.cpp4
-rw-r--r--src/input/frontend/qaction.cpp4
-rw-r--r--src/input/frontend/qaxis.cpp4
-rw-r--r--src/input/frontend/qinputchord.cpp4
-rw-r--r--src/input/frontend/qinputsequence.cpp4
-rw-r--r--src/input/frontend/qlogicaldevice.cpp8
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.cpp2
-rw-r--r--src/plugins/sceneparsers/sceneparsers.pro2
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp20
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem_p.h1
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp4
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial.cpp1
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial_p.h4
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp10
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h1
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode.cpp6
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode_p.h2
-rw-r--r--src/quick3d/quick3dextras/qt3dquickwindow.cpp3
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp38
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.h3
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d_p.h2
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.cpp158
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d_p.h10
-rw-r--r--src/render/backend/abstractrenderer_p.h3
-rw-r--r--src/render/backend/offscreensurfacehelper.cpp1
-rw-r--r--src/render/backend/platformsurfacefilter.cpp4
-rw-r--r--src/render/framegraph/framegraphnode.cpp1
-rw-r--r--src/render/framegraph/qlayerfilter.cpp4
-rw-r--r--src/render/framegraph/qrenderpassfilter.cpp8
-rw-r--r--src/render/framegraph/qrenderstateset.cpp4
-rw-r--r--src/render/framegraph/qsubtreeenabler.cpp2
-rw-r--r--src/render/framegraph/qtechniquefilter.cpp8
-rw-r--r--src/render/frontend/qcomputecommand.cpp2
-rw-r--r--src/render/frontend/qrenderaspect.cpp1
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--src/render/frontend/qrenderplugin_p.h4
-rw-r--r--src/render/frontend/qrendertarget.cpp4
-rw-r--r--src/render/frontend/sphere.cpp50
-rw-r--r--src/render/frontend/sphere_p.h13
-rw-r--r--src/render/geometry/buffer.cpp4
-rw-r--r--src/render/geometry/qbuffer.cpp2
-rw-r--r--src/render/geometry/qgeometry.cpp4
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp78
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp122
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h3
-rw-r--r--src/render/materialsystem/qeffect.cpp12
-rw-r--r--src/render/materialsystem/qfilterkey.cpp4
-rw-r--r--src/render/materialsystem/qmaterial.cpp4
-rw-r--r--src/render/materialsystem/qparameter.cpp4
-rw-r--r--src/render/materialsystem/qrenderpass.cpp12
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.cpp88
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.h1
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder_p.h6
-rw-r--r--src/render/materialsystem/qtechnique.cpp16
-rw-r--r--src/render/materialsystem/shader.cpp38
-rw-r--r--src/render/materialsystem/shader_p.h7
-rw-r--r--src/render/materialsystem/shaderbuilder.cpp63
-rw-r--r--src/render/materialsystem/shaderbuilder_p.h36
-rw-r--r--src/render/picking/objectpicker.cpp55
-rw-r--r--src/render/picking/objectpicker_p.h7
-rw-r--r--src/render/picking/picking.pri1
-rw-r--r--src/render/picking/qobjectpicker.cpp42
-rw-r--r--src/render/picking/qobjectpicker.h3
-rw-r--r--src/render/picking/qobjectpicker_p.h1
-rw-r--r--src/render/picking/qpickevent_p.h4
-rw-r--r--src/render/picking/qpicktriangleevent.cpp51
-rw-r--r--src/render/picking/qpicktriangleevent_p.h69
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp5
-rw-r--r--src/render/renderers/opengl/jobs/renderviewjobutils.cpp2
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp107
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h26
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp23
-rw-r--r--src/render/renderstates/qrenderstate.cpp1
-rw-r--r--src/render/texture/qabstracttexture.cpp108
-rw-r--r--src/render/texture/qtexture.cpp82
-rw-r--r--tests/auto/render/boundingsphere/tst_boundingsphere.cpp172
-rw-r--r--tests/auto/render/buffer/tst_buffer.cpp24
-rw-r--r--tests/auto/render/framegraphnode/tst_framegraphnode.cpp18
-rw-r--r--tests/auto/render/ktxtextures/data/16_16.pngbin0 -> 346 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTXbin0 -> 196 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTXbin0 -> 196 bytes
-rw-r--r--tests/auto/render/ktxtextures/ktxtextures.pro11
-rw-r--r--tests/auto/render/ktxtextures/tst_ktxtextures.cpp75
-rw-r--r--tests/auto/render/objectpicker/tst_objectpicker.cpp59
-rw-r--r--tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp626
-rw-r--r--tests/auto/render/picking/tst_picking.cpp50
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp38
-rw-r--r--tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp80
-rw-r--r--tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp32
-rw-r--r--tests/auto/render/render.pro1
-rw-r--r--tests/auto/render/scene2d/tst_scene2d.cpp62
-rw-r--r--tests/auto/render/shader/tst_shader.cpp2
-rw-r--r--tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp148
-rw-r--r--tests/manual/compressed_textures/compressed_textures.pro12
-rw-r--r--tests/manual/compressed_textures/compressed_textures.qrc5
-rw-r--r--tests/manual/compressed_textures/data/16_16.pngbin0 -> 346 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTXbin0 -> 196 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTXbin0 -> 196 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16-etc1.pkmbin0 -> 144 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16-etc2.pkmbin0 -> 144 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.ddsbin0 -> 332 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.ddsbin0 -> 276 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.ddsbin0 -> 256 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1.ddsbin0 -> 312 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.ddsbin0 -> 516 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.ddsbin0 -> 404 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.ddsbin0 -> 384 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3.ddsbin0 -> 496 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.ddsbin0 -> 384 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-lumi.ddsbin0 -> 469 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.ddsbin0 -> 1152 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-rgb.ddsbin0 -> 1492 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.ddsbin0 -> 1252 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.ddsbin0 -> 916 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.ddsbin0 -> 896 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1.ddsbin0 -> 1232 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.ddsbin0 -> 2356 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.ddsbin0 -> 1684 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.ddsbin0 -> 1664 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3.ddsbin0 -> 2336 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.ddsbin0 -> 1664 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-lumi.ddsbin0 -> 2174 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.ddsbin0 -> 6272 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-rgb.ddsbin0 -> 8312 bytes
-rw-r--r--tests/manual/compressed_textures/main.cpp75
-rw-r--r--tests/manual/compressed_textures/main.qml118
-rw-r--r--tests/manual/manual.pro3
138 files changed, 2074 insertions, 1065 deletions
diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp
index b2f6f817f..cb4621182 100644
--- a/src/animation/frontend/qabstractclipanimator.cpp
+++ b/src/animation/frontend/qabstractclipanimator.cpp
@@ -125,6 +125,11 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q
QAbstractClipAnimator::~QAbstractClipAnimator()
{
}
+/*!
+ \qmlproperty bool Qt3DAnimation::AbstractClipAnimator::running
+
+ This property holds a boolean indicating whether the animation is currently running.
+*/
/*!
\property Qt3DAnimation::QAbstractClipAnimator::running
@@ -142,6 +147,13 @@ bool QAbstractClipAnimator::isRunning() const
}
/*!
+ \qmlproperty ChannelMapper Qt3DAnimation::AbstractClipAnimator::channelMapper
+
+ This property holds the ChannelMapper that controls how the channels in
+ the animation clip map onto the properties of the target objects.
+*/
+
+/*!
\property Qt3DAnimation::QAbstractClipAnimator::channelMapper
This property holds the ChannelMapper that controls how the channels in
@@ -199,6 +211,12 @@ int QAbstractClipAnimator::loopCount() const
return d->m_loops;
}
/*!
+ \qmlproperty Clock Qt3DAnimation::AbstractClipAnimator::clock
+
+ The clock controls the speed with which an animation is played.
+*/
+
+/*!
\property Qt3DAnimation::QAbstractClipAnimator::clock
The clock controls the speed with which an animation is played.
@@ -208,7 +226,11 @@ QClock *QAbstractClipAnimator::clock() const
Q_D(const QAbstractClipAnimator);
return d->m_clock;
}
+/*!
+ \qmlproperty real Qt3DAnimation::AbstractClipAnimator::normalizedTime
+ This property holds the clips normalized time.
+*/
/*!
\property Qt3DAnimation::QAbstractClipAnimator::normalizedTime
diff --git a/src/animation/frontend/qblendedclipanimator.cpp b/src/animation/frontend/qblendedclipanimator.cpp
index 388144c81..c48706606 100644
--- a/src/animation/frontend/qblendedclipanimator.cpp
+++ b/src/animation/frontend/qblendedclipanimator.cpp
@@ -56,6 +56,7 @@ QBlendedClipAnimatorPrivate::QBlendedClipAnimatorPrivate()
\qmltype BlendedClipAnimator
\instantiates Qt3DAnimation::QBlendedClipAnimator
\inqmlmodule Qt3D.Animation
+ \inherits AbstractClipAnimator
\since 5.9
\brief BlendedClipAnimator is a component providing animation playback capabilities of a tree
diff --git a/src/animation/frontend/qchannelmapper.cpp b/src/animation/frontend/qchannelmapper.cpp
index 2146290e4..ab98039b4 100644
--- a/src/animation/frontend/qchannelmapper.cpp
+++ b/src/animation/frontend/qchannelmapper.cpp
@@ -36,6 +36,7 @@
#include "qchannelmapper.h"
#include "qchannelmapper_p.h"
+#include <Qt3DCore/qscenechange.h>
#include <Qt3DAnimation/qchannelmapping.h>
QT_BEGIN_NAMESPACE
@@ -85,7 +86,7 @@ void QChannelMapper::addMapping(QAbstractChannelMapping *mapping)
if (!mapping->parent())
mapping->setParent(this);
- d->update();
+ d->updateNode(mapping, "mappings", Qt3DCore::PropertyValueAdded);
}
}
@@ -94,7 +95,7 @@ void QChannelMapper::removeMapping(QAbstractChannelMapping *mapping)
Q_ASSERT(mapping);
Q_D(QChannelMapper);
d->m_mappings.removeOne(mapping);
- d->update();
+ d->updateNode(mapping, "mappings", Qt3DCore::PropertyValueRemoved);
// Remove bookkeeping connection
d->unregisterDestructionHelper(mapping);
}
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index 398758820..03510aa93 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -66,6 +66,7 @@ bool QClipAnimatorPrivate::canPlay() const
\qmltype ClipAnimator
\instantiates Qt3DAnimation::QClipAnimator
\inqmlmodule Qt3D.Animation
+ \inherits AbstractClipAnimator
\since 5.9
\brief ClipAnimator is a component providing simple animation playback capabilities.
diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h
index 8c191c1d8..8059421a6 100644
--- a/src/core/aspects/qabstractaspect.h
+++ b/src/core/aspects/qabstractaspect.h
@@ -81,6 +81,7 @@ protected:
template<class Frontend, bool supportsSyncing>
void registerBackendType(const QBackendNodeMapperPtr &functor);
void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor);
+ void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing);
template<class Frontend>
void unregisterBackendType();
void unregisterBackendType(const QMetaObject &);
@@ -88,7 +89,6 @@ protected:
private:
void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes);
void syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes);
- void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing);
virtual QVariant executeCommand(const QStringList &args);
diff --git a/src/input/frontend/qabstractphysicaldevice.cpp b/src/input/frontend/qabstractphysicaldevice.cpp
index 8cadf95a1..33c86f7b8 100644
--- a/src/input/frontend/qabstractphysicaldevice.cpp
+++ b/src/input/frontend/qabstractphysicaldevice.cpp
@@ -165,7 +165,7 @@ void QAbstractPhysicalDevice::addAxisSetting(QAxisSetting *axisSetting)
{
Q_D(QAbstractPhysicalDevice);
if (axisSetting && !d->m_axisSettings.contains(axisSetting)) {
- d->update();
+ d->updateNode(axisSetting, "axisSettings", Qt3DCore::PropertyValueAdded);
d->m_axisSettings.push_back(axisSetting);
}
}
@@ -177,7 +177,7 @@ void QAbstractPhysicalDevice::removeAxisSetting(QAxisSetting *axisSetting)
{
Q_D(QAbstractPhysicalDevice);
if (axisSetting && d->m_axisSettings.contains(axisSetting)) {
- d->update();
+ d->updateNode(axisSetting, "axisSettings", Qt3DCore::PropertyValueRemoved);
d->m_axisSettings.removeOne(axisSetting);
}
}
diff --git a/src/input/frontend/qaction.cpp b/src/input/frontend/qaction.cpp
index 8eccec9e4..c835062a2 100644
--- a/src/input/frontend/qaction.cpp
+++ b/src/input/frontend/qaction.cpp
@@ -119,7 +119,7 @@ void QAction::addInput(QAbstractActionInput *input)
// Ensures proper bookkeeping
d->registerDestructionHelper(input, &QAction::removeInput, d->m_inputs);
- d->update();
+ d->updateNode(input, "inputs", Qt3DCore::PropertyValueAdded);
}
}
@@ -131,7 +131,7 @@ void QAction::removeInput(QAbstractActionInput *input)
Q_D(QAction);
if (d->m_inputs.contains(input)) {
- d->update();
+ d->updateNode(input, "inputs", Qt3DCore::PropertyValueRemoved);
d->m_inputs.removeOne(input);
diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp
index 7c9998776..b6018c887 100644
--- a/src/input/frontend/qaxis.cpp
+++ b/src/input/frontend/qaxis.cpp
@@ -115,7 +115,7 @@ void QAxis::addInput(QAbstractAxisInput *input)
// Ensures proper bookkeeping
d->registerDestructionHelper(input, &QAxis::removeInput, d->m_inputs);
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -137,7 +137,7 @@ void QAxis::removeInput(QAbstractAxisInput *input)
Q_D(QAxis);
if (d->m_inputs.contains(input)) {
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_inputs.removeOne(input);
diff --git a/src/input/frontend/qinputchord.cpp b/src/input/frontend/qinputchord.cpp
index a64cc8961..0c4d15190 100644
--- a/src/input/frontend/qinputchord.cpp
+++ b/src/input/frontend/qinputchord.cpp
@@ -154,7 +154,7 @@ void QInputChord::addChord(QAbstractActionInput *input)
if (!input->parent())
input->setParent(this);
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -167,7 +167,7 @@ void QInputChord::removeChord(QAbstractActionInput *input)
{
Q_D(QInputChord);
if (d->m_chords.contains(input)) {
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_chords.removeOne(input);
diff --git a/src/input/frontend/qinputsequence.cpp b/src/input/frontend/qinputsequence.cpp
index 5e0e36aba..d59ebc0f3 100644
--- a/src/input/frontend/qinputsequence.cpp
+++ b/src/input/frontend/qinputsequence.cpp
@@ -207,7 +207,7 @@ void QInputSequence::addSequence(QAbstractActionInput *input)
if (!input->parent())
input->setParent(this);
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -220,7 +220,7 @@ void QInputSequence::removeSequence(QAbstractActionInput *input)
{
Q_D(QInputSequence);
if (d->m_sequences.contains(input)) {
- d->update();
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_sequences.removeOne(input);
diff --git a/src/input/frontend/qlogicaldevice.cpp b/src/input/frontend/qlogicaldevice.cpp
index 2069be633..44e04baa8 100644
--- a/src/input/frontend/qlogicaldevice.cpp
+++ b/src/input/frontend/qlogicaldevice.cpp
@@ -173,7 +173,7 @@ void QLogicalDevice::addAction(QAction *action)
// Ensures proper bookkeeping
d->registerDestructionHelper(action, &QLogicalDevice::removeAction, d->m_actions);
- d->update();
+ d->updateNode(action, "action", Qt3DCore::PropertyValueAdded);
}
}
@@ -184,7 +184,7 @@ void QLogicalDevice::removeAction(QAction *action)
{
Q_D(QLogicalDevice);
if (d->m_actions.contains(action)) {
- d->update();
+ d->updateNode(action, "action", Qt3DCore::PropertyValueRemoved);
d->m_actions.removeOne(action);
@@ -224,7 +224,7 @@ void QLogicalDevice::addAxis(QAxis *axis)
// Ensures proper bookkeeping
d->registerDestructionHelper(axis, &QLogicalDevice::removeAxis, d->m_axes);
- d->update();
+ d->updateNode(axis, "axis", Qt3DCore::PropertyValueAdded);
}
}
@@ -235,7 +235,7 @@ void QLogicalDevice::removeAxis(QAxis *axis)
{
Q_D(QLogicalDevice);
if (d->m_axes.contains(axis)) {
- d->update();
+ d->updateNode(axis, "axis", Qt3DCore::PropertyValueRemoved);
d->m_axes.removeOne(axis);
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
index eeb6b5346..dfb6c8f2b 100644
--- a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
@@ -96,7 +96,7 @@ bool Scene2DPlugin::registerBackendTypes(QRenderAspect *aspect,
{
registerBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject,
QSharedPointer<Scene2DBackendNodeMapper<Render::Quick::Scene2D> >
- ::create(renderer, m_scene2dNodeManager));
+ ::create(renderer, m_scene2dNodeManager), true);
return true;
}
bool Scene2DPlugin::unregisterBackendTypes(QRenderAspect *aspect)
diff --git a/src/plugins/sceneparsers/sceneparsers.pro b/src/plugins/sceneparsers/sceneparsers.pro
index 9bb0ada36..e57bcac22 100644
--- a/src/plugins/sceneparsers/sceneparsers.pro
+++ b/src/plugins/sceneparsers/sceneparsers.pro
@@ -2,7 +2,7 @@ TEMPLATE = subdirs
# QNX is not supported, and Linux GCC 4.9 on ARM chokes on the assimp
# sources (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66964).
QT_FOR_CONFIG += 3dcore-private
-qtConfig(assimp):if(qtConfig(system-assimp)|android-clang|gcc:greaterThan(QT_GCC_MAJOR_VERSION, 4)): {
+!ios:!tvos:!qcc:qtConfig(assimp):if(qtConfig(system-assimp)|android-clang|clang|win32-msvc)|if(gcc:greaterThan(QT_GCC_MAJOR_VERSION, 4)) {
SUBDIRS += assimp
}
SUBDIRS += gltf
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index 098cab032..f3f7acd71 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -500,10 +500,16 @@ void Scene3DItem::onBeforeSync()
// make Qt3D enter a locked state
m_renderer->allowRender();
- // Request refresh for next frame
+ // Note: it's too early to request an update at this point as
+ // beforeSync() triggered by afterAnimating is considered
+ // to be as being part of the current frame update
+}
+void Scene3DItem::requestUpdate()
+{
// When using the FBO mode, only the QQuickItem needs to be updated
// When using the Underlay mode, the whole windows needs updating
+ const bool usesFBO = m_compositingMode == FBO;
if (usesFBO) {
QQuickItem::update();
for (Scene3DView *view : m_views)
@@ -529,6 +535,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
m_dummySurface = new QOffscreenSurface;
m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living
m_dummySurface->setFormat(rw->format());
+ m_dummySurface->setScreen(rw->screen());
m_dummySurface->create();
surfaceSelector->setSurface(m_dummySurface);
} else {
@@ -616,6 +623,9 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
// If the render aspect wasn't created yet, do so now
if (m_renderAspect == nullptr) {
m_renderAspect = new QRenderAspect(QRenderAspect::Synchronous);
+ auto *rw = QQuickRenderControl::renderWindowFor(window());
+ static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->m_screen =
+ (rw ? rw->screen() : window()->screen());
m_aspectEngine->registerAspect(m_renderAspect);
// Before Synchronizing is in the SG Thread, we want beforeSync to be triggered
@@ -625,8 +635,6 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect));
QObject::connect(renderAspectPriv->m_aspectManager->changeArbiter(), &Qt3DCore::QChangeArbiter::receivedChange,
this, [this] { m_dirty = true; }, Qt::DirectConnection);
- QObject::connect(renderAspectPriv->m_aspectManager->changeArbiter(), &Qt3DCore::QChangeArbiter::receivedChange,
- this, &QQuickItem::update, Qt::AutoConnection);
}
if (m_renderer == nullptr) {
@@ -668,6 +676,12 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
window()->setClearBeforeRendering(false);
}
+ // Request update for next frame so that we can check whether we need to
+ // render again or not
+ static int requestUpdateMethodIdx = Scene3DItem::staticMetaObject.indexOfMethod("requestUpdate()");
+ static QMetaMethod requestUpdateMethod =Scene3DItem::staticMetaObject.method(requestUpdateMethodIdx);
+ requestUpdateMethod.invoke(this, Qt::QueuedConnection);
+
return fboNode;
}
diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h
index 4a2fc7f44..e46bb20af 100644
--- a/src/quick3d/imports/scene3d/scene3ditem_p.h
+++ b/src/quick3d/imports/scene3d/scene3ditem_p.h
@@ -129,6 +129,7 @@ Q_SIGNALS:
private Q_SLOTS:
void applyRootEntityChange();
void onBeforeSync();
+ void requestUpdate();
private:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override;
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index bc4dbd362..1e375ccbb 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -419,6 +419,10 @@ void Scene3DRenderer::render()
// Restore QtQuick FBO
QOpenGLFramebufferObject::bindDefault();
+
+ // Only show the node once Qt3D has rendered to it
+ // Avoids showing garbage on the first frame
+ m_node->show();
}
// Reset the state used by the Qt Quick scenegraph to avoid any
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
index 1b8b08a4e..80a1c2c9c 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
@@ -60,6 +60,7 @@ namespace Qt3DRender {
Scene3DSGMaterial::Scene3DSGMaterial()
: QSGMaterial()
, m_texture(nullptr)
+ , m_visible(false)
{
}
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
index c096f2a74..59724782b 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
@@ -75,8 +75,12 @@ public:
QSGMaterialType *type() const final { return &Scene3DSGMaterialShader::type; }
QSGMaterialShader *createShader() const final { return new Scene3DSGMaterialShader(); }
+ void show() { m_visible = true; }
+ bool visible() const { return m_visible; }
+
private:
QSGTexture *m_texture;
+ bool m_visible;
};
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
index d25c6a7f7..55538ad1f 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
@@ -118,21 +118,25 @@ const char *Scene3DSGMaterialShader::fragmentShader() const
if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
return ""
"#version 150 core \n"
+ "uniform bool visible; \n"
"uniform sampler2D source; \n"
"uniform float qt_Opacity; \n"
"in vec2 qt_TexCoord; \n"
"out vec4 fragColor; \n"
"void main() { \n"
- " vec4 p = texture(source, qt_TexCoord); \n"
+ " if (!visible) discard; \n"
+ " vec4 p = texture(source, qt_TexCoord); \n"
" float a = qt_Opacity * p.a; \n"
" fragColor = vec4(p.rgb * a, a); \n"
"}";
} else {
return ""
+ "uniform bool visible; \n"
"uniform highp sampler2D source; \n"
"uniform highp float qt_Opacity; \n"
"varying highp vec2 qt_TexCoord; \n"
"void main() { \n"
+ " if (!visible) discard; \n"
" highp vec4 p = texture2D(source, qt_TexCoord); \n"
" highp float a = qt_Opacity * p.a; \n"
" gl_FragColor = vec4(p.rgb * a, a); \n"
@@ -144,6 +148,7 @@ void Scene3DSGMaterialShader::initialize()
{
m_matrixId = program()->uniformLocation("qt_Matrix");
m_opacityId = program()->uniformLocation("qt_Opacity");
+ m_visibleId = program()->uniformLocation("visible");
}
void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
@@ -172,6 +177,9 @@ void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial
t->updateBindOptions();
}
+ if (oldTx == nullptr || oldTx->visible() != tx->visible())
+ program()->setUniformValue(m_visibleId, tx->visible());
+
if (state.isMatrixDirty())
program()->setUniformValue(m_matrixId, state.combinedMatrix());
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
index c372a1170..60edf6d45 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
@@ -74,6 +74,7 @@ protected:
private:
int m_matrixId;
int m_opacityId;
+ int m_visibleId;
};
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode.cpp b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
index c38e9ffeb..630cf49a9 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
@@ -84,6 +84,12 @@ void Scene3DSGNode::setRect(const QRectF &rect, const QRectF textureRect)
}
}
+void Scene3DSGNode::show()
+{
+ m_material.show();
+ m_opaqueMaterial.show();
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode_p.h b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
index 388c8a605..a7873bdb8 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
@@ -78,6 +78,8 @@ public:
void setRect(const QRectF &rect, const QRectF textureRect = QRectF(0.0f, 1.0f, 1.0f, -1.0f));
QRectF rect() const Q_DECL_NOTHROW { return m_rect; }
+ void show();
+
private:
Scene3DSGMaterial m_material;
Scene3DSGMaterial m_opaqueMaterial;
diff --git a/src/quick3d/quick3dextras/qt3dquickwindow.cpp b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
index bc4bb25ee..d67dfdc71 100644
--- a/src/quick3d/quick3dextras/qt3dquickwindow.cpp
+++ b/src/quick3d/quick3dextras/qt3dquickwindow.cpp
@@ -66,6 +66,7 @@
#include <Qt3DQuickExtras/private/qt3dquickwindowlogging_p.h>
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
QT_BEGIN_NAMESPACE
@@ -132,6 +133,8 @@ Qt3DQuickWindow::Qt3DQuickWindow(QWindow *parent)
QSurfaceFormat::setDefaultFormat(format);
d->m_renderAspect = new Qt3DRender::QRenderAspect;
+ if (parent && parent->screen())
+ static_cast<Qt3DRender::QRenderAspectPrivate*>(Qt3DRender::QRenderAspectPrivate::get(d->m_renderAspect))->m_screen = parent->screen();
d->m_inputAspect = new Qt3DInput::QInputAspect;
d->m_logicAspect = new Qt3DLogic::QLogicAspect;
d->m_engine = new Qt3DCore::Quick::QQmlAspectEngine;
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
index ef06f39f1..cbdc83e7d 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -42,8 +42,6 @@
#include "scene2devent_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -70,6 +68,8 @@ namespace Quick {
with the item; if an entity has a QObjectPicker component, the pick events from that picker
are sent to the QScene2D and converted to mouse events and finally sent to the item.
+ \note Only mouse events are supported. The item does not support keyboard input.
+
\since 5.9
*/
@@ -91,6 +91,8 @@ namespace Quick {
with the item; if an entity has an ObjectPicker component, the pick events from that picker
are sent to the Scene2D and converted to mouse events and finally sent to the item.
+ \note Only mouse events are supported. The item does not support keyboard input.
+
Usage:
\qml
Entity {
@@ -190,15 +192,6 @@ QScene2DPrivate::~QScene2DPrivate()
delete m_renderManager;
}
-void QScene2DPrivate::setScene(Qt3DCore::QScene *scene)
-{
- Q_Q(QScene2D);
- QNodePrivate::setScene(scene);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
- change->setPropertyName("sceneInitialized");
- notifyObservers(change);
-}
-
/*!
The constructor creates a new QScene2D instance with the specified \a parent.
@@ -311,6 +304,15 @@ QVector<Qt3DCore::QEntity*> QScene2D::entities()
}
/*!
+ Retrieve entities associated with the QScene2D.
+ */
+QVector<Qt3DCore::QEntity*> QScene2D::entities() const
+{
+ Q_D(const QScene2D);
+ return d->m_entities;
+}
+
+/*!
Adds an \a entity to the the QScene2D object. If the entities have QObjectPicker,
the pick events from that entity are sent to QScene2D and converted to mouse events.
*/
@@ -321,12 +323,7 @@ void QScene2D::addEntity(Qt3DCore::QEntity *entity)
d->m_entities.append(entity);
d->registerDestructionHelper(entity, &QScene2D::removeEntity, d->m_entities);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), entity);
- change->setPropertyName("entities");
- d->notifyObservers(change);
- }
+ d->updateNode(entity, "entities", PropertyValueAdded);
}
}
@@ -340,12 +337,7 @@ void QScene2D::removeEntity(Qt3DCore::QEntity *entity)
d->m_entities.removeAll(entity);
d->unregisterDestructionHelper(entity);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), entity);
- change->setPropertyName("entities");
- d->notifyObservers(change);
- }
+ d->updateNode(entity, "entities", PropertyValueRemoved);
}
}
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.h b/src/quick3d/quick3dscene2d/items/qscene2d.h
index eab900ca4..2f5c1010e 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.h
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.h
@@ -86,7 +86,8 @@ public:
QQuickItem *item() const;
bool isMouseEnabled() const;
- QVector<Qt3DCore::QEntity *> entities();
+ Q_DECL_DEPRECATED QVector<Qt3DCore::QEntity *> entities();
+ QVector<Qt3DCore::QEntity *> entities() const;
void addEntity(Qt3DCore::QEntity *entity);
void removeEntity(Qt3DCore::QEntity *entity);
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d_p.h b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
index ce354845a..4814564c2 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d_p.h
+++ b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
@@ -74,8 +74,6 @@ public:
QScene2DPrivate();
~QScene2DPrivate();
- void setScene(Qt3DCore::QScene *scene) override;
-
Scene2DManager *m_renderManager;
QMetaObject::Connection m_textureDestroyedConnection;
Qt3DRender::QRenderTargetOutput *m_output;
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp
index 562f0d2c7..981b290e2 100644
--- a/src/quick3d/quick3dscene2d/items/scene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp
@@ -37,6 +37,7 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DQuickScene2D/qscene2d.h>
#include <Qt3DRender/qpicktriangleevent.h>
#include <Qt3DRender/qobjectpicker.h>
@@ -58,6 +59,7 @@
#include <private/qbackendnode_p.h>
#include <private/qobjectpicker_p.h>
#include <private/qpickevent_p.h>
+#include <private/qpicktriangleevent_p.h>
#include <private/entity_p.h>
#include <private/platformsurfacefilter_p.h>
#include <private/trianglesvisitor_p.h>
@@ -130,7 +132,9 @@ Scene2D::Scene2D()
Scene2D::~Scene2D()
{
- stopGrabbing();
+ for (auto connection: qAsConst(m_connections))
+ QObject::disconnect(connection);
+ m_connections.clear();
}
void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
@@ -141,12 +145,9 @@ void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
void Scene2D::initializeSharedObject()
{
if (!m_initialized) {
-
// bail out if we're running autotests
- if (!m_sharedObject->m_renderManager
- || m_sharedObject->m_renderManager->thread() == QThread::currentThread()) {
+ if (!qgetenv("QT3D_SCENE2D_DISABLE_RENDERING").isEmpty())
return;
- }
renderThreadClientCount->fetchAndAddAcquire(1);
@@ -171,76 +172,50 @@ void Scene2D::initializeSharedObject()
}
}
-void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Scene2D::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
- const auto &data = typedChange->data;
- m_renderPolicy = data.renderPolicy;
- setSharedObject(data.sharedObject);
- setOutput(data.output);
- m_entities = data.entityIds;
- m_mouseEnabled = data.mouseEnabled;
-}
+ Qt3DRender::Render::BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QScene2D *node = qobject_cast<const QScene2D *>(frontEnd);
+ if (!node)
+ return;
+ const QScene2DPrivate *dnode = static_cast<const QScene2DPrivate *>(QScene2DPrivate::get(node));
-void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
-
- case Qt3DCore::PropertyUpdated: {
-
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange
- = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy")) {
- m_renderPolicy = propertyChange->value().value<QScene2D::RenderPolicy>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("output")) {
- Qt3DCore::QNodeId outputId = propertyChange->value().value<Qt3DCore::QNodeId>();
- setOutput(outputId);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("pressed")) {
- QObjectPickerEvent ev = propertyChange->value().value<QObjectPickerEvent>();
- QPickEventPtr pickEvent = ev.event;
- handlePickEvent(QEvent::MouseButtonPress, pickEvent);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("released")) {
- QObjectPickerEvent ev = propertyChange->value().value<QObjectPickerEvent>();
- QPickEventPtr pickEvent = ev.event;
- handlePickEvent(QEvent::MouseButtonRelease, pickEvent);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("moved")) {
- QObjectPickerEvent ev = propertyChange->value().value<QObjectPickerEvent>();
- QPickEventPtr pickEvent = ev.event;
- handlePickEvent(QEvent::MouseMove, pickEvent);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("mouseEnabled")) {
- m_mouseEnabled = propertyChange->value().toBool();
- if (m_mouseEnabled && !m_cachedPickEvent.isNull()) {
- handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent);
- m_cachedPickEvent.clear();
- }
- } else if (propertyChange->propertyName() == QByteArrayLiteral("sceneInitialized")) {
- startGrabbing();
+ if (m_mouseEnabled != node->isMouseEnabled()) {
+ m_mouseEnabled = node->isMouseEnabled();
+ if (!firstTime && m_mouseEnabled && m_cachedPickEvent) {
+ handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent.data());
+ m_cachedPickEvent.clear();
}
- break;
}
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("entities")) {
- m_entities.push_back(change->addedNodeId());
- registerObjectPickerEvents(change->addedNodeId());
- }
- break;
- }
+ m_renderPolicy = node->renderPolicy();
+ auto id = Qt3DCore::qIdForNode(node->output());
+ if (id != m_outputId)
+ setOutput(id);
+
+ auto ids = Qt3DCore::qIdsForNodes(node->entities());
+ std::sort(std::begin(ids), std::end(ids));
+ Qt3DCore::QNodeIdVector addedEntities;
+ Qt3DCore::QNodeIdVector removedEntities;
+ std::set_difference(std::begin(ids), std::end(ids),
+ std::begin(m_entities), std::end(m_entities),
+ std::inserter(addedEntities, addedEntities.end()));
+ std::set_difference(std::begin(m_entities), std::end(m_entities),
+ std::begin(ids), std::end(ids),
+ std::inserter(removedEntities, removedEntities.end()));
+ for (const auto &id: addedEntities) {
+ Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>(dnode->m_scene->lookupNode(id));
+ if (!entity)
+ return;
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("entities")) {
- m_entities.removeOne(change->removedNodeId());
- unregisterObjectPickerEvents(change->removedNodeId());
- }
- break;
+ registerObjectPickerEvents(entity);
}
+ for (const auto &id: removedEntities)
+ unregisterObjectPickerEvents(id);
+ m_entities = ids;
- default:
- break;
- }
- BackendNode::sceneChangeEvent(e);
+ if (firstTime)
+ setSharedObject(dnode->m_renderManager->m_sharedObject);
}
void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
@@ -449,19 +424,31 @@ void Scene2D::cleanup()
}
-bool Scene2D::registerObjectPickerEvents(Qt3DCore::QNodeId entityId)
+bool Scene2D::registerObjectPickerEvents(Qt3DCore::QEntity *qentity)
{
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- entityId, (void**)&entity, nullptr)) {
+ qentity->id(), (void**)&entity, nullptr))
return false;
- }
+
if (!entity->containsComponentsOfType<ObjectPicker>() ||
!entity->containsComponentsOfType<GeometryRenderer>()) {
qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
<< "Entity does not contain required components: ObjectPicker and GeometryRenderer";
return false;
}
+
+ QObjectPicker *picker = qentity->componentsOfType<QObjectPicker>().front();
+ m_connections << QObject::connect(picker, &QObjectPicker::pressed, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseButtonPress, pick);
+ });
+ m_connections << QObject::connect(picker, &QObjectPicker::released, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseButtonRelease, pick);
+ });
+ m_connections << QObject::connect(picker, &QObjectPicker::moved, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseMove, pick);
+ });
+
Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
arbiter->registerObserver(d_ptr, entity->componentUuid<ObjectPicker>());
@@ -472,26 +459,27 @@ void Scene2D::unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId)
{
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- entityId, (void**)&entity, nullptr)) {
+ entityId, (void**)&entity, nullptr))
return;
- }
+
Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
arbiter->unregisterObserver(d_ptr, entity->componentUuid<ObjectPicker>());
}
-void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
+void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEvent *ev)
{
if (!isEnabled())
return;
if (m_mouseEnabled) {
- QPickTriangleEvent *pickTriangle = static_cast<QPickTriangleEvent *>(ev.data());
+ const QPickTriangleEvent *pickTriangle = static_cast<const QPickTriangleEvent *>(ev);
+ Q_ASSERT(pickTriangle->entity());
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- QPickEventPrivate::get(pickTriangle)->m_entity,
- (void**)&entity, nullptr)) {
+ Qt3DCore::qIdForNode(pickTriangle->entity()),
+ (void**)&entity, nullptr))
return;
- }
+
CoordinateReader reader(renderer()->nodeManagers());
if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(),
QAttribute::defaultTextureCoordinateAttributeName())) {
@@ -515,24 +503,14 @@ void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
QCoreApplication::postEvent(m_sharedObject->m_quickWindow, mouseEvent);
}
} else if (type == QEvent::MouseButtonPress) {
- m_cachedPickEvent = ev;
+ const QPickTriangleEvent *pickTriangle = static_cast<const QPickTriangleEvent *>(ev);
+ const QPickTriangleEventPrivate *dpick = QPickTriangleEventPrivate::get(pickTriangle);
+ m_cachedPickEvent = QPickEventPtr(dpick->clone());
} else {
m_cachedPickEvent.clear();
}
}
-void Scene2D::startGrabbing()
-{
- for (Qt3DCore::QNodeId e : qAsConst(m_entities))
- registerObjectPickerEvents(e);
-}
-
-void Scene2D::stopGrabbing()
-{
- for (Qt3DCore::QNodeId e : qAsConst(m_entities))
- unregisterObjectPickerEvents(e);
-}
-
} // namespace Quick
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/quick3d/quick3dscene2d/items/scene2d_p.h b/src/quick3d/quick3dscene2d/items/scene2d_p.h
index bd7874cd6..2f2b556ec 100644
--- a/src/quick3d/quick3dscene2d/items/scene2d_p.h
+++ b/src/quick3d/quick3dscene2d/items/scene2d_p.h
@@ -94,16 +94,13 @@ public:
void setOutput(Qt3DCore::QNodeId outputId);
void initializeSharedObject();
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool updateFbo(QOpenGLTexture *texture);
void syncRenderControl();
- void startGrabbing();
- void stopGrabbing();
- bool registerObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ bool registerObjectPickerEvents(Qt3DCore::QEntity *qentity);
void unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId);
- void handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev);
+ void handlePickEvent(int type, const QPickEvent *ev);
QOpenGLContext *m_context;
QOpenGLContext *m_shareContext;
@@ -126,6 +123,7 @@ public:
#ifdef QT_OPENGL_ES_2_ANGLE
bool m_usingAngle;
#endif
+ QVector<QMetaObject::Connection> m_connections;
};
} // Quick
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 006919512..b618eda55 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QSize;
+class QScreen;
namespace Qt3DCore {
class QAbstractFrameAdvanceService;
@@ -175,6 +176,8 @@ public:
// For QtQuick rendering
virtual void setOpenGLContext(QOpenGLContext *ctx) = 0;
+ virtual void setScreen(QScreen *) {}
+ virtual QScreen *screen() const { return nullptr; }
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
virtual QSurfaceFormat format() = 0;
diff --git a/src/render/backend/offscreensurfacehelper.cpp b/src/render/backend/offscreensurfacehelper.cpp
index 89dc6211f..38558d484 100644
--- a/src/render/backend/offscreensurfacehelper.cpp
+++ b/src/render/backend/offscreensurfacehelper.cpp
@@ -72,6 +72,7 @@ void OffscreenSurfaceHelper::createOffscreenSurface()
m_offscreenSurface = new QOffscreenSurface;
m_offscreenSurface->setParent(this);
m_offscreenSurface->setFormat(m_renderer->format());
+ m_offscreenSurface->setScreen(m_renderer->screen());
m_offscreenSurface->create();
}
diff --git a/src/render/backend/platformsurfacefilter.cpp b/src/render/backend/platformsurfacefilter.cpp
index 7458f607d..891e30c44 100644
--- a/src/render/backend/platformsurfacefilter.cpp
+++ b/src/render/backend/platformsurfacefilter.cpp
@@ -107,10 +107,6 @@ bool PlatformSurfaceFilter::eventFilter(QObject *obj, QEvent *e)
// If we remove it, the call to isSurfaceValid will
// implicitely return false
PlatformSurfaceFilter::m_surfacesValidity.remove(m_surface);
- if (m_obj) {
- m_obj->removeEventFilter(this);
- m_obj = nullptr;
- }
break;
}
diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp
index 58ff05dc0..40d8fca3d 100644
--- a/src/render/framegraph/framegraphnode.cpp
+++ b/src/render/framegraph/framegraphnode.cpp
@@ -123,6 +123,7 @@ QVector<FrameGraphNode *> FrameGraphNode::children() const
void FrameGraphNode::cleanup()
{
setParentId({});
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
void FrameGraphNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp
index 5080012fd..8bad46f5d 100644
--- a/src/render/framegraph/qlayerfilter.cpp
+++ b/src/render/framegraph/qlayerfilter.cpp
@@ -203,7 +203,7 @@ void QLayerFilter::addLayer(QLayer *layer)
if (!layer->parent())
layer->setParent(this);
- d->update();
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueAdded);
}
}
@@ -214,7 +214,7 @@ void QLayerFilter::removeLayer(QLayer *layer)
{
Q_ASSERT(layer);
Q_D(QLayerFilter);
- d->update();
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueRemoved);
d->m_layers.removeOne(layer);
// Remove bookkeeping connection
d->unregisterDestructionHelper(layer);
diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp
index 778d3fa1f..952657eb6 100644
--- a/src/render/framegraph/qrenderpassfilter.cpp
+++ b/src/render/framegraph/qrenderpassfilter.cpp
@@ -139,7 +139,7 @@ void QRenderPassFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueAdded);
}
}
@@ -151,7 +151,7 @@ void QRenderPassFilter::removeMatch(QFilterKey *filterKey)
Q_ASSERT(filterKey);
Q_D(QRenderPassFilter);
- d->update();
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -177,7 +177,7 @@ void QRenderPassFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -189,7 +189,7 @@ void QRenderPassFilter::removeParameter(QParameter *parameter)
Q_ASSERT(parameter);
Q_D(QRenderPassFilter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp
index 8c2c6ee7f..5341b3c7d 100644
--- a/src/render/framegraph/qrenderstateset.cpp
+++ b/src/render/framegraph/qrenderstateset.cpp
@@ -191,7 +191,7 @@ void QRenderStateSet::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -203,7 +203,7 @@ void QRenderStateSet::removeRenderState(QRenderState *state)
Q_ASSERT(state);
Q_D(QRenderStateSet);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
diff --git a/src/render/framegraph/qsubtreeenabler.cpp b/src/render/framegraph/qsubtreeenabler.cpp
index d2c25852b..e5d182d00 100644
--- a/src/render/framegraph/qsubtreeenabler.cpp
+++ b/src/render/framegraph/qsubtreeenabler.cpp
@@ -164,7 +164,7 @@ void QSubtreeEnabler::setEnablement(QSubtreeEnabler::Enablement enablement)
/*!
Requests that the subtree be enabled.
- A conveninence method intended to be used with \c SingleShot enablement.
+ A convenience method intended to be used with \c SingleShot enablement.
*/
void QSubtreeEnabler::requestUpdate()
{
diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp
index 03e6a8ca7..c22e83381 100644
--- a/src/render/framegraph/qtechniquefilter.cpp
+++ b/src/render/framegraph/qtechniquefilter.cpp
@@ -144,7 +144,7 @@ void QTechniqueFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueAdded);
}
}
@@ -155,7 +155,7 @@ void QTechniqueFilter::removeMatch(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechniqueFilter);
- d->update();
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -181,7 +181,7 @@ void QTechniqueFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -192,7 +192,7 @@ void QTechniqueFilter::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechniqueFilter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp
index d040150d5..d0c9f5805 100644
--- a/src/render/frontend/qcomputecommand.cpp
+++ b/src/render/frontend/qcomputecommand.cpp
@@ -66,7 +66,7 @@ namespace Qt3DRender {
/*!
\qmltype ComputeCommand
\since 5.7
- \inmodule Qt3DRender
+ \inqmlmodule Qt3D.Render
\inherits Component3D
\instantiates Qt3DRender::QComputeCommand
\brief Component to issue work for the compute shader on GPU.
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 159c11981..271eb9c11 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -562,6 +562,7 @@ void QRenderAspect::onRegistered()
// TO DO: Load proper Renderer class based on Qt configuration preferences
d->m_renderer = new Render::Renderer(d->m_renderType);
+ d->m_renderer->setScreen(d->m_screen);
d->m_renderer->setNodeManagers(d->m_nodeManagers);
// Create a helper for deferring creation of an offscreen surface used during cleanup
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 8ef4ecd12..62e373b11 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -60,6 +60,7 @@
QT_BEGIN_NAMESPACE
class QSurface;
+class QScreen;
namespace Qt3DRender {
@@ -106,6 +107,7 @@ public:
QVector<Render::QRenderPlugin *> m_renderPlugins;
QRenderAspect::RenderType m_renderType;
Render::OffscreenSurfaceHelper *m_offscreenHelper;
+ QScreen *m_screen = nullptr;
static QMutex m_pluginLock;
static QVector<QString> m_pluginConfig;
diff --git a/src/render/frontend/qrenderplugin_p.h b/src/render/frontend/qrenderplugin_p.h
index c34dabefc..110c8295a 100644
--- a/src/render/frontend/qrenderplugin_p.h
+++ b/src/render/frontend/qrenderplugin_p.h
@@ -75,6 +75,10 @@ protected:
{
aspect->registerBackendType(obj, functor);
}
+ void registerBackendType(QRenderAspect *aspect, const QMetaObject &obj, const Qt3DCore::QBackendNodeMapperPtr &functor, bool supportsSyncing)
+ {
+ aspect->registerBackendType(obj, functor, supportsSyncing);
+ }
void unregisterBackendType(QRenderAspect *aspect, const QMetaObject &obj)
{
aspect->unregisterBackendType(obj);
diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp
index 7269a8067..57eecd795 100644
--- a/src/render/frontend/qrendertarget.cpp
+++ b/src/render/frontend/qrendertarget.cpp
@@ -123,7 +123,7 @@ void QRenderTarget::addOutput(QRenderTargetOutput *output)
if (!output->parent())
output->setParent(this);
- d->update();
+ d->updateNode(output, "output", Qt3DCore::PropertyValueAdded);
}
}
@@ -134,7 +134,7 @@ void QRenderTarget::removeOutput(QRenderTargetOutput *output)
{
Q_D(QRenderTarget);
- d->update();
+ d->updateNode(output, "output", Qt3DCore::PropertyValueRemoved);
d->m_outputs.removeOne(output);
// Remove bookkeeping connection
d->unregisterDestructionHelper(output);
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 4909acaef..470dbfe59 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -44,6 +44,7 @@
#include <QPair>
#include <math.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -55,6 +56,9 @@ namespace {
// returns true and intersection point q; false otherwise
bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, Vector3D *q = nullptr)
{
+ if (s.isNull())
+ return false;
+
const Vector3D p = ray.origin();
const Vector3D d = ray.direction();
const Vector3D m = p - s.center();
@@ -139,11 +143,31 @@ inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector
inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points)
{
- // Calculate the sphere encompassing two axially extreme points
- sphereFromExtremePoints(s, points);
-
- // Now make sure the sphere bounds all points by growing if needed
- s.expandToContain(points);
+ //def bounding_sphere(points):
+ // dist = lambda a,b: ((a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2)**0.5
+ // x = points[0]
+ // y = max(points,key= lambda p: dist(p,x) )
+ // z = max(points,key= lambda p: dist(p,y) )
+ // bounding_sphere = (((y[0]+z[0])/2,(y[1]+z[1])/2,(y[2]+z[2])/2), dist(y,z)/2)
+ //
+ // exterior_points = [p for p in points if dist(p,bounding_sphere[0]) > bounding_sphere[1] ]
+ // while ( len(exterior_points) > 0 ):
+ // pt = exterior_points.pop()
+ // if (dist(pt, bounding_sphere[0]) > bounding_sphere[1]):
+ // bounding_sphere = (bounding_sphere[0],dist(pt,bounding_sphere[0]))
+ //
+ // return bounding_sphere
+
+ const Vector3D x = points[0];
+ const Vector3D y = *std::max_element(points.begin(), points.end(), [&x](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - x).lengthSquared() < (rhs - x).lengthSquared(); });
+ const Vector3D z = *std::max_element(points.begin(), points.end(), [&y](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - y).lengthSquared() < (rhs - y).lengthSquared(); });
+
+ const Vector3D center = (y + z) * 0.5f;
+ const Vector3D maxDistPt = *std::max_element(points.begin(), points.end(), [&center](const Vector3D& lhs, const Vector3D& rhs){ return (lhs - center).lengthSquared() < (rhs - center).lengthSquared(); });
+ const float radius = (maxDistPt - center).length();
+
+ s.setCenter(center);
+ s.setRadius(radius);
}
} // anonymous namespace
@@ -169,6 +193,12 @@ void Sphere::initializeFromPoints(const QVector<Vector3D> &points)
void Sphere::expandToContain(const Vector3D &p)
{
+ if (isNull()) {
+ m_center = p;
+ m_radius = 0.0f;
+ return;
+ }
+
const Vector3D d = p - m_center;
const float dist2 = d.lengthSquared();
@@ -184,6 +214,13 @@ void Sphere::expandToContain(const Vector3D &p)
void Sphere::expandToContain(const Sphere &sphere)
{
+ if (isNull()) {
+ *this = sphere;
+ return;
+ } else if (sphere.isNull()) {
+ return;
+ }
+
const Vector3D d(sphere.m_center - m_center);
const float dist2 = d.lengthSquared();
@@ -206,6 +243,9 @@ void Sphere::expandToContain(const Sphere &sphere)
Sphere Sphere::transformed(const Matrix4x4 &mat) const
{
+ if (isNull())
+ return *this;
+
// Transform extremities in x, y, and z directions to find extremities
// of the resulting ellipsoid
Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f));
diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h
index 10cf92091..b7585f85a 100644
--- a/src/render/frontend/sphere_p.h
+++ b/src/render/frontend/sphere_p.h
@@ -69,7 +69,7 @@ class Q_3DRENDERSHARED_PRIVATE_EXPORT Sphere : public RayCasting::BoundingSphere
public:
inline Sphere(Qt3DCore::QNodeId i = Qt3DCore::QNodeId())
: m_center()
- , m_radius(0.0f)
+ , m_radius(-1.0f)
, m_id(i)
{}
@@ -82,7 +82,7 @@ public:
void setCenter(const Vector3D &c);
Vector3D center() const override;
- inline bool isNull() { return m_center == Vector3D() && m_radius == 0.0f; }
+ bool isNull() const { return m_center == Vector3D() && m_radius == -1.0f; }
void setRadius(float r);
float radius() const override;
@@ -131,7 +131,9 @@ inline Vector3D Sphere::center() const
inline void Sphere::setRadius(float r)
{
- m_radius = r;
+ Q_ASSERT(r >= 0.0f);
+ if (r >= 0.0f)
+ m_radius = r;
}
inline float Sphere::radius() const
@@ -142,11 +144,14 @@ inline float Sphere::radius() const
inline void Sphere::clear()
{
m_center = Vector3D();
- m_radius = 0.0f;
+ m_radius = -1.0f;
}
inline bool intersects(const Sphere &a, const Sphere &b)
{
+ if (a.isNull() || b.isNull())
+ return false;
+
// Calculate squared distance between sphere centers
const Vector3D d = a.center() - b.center();
const float distSq = Vector3D::dotProduct(d, d);
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 998db3640..0ce81efc1 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -130,8 +130,10 @@ void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (!node)
return;
- if (firstTime && m_manager != nullptr)
+ if (firstTime && m_manager != nullptr) {
m_manager->addBufferReference(peerId());
+ m_bufferDirty = true;
+ }
m_syncData = node->isSyncData();
m_access = node->accessType();
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index f27005f2b..d27da25c7 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -329,7 +329,7 @@ void QBuffer::setData(const QByteArray &bytes)
Q_D(QBuffer);
if (bytes != d->m_data) {
d->m_data = bytes;
- Qt3DCore::QNodePrivate::get(this)->update();
+ d->update();
emit dataChanged(bytes);
}
}
diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp
index 4b0bca3b3..48f054bce 100644
--- a/src/render/geometry/qgeometry.cpp
+++ b/src/render/geometry/qgeometry.cpp
@@ -194,7 +194,7 @@ void QGeometry::addAttribute(QAttribute *attribute)
if (!attribute->parent())
attribute->setParent(this);
- d->update();
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
@@ -209,7 +209,7 @@ void QGeometry::removeAttribute(QAttribute *attribute)
d->m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
- d->update();
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
}
void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute)
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 113dc34ce..9af2f4f38 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -90,30 +90,42 @@ public:
m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
- // Calculate squared distance for the pairs of points
- const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
- const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
- const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared();
-
- // Select most distant pair
- Vector3D p = findExtremePoints.xMinPt;
- Vector3D q = findExtremePoints.xMaxPt;
- if (yDist2 > xDist2 && yDist2 > zDist2) {
- p = findExtremePoints.yMinPt;
- q = findExtremePoints.yMaxPt;
+ FindMaxDistantPoint maxDistantPointY(m_manager);
+ maxDistantPointY.setReferencePoint = true;
+ if (!maxDistantPointY.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- if (zDist2 > xDist2 && zDist2 > yDist2) {
- p = findExtremePoints.zMinPt;
- q = findExtremePoints.zMaxPt;
+ if (maxDistantPointY.hasNoPoints)
+ return false;
+
+ //const Vector3D x = maxDistantPointY.referencePt;
+ const Vector3D y = maxDistantPointY.maxDistPt;
+
+ FindMaxDistantPoint maxDistantPointZ(m_manager);
+ maxDistantPointZ.setReferencePoint = false;
+ maxDistantPointZ.referencePt = y;
+ if (!maxDistantPointZ.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
+ }
+ const Vector3D z = maxDistantPointZ.maxDistPt;
+
+ const Vector3D center = (y + z) * 0.5f;
+
+ FindMaxDistantPoint maxDistantPointCenter(m_manager);
+ maxDistantPointCenter.setReferencePoint = false;
+ maxDistantPointCenter.referencePt = center;
+ if (!maxDistantPointCenter.apply(positionAttribute, indexAttribute, drawVertexCount,
+ primitiveRestartEnabled, primitiveRestartIndex)) {
+ return false;
}
- const Vector3D c = 0.5f * (p + q);
- m_volume.setCenter(c);
- m_volume.setRadius((q - c).length());
+ const float radius = (center - maxDistantPointCenter.maxDistPt).length();
- ExpandSphere expandSphere(m_manager, m_volume);
- if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount,
- primitiveRestartEnabled, primitiveRestartIndex))
+ m_volume = Qt3DRender::Render::Sphere(center, radius);
+
+ if (m_volume.isNull())
return false;
return true;
@@ -172,18 +184,34 @@ private:
}
};
- class ExpandSphere : public Buffer3fVisitor
+ class FindMaxDistantPoint : public Buffer3fVisitor
{
public:
- ExpandSphere(NodeManagers *manager, Sphere& volume)
- : Buffer3fVisitor(manager), m_volume(volume)
+ FindMaxDistantPoint(NodeManagers *manager)
+ : Buffer3fVisitor(manager)
{ }
- Sphere& m_volume;
+ float maxLengthSquared = 0.0f;
+ Vector3D maxDistPt;
+ Vector3D referencePt;
+ bool setReferencePoint = false;
+ bool hasNoPoints = true;
+
void visit(uint ndx, float x, float y, float z) override
{
Q_UNUSED(ndx);
- m_volume.expandToContain(Vector3D(x, y, z));
+ const Vector3D p = Vector3D(x, y, z);
+
+ if (hasNoPoints && setReferencePoint) {
+ maxLengthSquared = 0.0f;
+ referencePt = p;
+ }
+ const float lengthSquared = (p - referencePt).lengthSquared();
+ if ( lengthSquared >= maxLengthSquared ) {
+ maxDistPt = p;
+ maxLengthSquared = lengthSquared;
+ }
+ hasNoPoints = false;
}
};
};
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index a88e861b6..2973ee100 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -41,7 +41,11 @@
#include "qpicktriangleevent.h"
#include "qpicklineevent.h"
#include "qpickpointevent.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/qviewport.h>
#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/entity_p.h>
@@ -65,6 +69,82 @@ using namespace Qt3DRender::RayCasting;
namespace Render {
+class PickBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ PickBoundingVolumeJobPrivate() = default;
+ ~PickBoundingVolumeJobPrivate() override = default;
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ enum CustomEventType {
+ MouseButtonClick = QEvent::User,
+ };
+
+ struct EventDetails {
+ Qt3DCore::QNodeId pickerId;
+ int sourceEventType;
+ QPickEventPtr resultingEvent;
+ Qt3DCore::QNodeId viewportNodeId;
+ };
+
+ QVector<EventDetails> dispatches;
+};
+
+
+void PickBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ using namespace Qt3DCore;
+ QNodeId previousId;
+ QObjectPicker *node = nullptr;
+
+ for (auto res: qAsConst(dispatches)) {
+ if (previousId != res.pickerId) {
+ node = qobject_cast<QObjectPicker *>(manager->lookupNode(res.pickerId));
+ previousId = res.pickerId;
+ }
+ if (!node)
+ continue;
+
+ QObjectPickerPrivate *dnode = static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+
+ // resolve front end details
+ QPickEvent *pickEvent = res.resultingEvent.data();
+ if (pickEvent) {
+ QPickEventPrivate *dpickEvent = QPickEventPrivate::get(pickEvent);
+ dpickEvent->m_viewport = static_cast<QViewport *>(manager->lookupNode(res.viewportNodeId));
+ dpickEvent->m_entityPtr = static_cast<QEntity *>(manager->lookupNode(dpickEvent->m_entity));
+ }
+
+ // dispatch event
+ switch (res.sourceEventType) {
+ case QEvent::MouseButtonPress:
+ dnode->pressedEvent(pickEvent);
+ break;
+ case QEvent::MouseButtonRelease:
+ dnode->releasedEvent(pickEvent);
+ break;
+ case MouseButtonClick:
+ dnode->clickedEvent(pickEvent);
+ break;
+ case QEvent::MouseMove:
+ dnode->movedEvent(pickEvent);
+ break;
+ case QEvent::Enter:
+ emit node->entered();
+ dnode->setContainsMouse(true);
+ break;
+ case QEvent::Leave:
+ dnode->setContainsMouse(false);
+ emit node->exited();
+ break;
+ default: Q_UNREACHABLE();
+ }
+ }
+
+ dispatches.clear();
+}
+
namespace {
void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers)
@@ -109,10 +189,10 @@ void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &e
} // anonymous
PickBoundingVolumeJob::PickBoundingVolumeJob()
- : AbstractPickingJob()
+ : AbstractPickingJob(*new PickBoundingVolumeJobPrivate)
, m_pickersDirty(true)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0)
}
void PickBoundingVolumeJob::setRoot(Entity *root)
@@ -122,12 +202,12 @@ void PickBoundingVolumeJob::setRoot(Entity *root)
void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents)
{
- m_pendingMouseEvents = pendingEvents;
+ m_pendingMouseEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
{
- m_pendingKeyEvents = pendingEvents;
+ m_pendingKeyEvents.append(pendingEvents);
}
void PickBoundingVolumeJob::markPickersDirty()
@@ -300,6 +380,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
bool allHitsRequested,
Qt3DCore::QNodeId viewportNodeId)
{
+ Q_D(PickBoundingVolumeJob);
+
ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker);
// If we have hits
if (!sphereHits.isEmpty()) {
@@ -383,37 +465,43 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
// Store pressed object handle
m_currentPicker = objectPickerHandle;
// Send pressed event to m_currentPicker
- objectPicker->onPressed(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(true);
break;
}
case QEvent::MouseButtonRelease: {
// Only send the release event if it was pressed
- if (objectPicker->isPressed())
- objectPicker->onReleased(pickEvent, viewportNodeId);
+ if (objectPicker->isPressed()) {
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(false);
+ }
if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) {
- objectPicker->onClicked(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
m_currentPicker = HObjectPicker();
}
break;
}
#if QT_CONFIG(gestures)
case QEvent::Gesture: {
- objectPicker->onClicked(pickEvent, viewportNodeId);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
break;
}
#endif
case QEvent::MouseMove: {
- if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) {
- objectPicker->onMoved(pickEvent, viewportNodeId);
- }
+ if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled())
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
Q_FALLTHROUGH(); // fallthrough
}
case QEvent::HoverMove: {
if (!m_hoveredPickers.contains(objectPickerHandle)) {
if (objectPicker->isHoverEnabled()) {
// Send entered event to objectPicker
- objectPicker->onEntered();
+ d->dispatches.push_back({objectPicker->peerId(), QEvent::Enter, pickEvent, viewportNodeId});
// and save it in the hoveredPickers
m_hoveredPickers.push_back(objectPickerHandle);
}
@@ -440,7 +528,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
if (lastCurrentPicker != nullptr) {
m_currentPicker = HObjectPicker();
QPickEventPtr pickEvent(new QPickEvent);
- lastCurrentPicker->onReleased(pickEvent, viewportNodeId);
+ lastCurrentPicker->setPressed(false);
+ d->dispatches.push_back({lastCurrentPicker->peerId(), event.type(), pickEvent, viewportNodeId});
}
break;
}
@@ -452,12 +541,15 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
void PickBoundingVolumeJob::clearPreviouslyHoveredPickers()
{
+ Q_D(PickBoundingVolumeJob);
+
for (const HObjectPicker &pickHandle : qAsConst(m_hoveredPickersToClear)) {
ObjectPicker *pick = m_manager->objectPickerManager()->data(pickHandle);
if (pick)
- pick->onExited();
+ d->dispatches.push_back({pick->peerId(), QEvent::Leave, {}, {}});
m_hoveredPickers.removeAll(pickHandle);
}
+
m_hoveredPickersToClear.clear();
}
diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h
index e3d847916..49b11b775 100644
--- a/src/render/jobs/pickboundingvolumejob_p.h
+++ b/src/render/jobs/pickboundingvolumejob_p.h
@@ -70,6 +70,7 @@ namespace Qt3DRender {
class QViewport;
namespace Render {
+class PickBoundingVolumeJobPrivate;
namespace PickingUtils {
typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList;
@@ -101,6 +102,8 @@ protected:
Qt3DCore::QNodeId viewportNodeId);
private:
+ Q_DECLARE_PRIVATE(PickBoundingVolumeJob)
+
void clearPreviouslyHoveredPickers();
QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents;
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index 35f4d64a9..8637a92d4 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -65,6 +65,8 @@ QEffectPrivate::QEffectPrivate()
An QEffect instance should be shared among several QMaterial instances when possible.
+ \note QEffect node can not be disabled.
+
\code
QEffect *effect = new QEffect();
@@ -111,6 +113,8 @@ QEffectPrivate::QEffectPrivate()
A Parameter defined on an Effect is overridden by a QParameter (of the same
name) defined in a Material, TechniqueFilter, RenderPassFilter.
+ \note Effect node can not be disabled.
+
\code
Effect {
id: effect
@@ -188,7 +192,7 @@ void QEffect::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -202,7 +206,7 @@ void QEffect::removeParameter(QParameter *parameter)
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
}
/*!
@@ -234,7 +238,7 @@ void QEffect::addTechnique(QTechnique *t)
if (!t->parent())
t->setParent(this);
- d->update();
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueAdded);
}
}
@@ -245,7 +249,7 @@ void QEffect::removeTechnique(QTechnique *t)
{
Q_D(QEffect);
if (t)
- d->update();
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueRemoved);
d->m_techniques.removeOne(t);
// Remove bookkeeping connection
d->unregisterDestructionHelper(t);
diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp
index dc968400b..2105da987 100644
--- a/src/render/materialsystem/qfilterkey.cpp
+++ b/src/render/materialsystem/qfilterkey.cpp
@@ -60,6 +60,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
Filter keys are used by QTechnique and QRenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note QFilterKey node can not be disabled.
*/
/*!
@@ -73,6 +75,8 @@ QFilterKeyPrivate::QFilterKeyPrivate()
A FilterKey is a storage type for filter key and value pair.
Filter keys are used by Technique and RenderPass to specify at which stage of rendering the
technique or the render pass is used.
+
+ \note FilterKey node can not be disabled.
*/
QFilterKey::QFilterKey(QNode *parent)
diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp
index db286de6b..edd227500 100644
--- a/src/render/materialsystem/qmaterial.cpp
+++ b/src/render/materialsystem/qmaterial.cpp
@@ -272,7 +272,7 @@ void QMaterial::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -283,7 +283,7 @@ void QMaterial::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QMaterial);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
}
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 77eda8c8e..969882564 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -76,6 +76,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note Parameter node can not be disabled.
+
\code
Parameter {
name: "diffuseValues[0]"
@@ -138,6 +140,8 @@
\note when the targeted uniform is an array, the name should be the name
of the uniform with [0] appended to it.
+ \note QParameter node can not be disabled.
+
\code
QParameter *param = new QParameter();
QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp
index e9dd50325..dcb831b13 100644
--- a/src/render/materialsystem/qrenderpass.cpp
+++ b/src/render/materialsystem/qrenderpass.cpp
@@ -274,7 +274,7 @@ void QRenderPass::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -285,7 +285,7 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeyList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -322,7 +322,7 @@ void QRenderPass::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -333,7 +333,7 @@ void QRenderPass::removeRenderState(QRenderState *state)
{
Q_ASSERT(state);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
@@ -369,7 +369,7 @@ void QRenderPass::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -380,7 +380,7 @@ void QRenderPass::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QRenderPass);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/materialsystem/qshaderprogrambuilder.cpp b/src/render/materialsystem/qshaderprogrambuilder.cpp
index cafe23ee4..6613661d1 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.cpp
+++ b/src/render/materialsystem/qshaderprogrambuilder.cpp
@@ -79,6 +79,47 @@ QShaderProgramBuilderPrivate::QShaderProgramBuilderPrivate()
{
}
+void QShaderProgramBuilderPrivate::setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type)
+{
+ Q_Q(QShaderProgramBuilder);
+ const bool blocked = q->blockNotifications(true);
+
+ switch (type) {
+ case QShaderProgram::Vertex: {
+ m_vertexShaderCode = code;
+ emit q->vertexShaderCodeChanged(m_vertexShaderCode);
+ break;
+ }
+ case QShaderProgram::Fragment:{
+ m_fragmentShaderCode = code;
+ emit q->fragmentShaderCodeChanged(m_fragmentShaderCode);
+ break;
+ }
+ case QShaderProgram::Geometry: {
+ m_geometryShaderCode = code;
+ emit q->geometryShaderCodeChanged(m_geometryShaderCode);
+ break;
+ }
+ case QShaderProgram::Compute: {
+ m_computeShaderCode = code;
+ emit q->computeShaderCodeChanged(m_computeShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationControl: {
+ m_tessControlShaderCode = code;
+ emit q->tessellationControlShaderCodeChanged(m_tessControlShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationEvaluation: {
+ m_tessEvalShaderCode = code;
+ emit q->tessellationEvaluationShaderCodeChanged(m_tessEvalShaderCode);
+ break;
+ }
+ }
+
+ q->blockNotifications(blocked);
+}
+
QShaderProgramBuilder::QShaderProgramBuilder(QNode *parent)
: QNode(*new QShaderProgramBuilderPrivate, parent)
{
@@ -94,53 +135,6 @@ QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Q
{
}
-void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QShaderProgramBuilder);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("generatedShaderCode")) {
- const bool blocked = blockNotifications(true);
- const QPair<int, QByteArray> data = e->value().value<QPair<int, QByteArray>>();
-
- switch (data.first) {
- case QShaderProgram::Vertex: {
- d->m_vertexShaderCode = data.second;
- emit vertexShaderCodeChanged(d->m_vertexShaderCode);
- break;
- }
- case QShaderProgram::Fragment:{
- d->m_fragmentShaderCode = data.second;
- emit fragmentShaderCodeChanged(d->m_fragmentShaderCode);
- break;
- }
- case QShaderProgram::Geometry: {
- d->m_geometryShaderCode = data.second;
- emit geometryShaderCodeChanged(d->m_geometryShaderCode);
- break;
- }
- case QShaderProgram::Compute: {
- d->m_computeShaderCode = data.second;
- emit computeShaderCodeChanged(d->m_computeShaderCode);
- break;
- }
- case QShaderProgram::TessellationControl: {
- d->m_tessControlShaderCode = data.second;
- emit tessellationControlShaderCodeChanged(d->m_tessControlShaderCode);
- break;
- }
- case QShaderProgram::TessellationEvaluation: {
- d->m_tessEvalShaderCode = data.second;
- emit tessellationEvaluationShaderCodeChanged(d->m_tessEvalShaderCode);
- break;
- }
- }
-
- blockNotifications(blocked);
- }
- }
-}
-
/*!
\qmlproperty string ShaderProgramBuilder::shaderProgram
diff --git a/src/render/materialsystem/qshaderprogrambuilder.h b/src/render/materialsystem/qshaderprogrambuilder.h
index 184093730..5dc6b54ff 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.h
+++ b/src/render/materialsystem/qshaderprogrambuilder.h
@@ -117,7 +117,6 @@ Q_SIGNALS:
protected:
explicit QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QShaderProgramBuilder)
diff --git a/src/render/materialsystem/qshaderprogrambuilder_p.h b/src/render/materialsystem/qshaderprogrambuilder_p.h
index 2ac765a1d..22f8e6e58 100644
--- a/src/render/materialsystem/qshaderprogrambuilder_p.h
+++ b/src/render/materialsystem/qshaderprogrambuilder_p.h
@@ -52,6 +52,8 @@
//
#include <private/qnode_p.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qshaderprogrambuilder.h>
#include <QtCore/qurl.h>
@@ -60,7 +62,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
{
public:
QShaderProgramBuilderPrivate();
@@ -80,6 +82,8 @@ public:
QByteArray m_geometryShaderCode;
QByteArray m_fragmentShaderCode;
QByteArray m_computeShaderCode;
+
+ void setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type);
};
struct QShaderProgramBuilderData
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index 2b96aa285..a9b7ca82b 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -87,6 +87,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note Technique node can not be disabled.
+
\qml
Technique {
id: gl3Technique
@@ -152,6 +154,8 @@ QTechniquePrivate::~QTechniquePrivate()
QSurfaceFormat::setDefaultFormat(). Setting the QSurfaceFormat on the view
will likely have no effect on Qt3D related rendering.
+ \note QTechnique node can not be disabled.
+
\code
QTechnique *gl3Technique = new QTechnique();
@@ -254,7 +258,7 @@ void QTechnique::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -265,7 +269,7 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechnique);
- d->update();
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeys.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -301,7 +305,7 @@ void QTechnique::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -312,7 +316,7 @@ void QTechnique::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechnique);
- d->update();
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
@@ -338,7 +342,7 @@ void QTechnique::addRenderPass(QRenderPass *pass)
if (!pass->parent())
pass->setParent(this);
- d->update();
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
}
}
@@ -349,7 +353,7 @@ void QTechnique::removeRenderPass(QRenderPass *pass)
{
Q_ASSERT(pass);
Q_D(QTechnique);
- d->update();
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
d->m_renderPasses.removeOne(pass);
// Remove bookkeeping connection
d->unregisterDestructionHelper(pass);
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index f35fba9fa..58709b37e 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -64,6 +64,7 @@ Shader::Shader()
, m_dna(0)
, m_graphicsContext(nullptr)
, m_status(QShaderProgram::NotReady)
+ , m_requiresFrontendSync(false)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
}
@@ -170,8 +171,9 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co
m_shaderCode[type] = code;
m_isLoaded = false;
- setStatus(QShaderProgram::NotReady);
+ m_status = QShaderProgram::NotReady;
updateDNA();
+ m_requiresFrontendSync = true;
markDirty(AbstractRenderer::ShadersDirty);
}
@@ -237,20 +239,13 @@ ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName)
return ShaderStorageBlock();
}
-// To be called from a worker thread
-void Shader::submitPendingNotifications()
-{
- const QVector<Qt3DCore::QPropertyUpdatedChangePtr> notifications = std::move(m_pendingNotifications);
- for (const Qt3DCore::QPropertyUpdatedChangePtr &notification : notifications)
- notifyObservers(notification);
-}
-
void Shader::prepareUniforms(ShaderParameterPack &pack)
{
const PackUniformHash &values = pack.uniforms();
auto it = values.cbegin();
const auto end = values.cend();
+
while (it != end) {
// Find if there's a uniform with the same name id
for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
@@ -412,32 +407,21 @@ void Shader::initializeFromReference(const Shader &other)
m_shaderStorageBlockNames = other.m_shaderStorageBlockNames;
m_shaderStorageBlocks = other.m_shaderStorageBlocks;
m_isLoaded = other.m_isLoaded;
- setStatus(other.status());
- setLog(other.log());
+ m_status = other.m_status;
+ m_log = other.m_log;
+ m_requiresFrontendSync = true;
}
void Shader::setLog(const QString &log)
{
- if (log != m_log) {
- m_log = log;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("log");
- e->setValue(QVariant::fromValue(m_log));
- m_pendingNotifications.push_back(e);
- }
+ m_log = log;
+ m_requiresFrontendSync = true;
}
void Shader::setStatus(QShaderProgram::Status status)
{
- if (status != m_status) {
- m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- m_pendingNotifications.push_back(e);
- }
+ m_status = status;
+ m_requiresFrontendSync = true;
}
} // namespace Render
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index f8cdde3b7..fe1a401d9 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -122,8 +122,8 @@ public:
inline QString log() const { return m_log; }
inline QShaderProgram::Status status() const { return m_status; }
- void submitPendingNotifications();
- inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); }
+ inline bool requiresFrontendSync() const { return m_requiresFrontendSync; }
+ inline void unsetRequiresFrontendSync() { m_requiresFrontendSync = false; }
private:
QVector<QString> m_uniformsNames;
@@ -155,8 +155,7 @@ private:
QMetaObject::Connection m_contextConnection;
QString m_log;
QShaderProgram::Status m_status;
-
- QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications;
+ bool m_requiresFrontendSync;
void updateDNA();
diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp
index 6116ca56b..23f1400c9 100644
--- a/src/render/materialsystem/shaderbuilder.cpp
+++ b/src/render/materialsystem/shaderbuilder.cpp
@@ -115,31 +115,6 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-
-namespace {
-
-QShaderProgram::ShaderType toQShaderProgramType(ShaderBuilder::ShaderType type)
-{
- switch (type) {
- case ShaderBuilder::ShaderType::Vertex:
- return QShaderProgram::Vertex;
- case ShaderBuilder::ShaderType::TessellationControl:
- return QShaderProgram::TessellationControl;
- case ShaderBuilder::ShaderType::TessellationEvaluation:
- return QShaderProgram::TessellationEvaluation;
- case ShaderBuilder::ShaderType::Geometry:
- return QShaderProgram::Geometry;
- case ShaderBuilder::ShaderType::Fragment:
- return QShaderProgram::Fragment;
- case ShaderBuilder::ShaderType::Compute:
- return QShaderProgram::Compute;
- default:
- Q_UNREACHABLE();
- }
-}
-
-} // anonymous
-
QString ShaderBuilder::getPrototypesFile()
{
return qt3dGlobalShaderPrototypes->prototypesFile();
@@ -170,6 +145,7 @@ void ShaderBuilder::cleanup()
m_enabledLayers.clear();
m_graphs.clear();
m_dirtyTypes.clear();
+ m_pendingUpdates.clear();
QBackendNode::setEnabled(false);
}
@@ -191,7 +167,7 @@ void ShaderBuilder::setEnabledLayers(const QStringList &layers)
m_enabledLayers = layers;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
@@ -208,18 +184,18 @@ void ShaderBuilder::setGraphicsApi(const GraphicsApiFilterData &graphicsApi)
return;
m_graphicsApi = graphicsApi;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
}
-QUrl ShaderBuilder::shaderGraph(ShaderBuilder::ShaderType type) const
+QUrl ShaderBuilder::shaderGraph(QShaderProgram::ShaderType type) const
{
return m_graphs.value(type);
}
-void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &url)
+void ShaderBuilder::setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url)
{
if (url != m_graphs.value(type)) {
m_graphs.insert(type, url);
@@ -227,17 +203,17 @@ void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &u
}
}
-QByteArray ShaderBuilder::shaderCode(ShaderBuilder::ShaderType type) const
+QByteArray ShaderBuilder::shaderCode(QShaderProgram::ShaderType type) const
{
return m_codes.value(type);
}
-bool ShaderBuilder::isShaderCodeDirty(ShaderBuilder::ShaderType type) const
+bool ShaderBuilder::isShaderCodeDirty(QShaderProgram::ShaderType type) const
{
return m_dirtyTypes.contains(type);
}
-void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
+void ShaderBuilder::generateCode(QShaderProgram::ShaderType type)
{
const auto graphPath = QUrlHelper::urlToLocalFileOrQrc(shaderGraph(type));
QFile file(graphPath);
@@ -273,12 +249,9 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
m_codes.insert(type, QShaderProgramPrivate::deincludify(code, graphPath + QStringLiteral(".glsl")));
m_dirtyTypes.remove(type);
- // Send notification to the frontend
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- propertyChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- propertyChange->setPropertyName("generatedShaderCode");
- propertyChange->setValue(QVariant::fromValue(qMakePair(int(toQShaderProgramType(type)), m_codes.value(type))));
- notifyObservers(propertyChange);
+ m_pendingUpdates.push_back({ peerId(),
+ type,
+ m_codes.value(type) });
}
void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
@@ -305,13 +278,13 @@ void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
markDirty(AbstractRenderer::ShadersDirty);
}
- static const std::pair<ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
- {Vertex, &QShaderProgramBuilder::vertexShaderGraph},
- {TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
- {TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
- {Geometry, &QShaderProgramBuilder::geometryShaderGraph},
- {Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
- {Compute, &QShaderProgramBuilder::computeShaderGraph},
+ static const std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
+ {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph},
+ {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
+ {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
+ {QShaderProgram::Geometry, &QShaderProgramBuilder::geometryShaderGraph},
+ {QShaderProgram::Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
+ {QShaderProgram::Compute, &QShaderProgramBuilder::computeShaderGraph},
};
for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) {
diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h
index 6b92d3114..0a799afaa 100644
--- a/src/render/materialsystem/shaderbuilder_p.h
+++ b/src/render/materialsystem/shaderbuilder_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/qgraphicsapifilter_p.h>
@@ -60,18 +61,16 @@ namespace Qt3DRender {
namespace Render {
+struct ShaderBuilderUpdate
+{
+ Qt3DCore::QNodeId builderId;
+ Qt3DRender::QShaderProgram::ShaderType shaderType;
+ QByteArray shaderCode;
+};
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilder : public BackendNode
{
public:
- enum ShaderType {
- Vertex = 0,
- TessellationControl,
- TessellationEvaluation,
- Geometry,
- Fragment,
- Compute
- };
-
static QString getPrototypesFile();
static void setPrototypesFile(const QString &file);
static QStringList getPrototypeNames();
@@ -86,25 +85,28 @@ public:
GraphicsApiFilterData graphicsApi() const;
void setGraphicsApi(const GraphicsApiFilterData &graphicsApi);
- QUrl shaderGraph(ShaderType type) const;
- void setShaderGraph(ShaderType type, const QUrl &url);
+ QUrl shaderGraph(QShaderProgram::ShaderType type) const;
+ void setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url);
- QByteArray shaderCode(ShaderType type) const;
- bool isShaderCodeDirty(ShaderType type) const;
+ QByteArray shaderCode(QShaderProgram::ShaderType type) const;
+ bool isShaderCodeDirty(QShaderProgram::ShaderType type) const;
- void generateCode(ShaderType type);
+ void generateCode(QShaderProgram::ShaderType type);
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+ QVector<ShaderBuilderUpdate> takePendingUpdates() { return std::move(m_pendingUpdates); }
+
private:
void setEnabledLayers(const QStringList &layers);
GraphicsApiFilterData m_graphicsApi;
Qt3DCore::QNodeId m_shaderProgramId;
QStringList m_enabledLayers;
- QHash<ShaderType, QUrl> m_graphs;
- QHash<ShaderType, QByteArray> m_codes;
- QSet<ShaderType> m_dirtyTypes;
+ QHash<QShaderProgram::ShaderType, QUrl> m_graphs;
+ QHash<QShaderProgram::ShaderType, QByteArray> m_codes;
+ QSet<QShaderProgram::ShaderType> m_dirtyTypes;
+ QVector<ShaderBuilderUpdate> m_pendingUpdates;
};
} // namespace Render
diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp
index e278d6b6f..84169586e 100644
--- a/src/render/picking/objectpicker.cpp
+++ b/src/render/picking/objectpicker.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -100,7 +99,6 @@ void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstT
markDirty(AbstractRenderer::AllDirty);
notifyJob();
}
-
}
void ObjectPicker::notifyJob()
@@ -124,58 +122,9 @@ bool ObjectPicker::isDragEnabled() const
return m_dragEnabled;
}
-void ObjectPicker::onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("clicked");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- notifyObservers(e);
-}
-
-void ObjectPicker::onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("moved");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- notifyObservers(e);
-}
-
-void ObjectPicker::onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("pressed");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- m_isPressed = true;
- notifyObservers(e);
-}
-
-void ObjectPicker::onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("released");
- e->setValue(QVariant::fromValue(QObjectPickerEvent { event, viewportNodeId }));
- m_isPressed = false;
- notifyObservers(e);
-}
-
-void ObjectPicker::onEntered()
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("entered");
- notifyObservers(e);
-}
-
-void ObjectPicker::onExited()
+void ObjectPicker::setPressed(bool pressed)
{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("exited");
- notifyObservers(e);
+ m_isPressed = pressed;
}
void ObjectPicker::setPriority(int priority)
diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h
index b4f7d073c..49c8de770 100644
--- a/src/render/picking/objectpicker_p.h
+++ b/src/render/picking/objectpicker_p.h
@@ -74,12 +74,7 @@ public:
bool isHoverEnabled() const;
bool isDragEnabled() const;
- void onClicked(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onMoved(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onPressed(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onReleased(QPickEventPtr event, Qt3DCore::QNodeId viewportNodeId);
- void onEntered();
- void onExited();
+ void setPressed(bool pressed);
// Needed for unit tests
void setPriority(int priority);
diff --git a/src/render/picking/picking.pri b/src/render/picking/picking.pri
index 89c549de0..189d64bb6 100644
--- a/src/render/picking/picking.pri
+++ b/src/render/picking/picking.pri
@@ -7,6 +7,7 @@ HEADERS += \
$$PWD/qpicklineevent.h \
$$PWD/qpickpointevent.h \
$$PWD/qpicktriangleevent.h \
+ $$PWD/qpicktriangleevent_p.h \
$$PWD/objectpicker_p.h \
$$PWD/pickeventfilter_p.h \
$$PWD/qobjectpicker_p.h \
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 9537d4982..7d9741f21 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -82,6 +82,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
+
\since 5.6
*/
@@ -115,6 +118,9 @@ namespace Qt3DRender {
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
+
+ \note The camera far plane value affects picking and produces incorrect results due to
+ floating-point precision if it is greater than ~100 000.
*/
/*!
@@ -352,33 +358,6 @@ int QObjectPicker::priority() const
return d->m_priority;
}
-/*! \internal */
-void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QObjectPicker);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- // TO DO: Complete this part
- // to emit the correct signals
- const QByteArray propertyName = e->propertyName();
- if (propertyName == QByteArrayLiteral("pressed")) {
- d->pressedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("released")) {
- d->releasedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("clicked")) {
- d->clickedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("moved")) {
- d->movedEvent(d->resolvePickEvent(e));
- } else if (propertyName == QByteArrayLiteral("entered")) {
- emit entered();
- d->setContainsMouse(true);
- } else if (propertyName == QByteArrayLiteral("exited")) {
- d->setContainsMouse(false);
- emit exited();
- }
- }
-}
-
/*!
\internal
*/
@@ -407,15 +386,6 @@ void QObjectPickerPrivate::setContainsMouse(bool containsMouse)
}
}
-QPickEvent *QObjectPickerPrivate::resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e)
-{
- QObjectPickerEvent ev = e->value().value<QObjectPickerEvent>();
- QPickEvent *pickEvent = ev.event.data();
- pickEvent->d_func()->m_viewport = static_cast<QViewport *>(scene()->lookupNode(ev.viewportNodeId));
- pickEvent->d_func()->m_entityPtr = static_cast<Qt3DCore::QEntity *>(scene()->lookupNode(pickEvent->d_func()->m_entity));
- return pickEvent;
-}
-
void QObjectPickerPrivate::propagateEvent(QPickEvent *event, EventType type)
{
if (!m_entities.isEmpty()) {
diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h
index 8866c99a9..ee63c9418 100644
--- a/src/render/picking/qobjectpicker.h
+++ b/src/render/picking/qobjectpicker.h
@@ -90,9 +90,6 @@ Q_SIGNALS:
void containsMouseChanged(bool containsMouse);
Q_REVISION(13) void priorityChanged(int priority);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
private:
Q_DECLARE_PRIVATE(QObjectPicker)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h
index fb83912b0..69cee529d 100644
--- a/src/render/picking/qobjectpicker_p.h
+++ b/src/render/picking/qobjectpicker_p.h
@@ -91,7 +91,6 @@ public:
Moved
};
- QPickEvent *resolvePickEvent(Qt3DCore::QPropertyUpdatedChangePtr e);
void propagateEvent(QPickEvent *event, EventType type);
void pressedEvent(QPickEvent *event);
diff --git a/src/render/picking/qpickevent_p.h b/src/render/picking/qpickevent_p.h
index 4d2f1e2d4..15eeb04b8 100644
--- a/src/render/picking/qpickevent_p.h
+++ b/src/render/picking/qpickevent_p.h
@@ -37,6 +37,9 @@
**
****************************************************************************/
+#ifndef QT3DRENDER_QPICKEVENT_P_H
+#define QT3DRENDER_QPICKEVENT_P_H
+
//
// W A R N I N G
// -------------
@@ -95,3 +98,4 @@ public:
QT_END_NAMESPACE
+#endif // QT3DRENDER_QPICKEVENT_P_H
diff --git a/src/render/picking/qpicktriangleevent.cpp b/src/render/picking/qpicktriangleevent.cpp
index 3e8e8c72c..c077d412f 100644
--- a/src/render/picking/qpicktriangleevent.cpp
+++ b/src/render/picking/qpicktriangleevent.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpicktriangleevent.h"
+#include "qpicktriangleevent_p.h"
#include "qpickevent_p.h"
#include <private/qobject_p.h>
@@ -45,24 +46,42 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QPickTriangleEventPrivate : public QPickEventPrivate
+
+Qt3DRender::QPickTriangleEventPrivate::QPickTriangleEventPrivate()
+ : QPickEventPrivate()
+ , m_triangleIndex(0)
+ , m_vertex1Index(0)
+ , m_vertex2Index(0)
+ , m_vertex3Index(0)
+{
+}
+
+const QPickTriangleEventPrivate *QPickTriangleEventPrivate::get(const QPickTriangleEvent *ev)
{
-public:
- QPickTriangleEventPrivate()
- : QPickEventPrivate()
- , m_triangleIndex(0)
- , m_vertex1Index(0)
- , m_vertex2Index(0)
- , m_vertex3Index(0)
- {
- }
+ return ev->d_func();
+}
+
+QPickTriangleEvent *QPickTriangleEventPrivate::clone() const
+{
+ auto res = new QPickTriangleEvent();
+ res->d_func()->m_accepted = m_accepted;
+ res->d_func()->m_position = m_position;
+ res->d_func()->m_worldIntersection = m_worldIntersection;
+ res->d_func()->m_localIntersection = m_localIntersection;
+ res->d_func()->m_distance = m_distance;
+ res->d_func()->m_button = m_button;
+ res->d_func()->m_buttons = m_buttons;
+ res->d_func()->m_modifiers = m_modifiers;
+ res->d_func()->m_entity = m_entity;
+ res->d_func()->m_entityPtr = m_entityPtr;
+ res->d_func()->m_viewport = m_viewport;
+ res->d_func()->m_triangleIndex = m_triangleIndex;
+ res->d_func()->m_vertex1Index = m_vertex1Index;
+ res->d_func()->m_vertex2Index = m_vertex2Index;
+ res->d_func()->m_vertex3Index = m_vertex3Index;
+ return res;
+}
- uint m_triangleIndex;
- uint m_vertex1Index;
- uint m_vertex2Index;
- uint m_vertex3Index;
- QVector3D m_uvw;
-};
/*!
\class Qt3DRender::QPickTriangleEvent
diff --git a/src/render/picking/qpicktriangleevent_p.h b/src/render/picking/qpicktriangleevent_p.h
new file mode 100644
index 000000000..d646ac2bb
--- /dev/null
+++ b/src/render/picking/qpicktriangleevent_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+#define QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+
+#include <Qt3DRender/private/qpickevent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QPickTriangleEvent;
+
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QPickTriangleEventPrivate : public QPickEventPrivate
+{
+public:
+ QPickTriangleEventPrivate();
+
+ static const QPickTriangleEventPrivate *get(const QPickTriangleEvent *ev);
+ QPickTriangleEvent *clone() const;
+
+ uint m_triangleIndex;
+ uint m_vertex1Index;
+ uint m_vertex2Index;
+ uint m_vertex3Index;
+ QVector3D m_uvw;
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QPICKTRIANGLEEVENT_P_H
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
index f4bd8b871..333453ac7 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
@@ -279,7 +279,7 @@ void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderPro
}
-// Called by GL Command Thread
+// Called by Renderer::updateGLResources
void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
{
bool wasPresent = false;
@@ -317,7 +317,8 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
shader->setGraphicsContext(this);
shader->setLoaded(true);
- shader->markDirty(AbstractRenderer::AllDirty);
+ // Will force notifications to be sent to frontend at next frame
+ shader->markDirty(AbstractRenderer::ShadersDirty);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
index fee1cc4b5..cc211ba68 100644
--- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
@@ -513,7 +513,7 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
// the shaderdata cannot hold transformed properties for multiple
// thread contexts at once
activeUniformNamesToValue.insert(StringToInt::lookupId(varName),
- currentShaderData->getTransformedProperty(qmlPropertyName.toLatin1(), viewMatrix));
+ currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix));
}
}
}
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 42af03d11..121a6aa8f 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -91,6 +91,8 @@
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/private/subtreeenabler_p.h>
+#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
+#include <Qt3DRender/private/qshaderprogram_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -191,16 +193,18 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create())
- , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
- , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
- , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
- , m_sendTextureChangesToFrontendJob(decltype(m_sendTextureChangesToFrontendJob)::create([] {},
- [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
- JobTypes::SendTextureChangesToFrontend))
- , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
- , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend))
- , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering))
- , m_syncLoadingJobs(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncLoadingJobs))
+ , m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
+ , m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
+ , m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
+ , m_sendTextureChangesToFrontendJob(SynchronizerPostFramePtr::create([] {},
+ [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
+ JobTypes::SendTextureChangesToFrontend))
+ , m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
+ , m_sendDisablesToFrontendJob(SynchronizerJobPtr::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend))
+ , m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); },
+ [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
+ JobTypes::DirtyShaderGathering))
+ , m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
, m_shouldSwapBuffers(true)
@@ -343,6 +347,16 @@ void Renderer::setOpenGLContext(QOpenGLContext *context)
m_glContext = context;
}
+void Renderer::setScreen(QScreen *scr)
+{
+ m_screen = scr;
+}
+
+QScreen *Renderer::screen() const
+{
+ return m_screen;
+}
+
// Called in RenderThread context by the run method of RenderThread
// RenderThread has locked the mutex already and unlocks it when this
// method termintates
@@ -360,6 +374,8 @@ void Renderer::initialize()
// we need to create it
if (!m_glContext) {
ctx = new QOpenGLContext;
+ if (m_screen)
+ ctx->setScreen(m_screen);
ctx->setShareContext(qt_gl_global_share_context());
// TO DO: Shouldn't we use the highest context available and trust
@@ -389,6 +405,8 @@ void Renderer::initialize()
if (!ctx->shareContext()) {
m_shareContext = new QOpenGLContext;
+ if (ctx->screen())
+ m_shareContext->setScreen(ctx->screen());
m_shareContext->setFormat(ctx->format());
m_shareContext->setShareContext(ctx);
m_shareContext->create();
@@ -482,7 +500,8 @@ void Renderer::releaseGraphicsResources()
QOpenGLContext *context = m_submissionContext->openGLContext();
Q_ASSERT(context);
- if (context->makeCurrent(offscreenSurface)) {
+
+ if (context->thread() == QThread::currentThread() && context->makeCurrent(offscreenSurface)) {
// Clean up the graphics context and any resources
const QVector<HGLTexture> activeTexturesHandles = m_nodesManager->glTextureManager()->activeHandles();
@@ -1104,45 +1123,22 @@ void Renderer::reloadDirtyShaders()
if (shaderBuilder) {
shaderBuilder->setGraphicsApi(*technique->graphicsApiFilter());
- for (int i = 0; i <= ShaderBuilder::Compute; i++) {
- const auto builderType = static_cast<ShaderBuilder::ShaderType>(i);
- if (!shaderBuilder->shaderGraph(builderType).isValid())
+ for (int i = 0; i <= QShaderProgram::Compute; i++) {
+ const auto shaderType = static_cast<QShaderProgram::ShaderType>(i);
+ if (!shaderBuilder->shaderGraph(shaderType).isValid())
continue;
- if (shaderBuilder->isShaderCodeDirty(builderType)) {
- shaderBuilder->generateCode(builderType);
- }
-
- QShaderProgram::ShaderType shaderType = QShaderProgram::Vertex;
- switch (builderType) {
- case ShaderBuilder::Vertex:
- shaderType = QShaderProgram::Vertex;
- break;
- case ShaderBuilder::TessellationControl:
- shaderType = QShaderProgram::TessellationControl;
- break;
- case ShaderBuilder::TessellationEvaluation:
- shaderType = QShaderProgram::TessellationEvaluation;
- break;
- case ShaderBuilder::Geometry:
- shaderType = QShaderProgram::Geometry;
- break;
- case ShaderBuilder::Fragment:
- shaderType = QShaderProgram::Fragment;
- break;
- case ShaderBuilder::Compute:
- shaderType = QShaderProgram::Compute;
- break;
+ if (shaderBuilder->isShaderCodeDirty(shaderType)) {
+ shaderBuilder->generateCode(shaderType);
+ m_shaderBuilderUpdates.append(shaderBuilder->takePendingUpdates());
}
- const auto code = shaderBuilder->shaderCode(builderType);
+ const auto code = shaderBuilder->shaderCode(shaderType);
shader->setShaderCode(shaderType, code);
}
}
- if (Q_UNLIKELY(shader->hasPendingNotifications()))
- shader->submitPendingNotifications();
- // If the shader hasn't be loaded, load it
+ // If the shader hasn't been loaded, load it
if (shader != nullptr && !shader->isLoaded())
loadShader(shader, shaderHandle);
}
@@ -1150,6 +1146,33 @@ void Renderer::reloadDirtyShaders()
}
}
+// Executed in job postFrame
+void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager)
+{
+ Q_ASSERT(isRunning());
+
+ // Sync Shader
+ const QVector<HShader> activeShaders = m_nodesManager->shaderManager()->activeHandles();
+ for (const HShader &handle :activeShaders) {
+ Shader *s = m_nodesManager->shaderManager()->data(handle);
+ if (s->requiresFrontendSync()) {
+ QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId()));
+ QShaderProgramPrivate *dFrontend = static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend));
+ s->unsetRequiresFrontendSync();
+ dFrontend->setStatus(s->status());
+ dFrontend->setLog(s->log());
+ }
+ }
+
+ // Sync ShaderBuilder
+ const QVector<ShaderBuilderUpdate> shaderBuilderUpdates = std::move(m_shaderBuilderUpdates);
+ for (const ShaderBuilderUpdate &update : shaderBuilderUpdates) {
+ QShaderProgramBuilder *builder = static_cast<decltype(builder)>(manager->lookupNode(update.builderId));
+ QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(QNodePrivate::get(builder));
+ dBuilder->setShaderCode(update.shaderCode, update.shaderType);
+ }
+}
+
// Executed in a job (as postFrame)
void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager)
{
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 41a071290..b1cd4aac5 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -81,6 +81,7 @@
#include <Qt3DRender/private/renderercache_p.h>
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/glfence_p.h>
+#include <Qt3DRender/private/shaderbuilder_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -105,6 +106,7 @@ QT_BEGIN_NAMESPACE
class QSurface;
class QMouseEvent;
+class QScreen;
namespace Qt3DCore {
class QEntity;
@@ -154,7 +156,7 @@ class UpdateLevelOfDetailJob;
typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
+using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
@@ -220,7 +222,7 @@ public:
inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; }
inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
- inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
+ inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; }
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
@@ -292,6 +294,8 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
RendererCache *cache() { return &m_cache; }
+ void setScreen(QScreen *scr) override;
+ QScreen *screen() const override;
#ifdef QT3D_RENDER_UNIT_TESTS
public:
@@ -374,14 +378,13 @@ private:
HVao *previousVAOHandle,
OpenGLVertexArrayObject **vao);
- GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
- GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>> m_sendTextureChangesToFrontendJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob;
- IntrospectShadersJobPtr m_introspectShaderJob;
-
+ SynchronizerJobPtr m_bufferGathererJob;
+ SynchronizerJobPtr m_vaoGathererJob;
+ SynchronizerJobPtr m_textureGathererJob;
+ SynchronizerPostFramePtr m_sendTextureChangesToFrontendJob;
+ SynchronizerJobPtr m_sendSetFenceHandlesToFrontendJob;
+ SynchronizerJobPtr m_sendDisablesToFrontendJob;
+ SynchronizerPostFramePtr m_introspectShaderJob;
SynchronizerJobPtr m_syncLoadingJobs;
void lookForAbandonedVaos();
@@ -389,6 +392,7 @@ private:
void lookForDownloadableBuffers();
void lookForDirtyTextures();
void reloadDirtyShaders();
+ void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendSetFenceHandlesToFrontend();
void sendDisablesToFrontend();
@@ -404,6 +408,7 @@ private:
QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
QVector<Qt3DCore::QNodeId> m_updatedDisables;
Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
+ QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates;
bool m_ownedContext;
@@ -424,6 +429,7 @@ private:
bool m_shouldSwapBuffers;
QVector<FrameGraphNode *> m_frameGraphLeaves;
+ QScreen *m_screen = nullptr;
};
} // namespace Render
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 8fbe8e188..aa9f4d1a5 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -102,6 +102,12 @@ int LIGHT_COLOR_NAMES[MAX_LIGHTS];
int LIGHT_INTENSITY_NAMES[MAX_LIGHTS];
QString LIGHT_STRUCT_NAMES[MAX_LIGHTS];
+int LIGHT_POSITION_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_TYPE_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_COLOR_UNROLL_NAMES[MAX_LIGHTS];
+int LIGHT_INTENSITY_UNROLL_NAMES[MAX_LIGHTS];
+QString LIGHT_STRUCT_UNROLL_NAMES[MAX_LIGHTS];
+
bool wasInitialized = false;
} // anonymous namespace
@@ -261,6 +267,12 @@ RenderView::RenderView()
LIGHT_TYPE_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_TYPE_NAME);
LIGHT_COLOR_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_COLOR_NAME);
LIGHT_INTENSITY_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_INTENSITY_NAME);
+
+ LIGHT_STRUCT_UNROLL_NAMES[i] = QLatin1String("light_") + QLatin1Char(char('0' + i));
+ LIGHT_POSITION_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_POSITION_NAME);
+ LIGHT_TYPE_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_TYPE_NAME);
+ LIGHT_COLOR_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_COLOR_NAME);
+ LIGHT_INTENSITY_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_INTENSITY_NAME);
}
}
}
@@ -1008,6 +1020,11 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
+
// There is no risk in doing that even if multithreaded
// since we are sure that a shaderData is unique for a given light
// and won't ever be referenced as a Component either
@@ -1016,6 +1033,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
shaderData->updateWorldTransform(*worldTransform);
setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
++lightIdx;
}
}
@@ -1030,6 +1048,11 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
}
// Environment Light
diff --git a/src/render/renderstates/qrenderstate.cpp b/src/render/renderstates/qrenderstate.cpp
index 8a7d897be..cd5346710 100644
--- a/src/render/renderstates/qrenderstate.cpp
+++ b/src/render/renderstates/qrenderstate.cpp
@@ -59,6 +59,7 @@ namespace Qt3DRender {
/*!
\qmltype RenderState
+ \inqmlmodule Qt3D.Render
\brief An abstract base type for all render states.
\since 5.7
\inherits Node
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp
index ab9f01d39..7fca2ba3f 100644
--- a/src/render/texture/qabstracttexture.cpp
+++ b/src/render/texture/qabstracttexture.cpp
@@ -139,6 +139,27 @@ void QAbstractTexturePrivate::setHandleType(QAbstractTexture::HandleType type)
*/
/*!
+ \qmltype AbstractTexture
+ \instantiates Qt3DRender::QAbstractTexture
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief A base class to be used to provide textures.
+
+ The AbstractTexture class shouldn't be used directly but rather through one
+ of its subclasses. Each subclass implements a given texture target (2D,
+ 2DArray, 3D, CubeMap ...) Each subclass provides a set of functors for each
+ layer, cube map face and mipmap level. In turn the backend uses those
+ functor to properly fill a corresponding OpenGL texture with data. It is
+ expected the functor does as minimal processing as possible so as not to
+ slow down textures generation and upload. If the content of a texture is
+ the result of a slow procedural generation process, it is recommended not
+ to implement this directly in a functor.
+
+ All textures are unique. If you instantiate twice the same texture this
+ will create 2 identical textures on the GPU, no sharing will take place.
+ */
+
+/*!
\enum Qt3DRender::QAbstractTexture::CubeMapFace
This enum identifies the faces of a cube map texture
@@ -409,6 +430,12 @@ void QAbstractTexture::setSize(int w, int h, int d)
Holds the width of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::width
+
+ Holds the width of the texture provider.
+ */
+
+/*!
Set the width of the texture provider to \a width.
*/
void QAbstractTexture::setWidth(int width)
@@ -426,6 +453,11 @@ void QAbstractTexture::setWidth(int width)
Holds the height of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::height
+
+ Holds the height of the texture provider.
+ */
+/*!
Set the height to \a height.
*/
void QAbstractTexture::setHeight(int height)
@@ -443,6 +475,11 @@ void QAbstractTexture::setHeight(int height)
Holds the depth of the texture provider.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::depth
+
+ Holds the depth of the texture provider.
+ */
+/*!
Set the depth of the texture to \a depth.
*/
void QAbstractTexture::setDepth(int depth)
@@ -491,6 +528,15 @@ int QAbstractTexture::depth() const
array target formats.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::layers
+
+ Holds the maximum layer count of the texture provider. By default, the
+ maximum layer count is 1.
+
+ \note this has a meaning only for texture providers that have 3D or
+ array target formats.
+ */
+/*!
Set the maximum layer count to \a layers.
*/
void QAbstractTexture::setLayers(int layers)
@@ -524,6 +570,15 @@ int QAbstractTexture::layers() const
formats.
*/
/*!
+ \qmlproperty int Qt3DRender::QAbstractTexture::samples
+
+ Holds the number of samples per texel for the texture provider.
+ By default, the number of samples is 1.
+
+ \note this has a meaning only for texture providers that have multisample
+ formats.
+ */
+/*!
Set the number of samples per texel to \a samples.
*/
void QAbstractTexture::setSamples(int samples)
@@ -553,6 +608,11 @@ int QAbstractTexture::samples() const
Holds the format of the texture provider.
*/
/*!
+ \qmlproperty TextureFormat Qt3DRender::QAbstractTexture::format
+
+ Holds the format of the texture provider.
+ */
+/*!
Set the texture format to \a format.
*/
void QAbstractTexture::setFormat(TextureFormat format)
@@ -578,6 +638,11 @@ QAbstractTexture::TextureFormat QAbstractTexture::format() const
Holds the current status of the texture provider.
*/
+/*!
+ \qmlproperty Status Qt3DRender::QAbstractTexture::status readonly
+
+ Holds the current status of the texture provider.
+ */
/*!
\enum Qt3DRender::QAbstractTexture::Status
@@ -648,6 +713,13 @@ QAbstractTexture::Status QAbstractTexture::status() const
\note The target format can only be set once.
*/
/*!
+ \qmlproperty Target Qt3DRender::QAbstractTexture::target readonly
+
+ Holds the target format of the texture provider.
+
+ \note The target format can only be set once.
+ */
+/*!
\enum Qt3DRender::QAbstractTexture::Target
\value TargetAutomatic
@@ -741,6 +813,11 @@ QVector<QAbstractTextureImage *> QAbstractTexture::textureImages() const
Holds whether the texture provider should auto generate mipmaps.
*/
/*!
+ \qmlproperty bool Qt3DRender::QAbstractTexture::generateMipMaps
+
+ Holds whether the texture provider should auto generate mipmaps.
+ */
+/*!
Boolean parameter \a gen sets a flag indicating whether the
texture provider should generate mipmaps or not.
*/
@@ -765,6 +842,11 @@ bool QAbstractTexture::generateMipMaps() const
Holds the minification filter of the texture provider.
*/
/*!
+ \qmlproperty Filter Qt3DRender::QAbstractTexture::minificationFilter
+
+ Holds the minification filter of the texture provider.
+ */
+/*!
Set the minification filter to the specified value \a f.
*/
void QAbstractTexture::setMinificationFilter(Filter f)
@@ -799,6 +881,11 @@ void QAbstractTexture::setMinificationFilter(Filter f)
Holds the magnification filter of the texture provider.
*/
/*!
+ \qmlproperty Filter Qt3DRender::QAbstractTexture::magnificationFilter
+
+ Holds the magnification filter of the texture provider.
+ */
+/*!
Set the magnification filter to \a f.
*/
void QAbstractTexture::setMagnificationFilter(Filter f)
@@ -828,6 +915,11 @@ QAbstractTexture::Filter QAbstractTexture::magnificationFilter() const
Holds the wrap mode of the texture provider.
*/
/*!
+ \qmlproperty QTextureWrapMode Qt3DRender::QAbstractTexture::wrapMode
+
+ Holds the wrap mode of the texture provider.
+ */
+/*!
Set the wrapmode to the value specified in \a wrapMode.
*/
void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode)
@@ -859,6 +951,11 @@ QTextureWrapMode *QAbstractTexture::wrapMode()
Holds the maximum anisotropy of the texture provider.
*/
/*!
+ \qmlproperty bool Qt3DRender::QAbstractTexture::maximumAnisotropy
+
+ Holds the maximum anisotropy of the texture provider.
+ */
+/*!
Sets the maximum anisotropy to \a anisotropy.
*/
void QAbstractTexture::setMaximumAnisotropy(float anisotropy)
@@ -885,6 +982,11 @@ float QAbstractTexture::maximumAnisotropy() const
Holds the comparison function of the texture provider.
*/
/*!
+ \qmlproperty ComparisonFunction Qt3DRender::QAbstractTexture::ComparisonFunction
+
+ Holds the comparison function of the texture provider.
+ */
+/*!
Set the comparison function to \a function.
*/
void QAbstractTexture::setComparisonFunction(QAbstractTexture::ComparisonFunction function)
@@ -910,6 +1012,12 @@ QAbstractTexture::ComparisonFunction QAbstractTexture::comparisonFunction() cons
Holds the comparison mode of the texture provider.
*/
+
+/*!
+ \qmlproperty ComparisonMode Qt3DRender::QAbstractTexture::ComparisonMode
+
+ Holds the comparison mode of the texture provider.
+ */
/*!
Set the comparison mode to \a mode.
*/
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index 734942847..bca66e630 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -1161,6 +1161,13 @@ void TextureDownloadRequest::onCompleted()
\since 5.5
\brief A QAbstractTexture with a Target1D target format.
*/
+/*!
+ \qmltype Texture1D
+ \instantiates Qt3DRender::QTexture1D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target1D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture1D instance with \a parent as parent.
@@ -1182,6 +1189,13 @@ QTexture1D::~QTexture1D()
\since 5.5
\brief A QAbstractTexture with a Target1DArray target format.
*/
+/*!
+ \qmltype Texture1DArray
+ \instantiates Qt3DRender::QTexture1DArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target1DArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture1DArray instance with \a parent as parent.
@@ -1203,6 +1217,13 @@ QTexture1DArray::~QTexture1DArray()
\since 5.5
\brief A QAbstractTexture with a Target2D target format.
*/
+/*!
+ \qmltype Texture2D
+ \instantiates Qt3DRender::QTexture2D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2D instance with \a parent as parent.
@@ -1224,6 +1245,13 @@ QTexture2D::~QTexture2D()
\since 5.5
\brief A QAbstractTexture with a Target2DArray target format.
*/
+/*!
+ \qmltype Texture2DArray
+ \instantiates Qt3DRender::QTexture2DArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DArray instance with \a parent as parent.
@@ -1245,6 +1273,13 @@ QTexture2DArray::~QTexture2DArray()
\since 5.5
\brief A QAbstractTexture with a Target3D target format.
*/
+/*!
+ \qmltype Texture3D
+ \instantiates Qt3DRender::QTexture3D
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target3D target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture3D instance with \a parent as parent.
@@ -1266,6 +1301,13 @@ QTexture3D::~QTexture3D()
\since 5.5
\brief A QAbstractTexture with a TargetCubeMap target format.
*/
+/*!
+ \qmltype TextureCubeMap
+ \instantiates Qt3DRender::QTextureCubeMap
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetCubeMap target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureCubeMap instance with \a parent as parent.
@@ -1287,6 +1329,13 @@ QTextureCubeMap::~QTextureCubeMap()
\since 5.5
\brief A QAbstractTexture with a TargetCubeMapArray target format.
*/
+/*!
+ \qmltype TextureCubeMapArray
+ \instantiates Qt3DRender::QTextureCubeMapArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetCubeMapArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureCubeMapArray instance with \a parent as parent.
@@ -1308,6 +1357,13 @@ QTextureCubeMapArray::~QTextureCubeMapArray()
\since 5.5
\brief A QAbstractTexture with a Target2DMultisample target format.
*/
+/*!
+ \qmltype Texture2DMultisample
+ \instantiates Qt3DRender::QTexture2DMultisample
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DMultisample target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DMultisample instance with \a parent as parent.
@@ -1329,6 +1385,13 @@ QTexture2DMultisample::~QTexture2DMultisample()
\since 5.5
\brief A QAbstractTexture with a Target2DMultisampleArray target format.
*/
+/*!
+ \qmltype Texture2DMultisampleArray
+ \instantiates Qt3DRender::QTexture2DMultisampleArray
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a Target2DMultisampleArray target format.
+ */
/*!
Constructs a new Qt3DRender::QTexture2DMultisampleArray instance with \a parent as parent.
@@ -1350,6 +1413,13 @@ QTexture2DMultisampleArray::~QTexture2DMultisampleArray()
\since 5.5
\brief A QAbstractTexture with a TargetRectangle target format.
*/
+/*!
+ \qmltype TextureRectangle
+ \instantiates Qt3DRender::QTextureRectangle
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetRectangle target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureRectangle instance with \a parent as parent.
@@ -1371,6 +1441,13 @@ QTextureRectangle::~QTextureRectangle()
\since 5.5
\brief A QAbstractTexture with a TargetBuffer target format.
*/
+/*!
+ \qmltype TextureBuffer
+ \instantiates Qt3DRender::QTextureBuffer
+ \inqmlmodule Qt3D.Render
+ \since 5.5
+ \brief An AbstractTexture with a TargetBuffer target format.
+ */
/*!
Constructs a new Qt3DRender::QTextureBuffer instance with \a parent as parent.
@@ -1483,6 +1560,11 @@ void QTextureLoader::setSource(const QUrl& source)
Q_D(QTextureLoader);
if (source != d->m_source) {
d->m_source = source;
+
+ // Reset target and format
+ d->m_target = TargetAutomatic;
+ setFormat(NoFormat);
+
d->updateGenerator();
const bool blocked = blockNotifications(true);
emit sourceChanged(source);
diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
index 80298780a..34d195221 100644
--- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
+++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
@@ -204,13 +204,150 @@ class tst_BoundingSphere : public Qt3DCore::QBackendNodeTester
private:
private Q_SLOTS:
+ void checkIsNull() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void remainsNotNullAfterTransform() {
+ QMatrix4x4 mat;
+ mat.translate(-5,-5,-5);
+ auto mMat = Matrix4x4(mat);
+ auto pointSphere = Qt3DRender::Render::Sphere(Vector3D(5.f,5.f,5.f),0.f);
+ pointSphere.transform(mMat);
+ QVERIFY(!pointSphere.isNull());
+ QVERIFY(pointSphere.center() == Vector3D(0.,0.,0));
+ QVERIFY(pointSphere.radius() == 0.f);
+ }
+
+ void remainsNullAfterTransform() {
+ QMatrix4x4 mat;
+ mat.translate(-5,-5,-5);
+ auto mMat = Matrix4x4(mat);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.transform(mMat);
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void expandToContainSphere() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto secondValidSphere = Qt3DRender::Render::Sphere(Vector3D(10.f,10.f,10.f),1.f);
+ firstValidSphere.expandToContain(secondValidSphere);
+ QVERIFY(firstValidSphere.center()==Vector3D(0.f,0.f,0.f));
+ float dist = static_cast<float>((2 + sqrt(3.*(20)*(20)))/2.);
+ QVERIFY(qFuzzyCompare(firstValidSphere.radius(), dist));
+ }
+
+ void expandToContainSphereOneInvalid() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ auto copiedSphere = firstValidSphere;
+ firstValidSphere.expandToContain(defaultSphere);
+ QVERIFY(firstValidSphere.center() == copiedSphere.center());
+ QVERIFY(firstValidSphere.radius() == copiedSphere.radius());
+ QVERIFY(!firstValidSphere.isNull());
+ }
+
+ void expandToContainOtherSphereInvalid() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(firstValidSphere);
+ QVERIFY(defaultSphere.center() == firstValidSphere.center());
+ QVERIFY(defaultSphere.radius() == firstValidSphere.radius());
+ QVERIFY(!defaultSphere.isNull());
+ }
+
+ void expandNullSphereWithNullSphere() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ auto otherDefaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(otherDefaultSphere);
+ QVERIFY(defaultSphere.isNull());
+ }
+
+ void expandToContainPoint() {
+ auto firstValidSphere = Qt3DRender::Render::Sphere(Vector3D(-10.f,-10.f,-10.f),1.f);
+ firstValidSphere.expandToContain(Vector3D(0,0,0));
+ QVERIFY(!firstValidSphere.isNull());
+ float expectedRadius = static_cast<float>((1 + qSqrt(3.*(10)*(10)))/2.);
+ QVERIFY(qFuzzyCompare(firstValidSphere.radius(), expectedRadius));
+ }
+
+ void nullSphereExpandToContainPoint() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(Vector3D(5,5,5));
+ QVERIFY(!defaultSphere.isNull());
+ QVERIFY(defaultSphere.center() == Vector3D(5,5,5));
+ QVERIFY(qFuzzyIsNull(defaultSphere.radius()));
+ }
+
+ void nullSphereExpandToOrigin() {
+ auto defaultSphere = Qt3DRender::Render::Sphere();
+ defaultSphere.expandToContain(Vector3D(0,0,0));
+ QVERIFY(!defaultSphere.isNull());
+ QVERIFY(defaultSphere.center() == Vector3D(0,0,0));
+ QVERIFY(qFuzzyIsNull(defaultSphere.radius()));
+ }
+
+ void ritterSphereCubePoints() {
+ QVector<Vector3D> cubePts={
+ Vector3D(-0.5, -0.5, 0.5),
+ Vector3D( 0.5, -0.5, -0.5),
+ Vector3D(-0.5, 0.5, -0.5),
+ Vector3D( 0.5, 0.5, -0.5),
+ Vector3D(-0.5, -0.5, -0.5),
+ Vector3D( 0.5, -0.5, 0.5),
+ Vector3D(-0.5, 0.5, 0.5),
+ Vector3D( 0.5, 0.5, 0.5)
+ };
+ auto ritterSphere=Qt3DRender::Render::Sphere::fromPoints(cubePts);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().x()));
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().y()));
+ QVERIFY(qFuzzyIsNull(ritterSphere.center().z()));
+ QVERIFY(qFuzzyCompare(ritterSphere.radius(), static_cast<float>(qSqrt(3)/2)));
+ }
+
+ void ritterSphereRandomPoints() {
+ QVector<Vector3D> randomPts={
+ Vector3D(-81, 55, 46),
+ Vector3D(-91, -73, -42),
+ Vector3D(-50, -76, -77),
+ Vector3D(-40, 63, 58),
+ Vector3D(-28, -2, -57),
+ Vector3D(84, 17, 33),
+ Vector3D(53, 11, -49),
+ Vector3D(-7, -24, -86),
+ Vector3D(-89, 6, 76),
+ Vector3D(46, -18, -27)
+ };
+
+ auto ritterSphere = Qt3DRender::Render::Sphere::fromPoints(randomPts);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyCompare(ritterSphere.center().x(), 17.f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().y(), -29.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().z(), -22.0f));
+ QVERIFY(qFuzzyCompare(ritterSphere.radius(), 148.66152831179963f));
+ }
+
+ void ritterSphereOnePoint() {
+ QVector<Vector3D> singlePt={
+ Vector3D(-0.5, -0.5, -0.5),
+ };
+ auto ritterSphere = Qt3DRender::Render::Sphere::fromPoints(singlePt);
+ QVERIFY(!ritterSphere.isNull());
+ QVERIFY(qFuzzyCompare(ritterSphere.center().x(), -0.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().y(), -0.5f));
+ QVERIFY(qFuzzyCompare(ritterSphere.center().z(), -0.5f));
+ QVERIFY(qFuzzyIsNull(ritterSphere.radius()));
+ }
+
void checkExtraGeometries_data()
{
QTest::addColumn<QString>("qmlFile");
QTest::addColumn<QVector3D>("sphereCenter");
QTest::addColumn<float>("sphereRadius");
QTest::newRow("SphereMesh") << "qrc:/sphere.qml" << QVector3D(0.f, 0.f, 0.f) << 1.f;
- QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.0928356f, -0.212021f, -0.0467958f) << 1.07583f; // weird!
+ QTest::newRow("CubeMesh") << "qrc:/cube.qml" << QVector3D(0.f, 0.f, 0.f) << static_cast<float>(qSqrt(3.)/2.); // not weird at all
}
void checkExtraGeometries()
@@ -235,9 +372,10 @@ private Q_SLOTS:
const auto boundingSphere = test->sceneRoot()->worldBoundingVolumeWithChildren();
qDebug() << qmlFile << boundingSphere->radius() << boundingSphere->center();
QCOMPARE(boundingSphere->radius(), sphereRadius);
- QVERIFY(qAbs(boundingSphere->center().x() - sphereCenter.x()) < 0.000001f); // qFuzzyCompare hates 0s
- QVERIFY(qAbs(boundingSphere->center().y() - sphereCenter.y()) < 0.000001f);
- QVERIFY(qAbs(boundingSphere->center().z() - sphereCenter.z()) < 0.000001f);
+
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().x() - sphereCenter.x()));
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().y() - sphereCenter.y()));
+ QVERIFY(qFuzzyIsNull(boundingSphere->center().z() - sphereCenter.z()));
}
void checkCustomGeometry_data()
@@ -247,10 +385,10 @@ private Q_SLOTS:
QTest::addColumn<QVector3D>("expectedCenter");
QTest::addColumn<float>("expectedRadius");
QTest::addColumn<bool>("withPrimitiveRestart");
- QTest::newRow("all") << 0 << 0 << QVector3D(-0.488892f, 0.0192147f, -75.4804f) << 25.5442f << false;
+ QTest::newRow("all") << 0 << 0 << QVector3D(0.0f, 0.0f, -75.0f) << 25.03997f << false;
QTest::newRow("first only") << 3 << 0 << QVector3D(0, 1, -100) << 1.0f << false;
QTest::newRow("second only") << 3 << int(3 * sizeof(ushort)) << QVector3D(0, -1, -50) << 1.0f << false;
- QTest::newRow("all with primitive restart") << 0 << 0 << QVector3D(-0.488892f, 0.0192147f, -75.4804f) << 25.5442f << true;
+ QTest::newRow("all with primitive restart") << 0 << 0 << QVector3D(0.0f, 0.0f, -75.0f) << 25.03997f << true;
QTest::newRow("first only with primitive restart") << 4 << 0 << QVector3D(0, 1, -100) << 1.0f << true;
QTest::newRow("second only with primitive restart") << 4 << int(3 * sizeof(ushort)) << QVector3D(0, -1, -50) << 1.0f << true;
}
@@ -376,18 +514,17 @@ private Q_SLOTS:
float radius = entityBackend->localBoundingVolume()->radius();
qDebug() << radius << center;
- // truncate and compare integers only
- QCOMPARE(int(radius), int(expectedRadius));
- QCOMPARE(int(center.x()), int(expectedCenter.x()));
- QCOMPARE(int(center.y()), int(expectedCenter.y()));
- QCOMPARE(int(center.z()), int(expectedCenter.z()));
+ QCOMPARE(radius, expectedRadius);
+ QCOMPARE(center.x(), expectedCenter.x());
+ QCOMPARE(center.y(), expectedCenter.y());
+ QCOMPARE(center.z(), expectedCenter.z());
}
void checkCustomPackedGeometry()
{
int drawVertexCount = 6;
- QVector3D expectedCenter(-0.488892f, 0.0192147f, -75.4804f);
- float expectedRadius = 25.5442f;
+ QVector3D expectedCenter(0.0f, 0.0f, -75.0f);
+ float expectedRadius = 25.03997f;
// two triangles with different Z
QByteArray vdata;
@@ -467,11 +604,10 @@ private Q_SLOTS:
float radius = entityBackend->localBoundingVolume()->radius();
qDebug() << radius << center;
- // truncate and compare integers only
- QVERIFY(int(radius) == int(expectedRadius));
- QVERIFY(int(center.x()) == int(expectedCenter.x()));
- QVERIFY(int(center.y()) == int(expectedCenter.y()));
- QVERIFY(int(center.z()) == int(expectedCenter.z()));
+ QCOMPARE(radius, expectedRadius);
+ QCOMPARE(center.x(), expectedCenter.x());
+ QCOMPARE(center.y(), expectedCenter.y());
+ QCOMPARE(center.z(), expectedCenter.z());
}
};
diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp
index 1487d3728..48215bea5 100644
--- a/tests/auto/render/buffer/tst_buffer.cpp
+++ b/tests/auto/render/buffer/tst_buffer.cpp
@@ -113,26 +113,40 @@ private Q_SLOTS:
// GIVEN
Qt3DRender::QBuffer frontendBuffer;
- frontendBuffer.setUsage(Qt3DRender::QBuffer::DynamicCopy);
- frontendBuffer.setData(QByteArrayLiteral("C7KR4"));
- frontendBuffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73)));
// WHEN
backendBuffer.setManager(&bufferManager);
backendBuffer.setRenderer(&renderer);
simulateInitializationSync(&frontendBuffer, &backendBuffer);
- frontendBuffer.updateData(2, QByteArrayLiteral("LS5"));
+ // THEN
+ QCOMPARE(backendBuffer.isDirty(), true);
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
+ QVERIFY(backendBuffer.data().isEmpty());
+ QVERIFY(backendBuffer.dataGenerator().isNull());
+ QVERIFY(backendBuffer.pendingBufferUpdates().empty());
+
+ // WHEN
+ frontendBuffer.setUsage(Qt3DRender::QBuffer::DynamicCopy);
+ frontendBuffer.setData(QByteArrayLiteral("C7KR4"));
+ frontendBuffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73)));
backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy);
QCOMPARE(backendBuffer.isDirty(), true);
- QCOMPARE(backendBuffer.data(), QByteArrayLiteral("C7LS5"));
+ QCOMPARE(backendBuffer.data(), QByteArrayLiteral("C7KR4"));
QVERIFY(!backendBuffer.dataGenerator().isNull());
QVERIFY(!backendBuffer.pendingBufferUpdates().empty());
// WHEN
+ frontendBuffer.updateData(2, QByteArrayLiteral("LS5"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
+
+ // THEN
+ QCOMPARE(backendBuffer.isDirty(), true);
+ QCOMPARE(backendBuffer.data(), QByteArrayLiteral("C7LS5"));
+ // WHEN
backendBuffer.cleanup();
// THEN
diff --git a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
index 770f7e72d..a7cea2ef2 100644
--- a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
+++ b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
@@ -266,6 +266,24 @@ private Q_SLOTS:
}
}
+ void checCleanupMarksDirty()
+ {
+ // GIVEN
+ TestRenderer renderer;
+ Qt3DRender::Render::FrameGraphNode *backendFGNode = new MyFrameGraphNode();
+
+ backendFGNode->setRenderer(&renderer);
+
+ // THEN
+ QVERIFY(renderer.dirtyBits() == 0);
+
+ // WHEN
+ backendFGNode->cleanup();
+
+ // THEN
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
+ }
+
};
QTEST_MAIN(tst_FrameGraphNode)
diff --git a/tests/auto/render/ktxtextures/data/16_16.png b/tests/auto/render/ktxtextures/data/16_16.png
new file mode 100644
index 000000000..aefb48dc4
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16.png
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX
new file mode 100644
index 000000000..953f300ad
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX
new file mode 100644
index 000000000..4c23241e4
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX
new file mode 100644
index 000000000..01646e99a
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX
new file mode 100644
index 000000000..2d2efff1b
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX
new file mode 100644
index 000000000..15e30abc8
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/ktxtextures.pro b/tests/auto/render/ktxtextures/ktxtextures.pro
new file mode 100644
index 000000000..beca06dc2
--- /dev/null
+++ b/tests/auto/render/ktxtextures/ktxtextures.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_ktxtextures
+
+CONFIG += testcase
+
+SOURCES += tst_ktxtextures.cpp
+
+TESTDATA = data/*
+
+QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib
diff --git a/tests/auto/render/ktxtextures/tst_ktxtextures.cpp b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp
new file mode 100644
index 000000000..57ccd3652
--- /dev/null
+++ b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qtextureimagedata.h>
+#include <Qt3DRender/private/qtexture_p.h>
+
+class tst_KtxTextures : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void ktxImageData();
+};
+
+void tst_KtxTextures::ktxImageData()
+{
+ const struct TextureInfo {
+ const char *source;
+ int width;
+ int height;
+ int depth;
+ int faces;
+ int mipmapLevels;
+ QOpenGLTexture::TextureFormat format;
+ } textures[] = {
+ { "data/16_16_PNG_ASTC_7.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA_ASTC_4x4 },
+ { "data/16_16_PNG_ASTC_8.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA_ASTC_4x4 },
+ { "data/16_16_PNG_ETC2_RGB_13.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC2 },
+ { "data/16_16_PNG_ETC2_RGBA_11.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA8_ETC2_EAC },
+ { "data/16_16_PNG_ETC_RGB_12.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC1 },
+ };
+
+ for (unsigned i = 0; i < sizeof(textures)/sizeof(*textures); i++) {
+ const TextureInfo *texture = &textures[i];
+
+ Qt3DRender::QTextureImageDataPtr data = Qt3DRender::TextureLoadingHelper::loadTextureData(QUrl::fromLocalFile(QFINDTESTDATA(texture->source)), true, false);
+
+ QVERIFY(data);
+ QCOMPARE(data->width(), texture->width);
+ QCOMPARE(data->height(), texture->height);
+ QCOMPARE(data->faces(), texture->faces);
+ QCOMPARE(data->mipLevels(), texture->mipmapLevels);
+ QCOMPARE(data->format(), texture->format);
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_KtxTextures)
+
+#include "tst_ktxtextures.moc"
diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp
index a8d9bd010..5fc988d47 100644
--- a/tests/auto/render/objectpicker/tst_objectpicker.cpp
+++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp
@@ -137,65 +137,6 @@ private Q_SLOTS:
QVERIFY(renderer.dirtyBits() != 0);
}
}
-
- void checkBackendPropertyNotifications()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DRender::Render::ObjectPicker objectPicker;
- Qt3DCore::QBackendNodePrivate::get(&objectPicker)->setArbiter(&arbiter);
- Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent);
-
- // WHEN
- objectPicker.onPressed(event, Qt3DCore::QNodeId());
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onReleased(event, Qt3DCore::QNodeId());
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onClicked(event, Qt3DCore::QNodeId());
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onEntered();
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onExited();
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
-
- arbiter.events.clear();
- }
};
diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
index 1fbdc4d04..5191b1a36 100644
--- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
+++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
@@ -34,6 +34,10 @@
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
#include <QtQuick/qquickwindow.h>
#include <Qt3DRender/QCamera>
@@ -60,6 +64,8 @@
#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/private/nopicking_p.h>
+#include <QSignalSpy>
+
#include <private/qpickevent_p.h>
QT_BEGIN_NAMESPACE
@@ -114,10 +120,18 @@ public:
: Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)
, m_sceneRoot(nullptr)
{
- QRenderAspect::onRegistered();
-
+ m_engine = new Qt3DCore::QAspectEngine(this);
+ m_engine->registerAspect(this);
+ Q_ASSERT(d_func()->m_aspectManager);
+
+ // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop
+ Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { });
+ Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine);
+ aed->m_root = proot;
+ aed->initialize();
+ aed->initNodeTree(root);
const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChangesForNodes(nodes));
+ aed->m_aspectManager->setRootEntity(proot.data(), nodes);
Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
@@ -126,7 +140,17 @@ public:
~TestAspect()
{
- QRenderAspect::onUnregistered();
+ using namespace Qt3DCore;
+ QNodeVisitor visitor;
+ visitor.traverse(m_engine->rootEntity().data(), [](QNode *node) {
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_scene = nullptr;
+ d->m_changeArbiter = nullptr;
+ });
+
+ m_engine->unregisterAspect(this);
+ delete m_engine;
+ m_engine = nullptr;
}
void onRegistered() { QRenderAspect::onRegistered(); }
@@ -136,8 +160,10 @@ public:
Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); }
Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); }
Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; }
-
+ Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; }
+ Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; }
private:
+ Qt3DCore::QAspectEngine *m_engine;
Render::Entity *m_sceneRoot;
};
@@ -285,7 +311,7 @@ private Q_SLOTS:
auto vca = results.first();
QCOMPARE(vca.area, QSize(600, 600));
QCOMPARE(vca.cameraId, camera->id());
- QCOMPARE(vca.viewport, QRectF(0.0f, 0.0f, 1.0f, 1.0f));
+ QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.));
}
void checkCurrentPickerChange_data()
@@ -344,7 +370,7 @@ private Q_SLOTS:
// WHEN
QList<QPair<QObject *,QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -357,7 +383,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -367,7 +393,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -380,7 +406,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -440,7 +466,7 @@ private Q_SLOTS:
// WHEN
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 440.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 440.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -490,7 +516,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
@@ -547,7 +573,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -597,7 +623,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -608,7 +634,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -658,7 +684,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -669,7 +695,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -719,7 +745,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
const bool earlyReturn = !pickBVJob.runHelper();
@@ -740,6 +766,7 @@ private Q_SLOTS:
QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml"));
QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root()));
QVERIFY(root);
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
QList<Qt3DRender::QRenderSettings *> renderSettings = root->findChildren<Qt3DRender::QRenderSettings *>();
QCOMPARE(renderSettings.size(), 1);
@@ -751,9 +778,7 @@ private Q_SLOTS:
settings->setPickMethod(pickMethod);
settings->setPickResultMode(pickResultMode);
settings->setFaceOrientationPickingMode(faceOrientationPickingMode);
-
- QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
- TestArbiter arbiter;
+ test->renderSettings()->syncFromFrontEnd(renderSettings.first(), false);
// Runs Required jobs
runRequiredJobs(test.data());
@@ -770,7 +795,7 @@ private Q_SLOTS:
Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id());
QVERIFY(backendPicker1);
- Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter);
+ Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(test->arbiter());
QCOMPARE(test->renderSettings()->pickMethod(), pickMethod);
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
@@ -785,94 +810,88 @@ private Q_SLOTS:
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
+ QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Move on same object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
- pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Release on object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released + Clicked
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>());
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
- pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), /*backAndFrontPicking ? 2 :*/ 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
+
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
+ mouseClickedSpy.clear();
// WHEN -> Release outside of object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0, 0.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
}
void checkDispatchReleaseEventOnLastPickerWhenMovingOutOfViewport()
@@ -910,57 +929,70 @@ private Q_SLOTS:
QVERIFY(backendPicker1);
Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter);
+ QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
- QVERIFY(pickEvent.event.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
// WHEN -> Releasing out of the viewport
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Should have received released event
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
- QVERIFY(Qt3DRender::QPickEventPrivate::get(pickEvent.event.data())->m_entity.isNull());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
- arbiter.events.clear();
// WHEN -> Releasing out of the viewport
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Should have received nothing
- QCOMPARE(arbiter.events.count(), 0);
+ QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
}
void checkDispatchHoverEvent_data()
@@ -1010,60 +1042,64 @@ private Q_SLOTS:
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode);
+ QSignalSpy mouseEntered(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker1, &Qt3DRender::QObjectPicker::exited);
+
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Hover on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Entered
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 0);
// WHEN -> HoverMove Out
events.clear();
- events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0f, 40.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0, 40.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN - Exited
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 1);
- arbiter.events.clear();
+ mouseEntered.clear();
+ mouseExited.clear();
// WHEN -> HoverMove In + Pressed other
events.clear();
- events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0, 0.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN - Entered, Exited
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 1);
}
void shouldDispatchMouseEventFromChildren_data()
@@ -1115,78 +1151,94 @@ private Q_SLOTS:
(pickResultMode == Qt3DRender::QPickingSettings::AllPicks) &&
(faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Move on same object
+ mouseButtonPressedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Release on object
+ mouseMovedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released + Clicked
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
-
- arbiter.events.clear();
+ QVERIFY(!picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
// WHEN -> Release outside of object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
+
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0., 0.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
+ QVERIFY(!picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
}
void checkPickerGrabbing_data()
@@ -1212,6 +1264,11 @@ private Q_SLOTS:
settings->setPickResultMode(pickResultMode);
settings->setFaceOrientationPickingMode(faceOrientationPickingMode);
+ const bool backAndFrontPicking =
+ (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) &&
+ (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) &&
+ (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace);
+
QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
TestArbiter arbiter1;
TestArbiter arbiter2;
@@ -1245,47 +1302,85 @@ private Q_SLOTS:
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode);
+ QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy1.isValid());
+ QVERIFY(mouseMovedSpy1.isValid());
+ QVERIFY(mouseButtonReleasedSpy1.isValid());
+ QVERIFY(mouseClickedSpy1.isValid());
+ QVERIFY(mouseEntered1.isValid());
+ QVERIFY(mouseExited1.isValid());
+
+ QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy2.isValid());
+ QVERIFY(mouseMovedSpy2.isValid());
+ QVERIFY(mouseButtonReleasedSpy2.isValid());
+ QVERIFY(mouseClickedSpy2.isValid());
+ QVERIFY(mouseEntered2.isValid());
+ QVERIFY(mouseExited2.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker1->isPressed());
- arbiter1.events.clear();
+ QCOMPARE(mouseButtonPressedSpy1.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
// WHEN -> Move on next object, show stay on previous picker unless all picks are requested
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved over the second picker, is the first one still pressed
QVERIFY(!earlyReturn);
if (pickResultMode != Qt3DRender::QPickingSettings::AllPicks) {
QVERIFY(backendPicker1->isPressed());
- change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 1);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
} else {
- QVERIFY(arbiter2.events.size() > 1);
- change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
- change = arbiter2.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 1);
+ QCOMPARE(mouseExited2.count(), 0);
}
-
- arbiter1.events.clear();
- arbiter2.events.clear();
}
void checkParentNoPickerChildPicker()
@@ -1321,22 +1416,41 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkPickerAndViewports()
@@ -1372,38 +1486,63 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object in vp1
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
// WHEN reset -> Presset on object in vp2
backendPicker->cleanup();
backendPicker->setEnabled(true);
events.clear();
- arbiter.events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Nothing happened
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 0);
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkMultipleRayDirections_data()
@@ -1420,8 +1559,8 @@ private Q_SLOTS:
const double angle = M_PI * 2. / (double)n * i;
const double x = std::sin(angle) * 10.;
const double z = std::cos(angle) * 10.;
- QVector3D pos(x, 0, z);
- QVector3D up(0, 1, 0);
+ QVector3D pos(x, 0.f, z);
+ QVector3D up(0.f, 1.f, 0.f);
QTest::newRow(QString::number(k++).toLatin1().data()) << m * pos << m * up;
}
}
@@ -1466,25 +1605,41 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QObjectPickerEvent pickEvent = change->value().value<Qt3DRender::QObjectPickerEvent>();
- QVERIFY(pickEvent.event);
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkPriorityPicking()
@@ -1523,6 +1678,33 @@ private Q_SLOTS:
QVERIFY(backendPicker2);
Qt3DCore::QBackendNodePrivate::get(backendPicker2)->setArbiter(&arbiter2);
+ QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy1.isValid());
+ QVERIFY(mouseMovedSpy1.isValid());
+ QVERIFY(mouseButtonReleasedSpy1.isValid());
+ QVERIFY(mouseClickedSpy1.isValid());
+ QVERIFY(mouseEntered1.isValid());
+ QVERIFY(mouseExited1.isValid());
+
+ QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy2.isValid());
+ QVERIFY(mouseMovedSpy2.isValid());
+ QVERIFY(mouseButtonReleasedSpy2.isValid());
+ QVERIFY(mouseClickedSpy2.isValid());
+ QVERIFY(mouseEntered2.isValid());
+ QVERIFY(mouseExited2.isValid());
// WHEN both have priority == 0, select closest
{
@@ -1531,31 +1713,62 @@ private Q_SLOTS:
// WHEN -> Pressed on object
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Select picker with highest priority
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
QVERIFY(!backendPicker2->isPressed());
- QVERIFY(arbiter2.events.isEmpty());
-
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f),
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
+
+ events.clear();
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
pickBVJob.runHelper();
- arbiter1.events.clear();
- arbiter2.events.clear();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 1);
+ QCOMPARE(mouseClickedSpy1.count(), 1);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
+
QVERIFY(!backendPicker2->isPressed());
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
}
+ mouseButtonPressedSpy1.clear();
+ mouseButtonReleasedSpy1.clear();
+ mouseClickedSpy1.clear();
+
// WHEN furthest one has higher priority, select furthest one
{
backendPicker2->setPriority(1000);
@@ -1566,29 +1779,56 @@ private Q_SLOTS:
// WHEN -> Pressed on object
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Select picker with highest priority
QVERIFY(!earlyReturn);
- QVERIFY(backendPicker2->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
QVERIFY(!backendPicker1->isPressed());
- QVERIFY(arbiter1.events.isEmpty());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 0);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f),
+ QVERIFY(backendPicker2->isPressed());
+ QVERIFY(picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 1);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
+
+ events.clear();
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
pickBVJob.runHelper();
- arbiter1.events.clear();
- arbiter2.events.clear();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 0);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
+
QVERIFY(!backendPicker2->isPressed());
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 1);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 1);
+ QCOMPARE(mouseClickedSpy2.count(), 1);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
}
}
@@ -1635,7 +1875,7 @@ private Q_SLOTS:
auto vca = results.first();
QCOMPARE(vca.area, QSize(600, 600));
QCOMPARE(vca.cameraId, camera->id());
- QCOMPARE(vca.viewport, QRectF(0.0f, 0.0f, 1.0f, 1.0f));
+ QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.));
}
};
diff --git a/tests/auto/render/picking/tst_picking.cpp b/tests/auto/render/picking/tst_picking.cpp
index 4f4201e07..d0e6512d5 100644
--- a/tests/auto/render/picking/tst_picking.cpp
+++ b/tests/auto/render/picking/tst_picking.cpp
@@ -153,14 +153,13 @@ private Q_SLOTS:
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()});
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("pressed");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 0);
@@ -171,7 +170,7 @@ private Q_SLOTS:
// WHEN
child11.pressedCalled = 0;
child11.acceptsEvents = false;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 0);
@@ -184,7 +183,7 @@ private Q_SLOTS:
child1.pressedCalled = 0;
child11.acceptsEvents = false;
child11.pressedCalled = 0;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 1);
@@ -208,16 +207,14 @@ private Q_SLOTS:
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()});
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("pressed");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
- e->setPropertyName("released");
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
+ dpicker(child11.picker)->releasedEvent(event.data());
// THEN
QCOMPARE(root.releasedCalled, 0);
@@ -229,10 +226,8 @@ private Q_SLOTS:
child11.releasedCalled = 0;
child11.pressedCalled = 0;
child11.acceptsEvents = false;
- e->setPropertyName("pressed");
- child11.picker->sceneChangeEvent(e);
- e->setPropertyName("released");
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
+ dpicker(child11.picker)->releasedEvent(event.data());
// THEN
QCOMPARE(child1.pressedCalled, 1);
@@ -259,14 +254,13 @@ private Q_SLOTS:
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QObjectPickerEvent>({event, Qt3DCore::QNodeId()});
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("clicked");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 0);
@@ -277,7 +271,7 @@ private Q_SLOTS:
// WHEN
child11.clickedCalled = 0;
child11.acceptsEvents = false;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 0);
@@ -290,7 +284,7 @@ private Q_SLOTS:
child1.clickedCalled = 0;
child11.acceptsEvents = false;
child11.clickedCalled = 0;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 1);
diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
index 07adf12b5..1bed9fc44 100644
--- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
+++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
@@ -29,6 +29,10 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
+#include <Qt3DRender/qgeometry.h>
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/entity_p.h>
@@ -43,6 +47,40 @@ namespace {
Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent)
{
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(parent);
+
+ // create geometry with a valid bounding volume - a single point is sufficient
+ auto geometry = new Qt3DRender::QGeometry;
+ auto vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry);
+
+ auto positionAttribute = new Qt3DRender::QAttribute;
+ positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
+ positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
+ positionAttribute->setVertexSize(3);
+ positionAttribute->setByteStride(3 * sizeof(float));
+ positionAttribute->setBuffer(vertexBuffer);
+
+ QByteArray vertexBufferData;
+ vertexBufferData.resize(static_cast<int>(3 * sizeof(float)));
+
+ auto vertexArray = reinterpret_cast<float*>(vertexBufferData.data());
+
+ int i = 0;
+ vertexArray[i++] = 0.0f;
+ vertexArray[i++] = 0.0f;
+ vertexArray[i++] = 0.0f;
+
+ vertexBuffer->setData(vertexBufferData);
+ positionAttribute->setCount(1);
+
+ geometry->addAttribute(positionAttribute);
+
+ auto geometryRenderer = new Qt3DRender::QGeometryRenderer;
+ geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Points);
+ geometryRenderer->setGeometry(geometry);
+
+ entity->addComponent(geometryRenderer);
+
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(parent);
const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance;
diff --git a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
index 53c0ec939..5977829a6 100644
--- a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
+++ b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
@@ -234,24 +234,6 @@ private Q_SLOTS:
QTest::newRow("objectPicker_all_true") << objectPicker;
}
- // TODO: Avoid cloning here
-// void checkCloning()
-// {
-// // GIVEN
-// QFETCH(Qt3DRender::QObjectPicker *, objectPicker);
-
-// // WHEN
-// Qt3DRender::QObjectPicker *clone = static_cast<Qt3DRender::QObjectPicker *>(QNode::clone(objectPicker));
-// QCoreApplication::processEvents();
-
-// // THEN
-// QVERIFY(clone != nullptr);
-// QCOMPARE(objectPicker->id(), clone->id());
-// QCOMPARE(objectPicker->isHoverEnabled(), clone->isHoverEnabled());
-// QCOMPARE(objectPicker->isPressed(), clone->isPressed());
-// QCOMPARE(objectPicker->containsMouse(), clone->containsMouse());
-// }
-
void checkPropertyUpdates()
{
// GIVEN
@@ -272,68 +254,6 @@ private Q_SLOTS:
arbiter.dirtyNodes.clear();
}
-
- void checkBackendUpdates_data()
- {
- QTest::addColumn<QByteArray>("signalPrototype");
- QTest::addColumn<QByteArray>("propertyName");
- QTest::addColumn<bool>("requiresEvent");
-
- QTest::newRow("clicked")
- << QByteArray(SIGNAL(clicked(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("clicked")
- << true;
-
- QTest::newRow("pressed")
- << QByteArray(SIGNAL(pressed(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("pressed")
- << true;
-
- QTest::newRow("released")
- << QByteArray(SIGNAL(released(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("released")
- << true;
-
- QTest::newRow("entered")
- << QByteArray(SIGNAL(entered()))
- << QByteArrayLiteral("entered")
- << false;
-
- QTest::newRow("exited")
- << QByteArray(SIGNAL(exited()))
- << QByteArrayLiteral("exited")
- << false;
- }
-
- void checkBackendUpdates()
- {
- // GIVEN
- QFETCH(QByteArray, signalPrototype);
- QFETCH(QByteArray, propertyName);
- QFETCH(bool, requiresEvent);
- Qt3DCore::QScene scene;
- QScopedPointer<MyObjectPicker> objectPicker(new MyObjectPicker());
- Qt3DCore::QNodePrivate::get(objectPicker.data())->setScene(&scene);
-
- QSignalSpy spy(objectPicker.data(), signalPrototype.constData());
- Qt3DRender::QObjectPickerEvent event {Qt3DRender::QPickEventPtr::create(), Qt3DCore::QNodeId()};
-
- // WHEN
- // Create Backend Change and distribute it to frontend node
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(objectPicker->id()));
- e->setPropertyName(propertyName.constData());
- if (requiresEvent)
- {
- QVariant v;
- v.setValue<Qt3DRender::QObjectPickerEvent>(event);
- e->setValue(v);
- }
- objectPicker->sceneChangeEvent(e);
-
- // THEN
- // Check that the QObjectPicker triggers the expected signal
- QCOMPARE(spy.count(), 1);
- }
};
QTEST_MAIN(tst_QObjectPicker)
diff --git a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
index 881c24728..851316e60 100644
--- a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
+++ b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
@@ -594,13 +594,11 @@ private Q_SLOTS:
void checkGeneratedCodePropertyUpdates()
{
+ Qt3DRender::QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(Qt3DCore::QNodePrivate::get(this));
{
// WHEN
QSignalSpy spy(this, SIGNAL(vertexShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Vertex), QByteArrayLiteral("vertex"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("vertex"), Qt3DRender::QShaderProgram::Vertex);
// THEN
QVERIFY(spy.isValid());
@@ -610,10 +608,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(fragmentShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Fragment), QByteArrayLiteral("fragment"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("fragment"), Qt3DRender::QShaderProgram::Fragment);
// THEN
QVERIFY(spy.isValid());
@@ -623,10 +618,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(geometryShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Geometry), QByteArrayLiteral("geometry"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("geometry"), Qt3DRender::QShaderProgram::Geometry);
// THEN
QVERIFY(spy.isValid());
@@ -636,10 +628,8 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(computeShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Compute), QByteArrayLiteral("compute"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("compute"), Qt3DRender::QShaderProgram::Compute);
+
// THEN
QVERIFY(spy.isValid());
@@ -649,10 +639,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(tessellationControlShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::TessellationControl), QByteArrayLiteral("control"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("control"), Qt3DRender::QShaderProgram::TessellationControl);
// THEN
QVERIFY(spy.isValid());
@@ -662,10 +649,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(tessellationEvaluationShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::TessellationEvaluation), QByteArrayLiteral("eval"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("eval"), Qt3DRender::QShaderProgram::TessellationEvaluation);
// THEN
QVERIFY(spy.isValid());
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 786d8050f..180ff7ac1 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -41,6 +41,7 @@ qtConfig(private_tests) {
# qboundingvolumedebug \
# boundingvolumedebug \
ddstextures \
+ ktxtextures \
shadercache \
layerfiltering \
filterentitybycomponent \
diff --git a/tests/auto/render/scene2d/tst_scene2d.cpp b/tests/auto/render/scene2d/tst_scene2d.cpp
index f620064ed..fcb4c0908 100644
--- a/tests/auto/render/scene2d/tst_scene2d.cpp
+++ b/tests/auto/render/scene2d/tst_scene2d.cpp
@@ -128,7 +128,7 @@ private Q_SLOTS:
// WHEN
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
backendScene2d->setRenderer(&renderer);
- simulateInitialization(&frontend, backendScene2d.data());
+ simulateInitializationSync(&frontend, backendScene2d.data());
// THEN
QCOMPARE(backendScene2d->isEnabled(), true);
@@ -144,7 +144,7 @@ private Q_SLOTS:
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
frontend.setEnabled(false);
backendScene2d->setRenderer(&renderer);
- simulateInitialization(&frontend, backendScene2d.data());
+ simulateInitializationSync(&frontend, backendScene2d.data());
// THEN
QCOMPARE(backendScene2d->peerId(), frontend.id());
@@ -156,18 +156,18 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::Quick::QScene2D frontend;
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
TestRenderer renderer;
QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput());
backendScene2d->setRenderer(&renderer);
+ simulateInitializationSync(&frontend, backendScene2d.data());
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendScene2d->sceneChangeEvent(change);
+ frontend.setEnabled(false);
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->isEnabled(), newValue);
@@ -175,10 +175,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DCore::QNodeId newValue = output.data()->id();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("output");
- change->setValue(QVariant::fromValue(newValue));
- backendScene2d->sceneChangeEvent(change);
+ frontend.setOutput(output.data());
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->m_outputId, newValue);
@@ -186,10 +184,8 @@ private Q_SLOTS:
{
// WHEN
const QScene2D::RenderPolicy newValue = QScene2D::SingleShot;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("renderPolicy");
- change->setValue(QVariant::fromValue(newValue));
- backendScene2d->sceneChangeEvent(change);
+ frontend.setRenderPolicy(newValue);
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->m_renderPolicy, newValue);
@@ -197,10 +193,7 @@ private Q_SLOTS:
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("mouseEnabled");
- change->setValue(newValue);
- backendScene2d->sceneChangeEvent(change);
+ frontend.setMouseEnabled(newValue);
// THEN
QCOMPARE(backendScene2d->isEnabled(), newValue);
@@ -209,10 +202,11 @@ private Q_SLOTS:
backendScene2d->cleanup();
}
-
void testCoordinateCalculation()
{
// GIVEN
+ qputenv("QT3D_SCENE2D_DISABLE_RENDERING", "1");
+
QScopedPointer<TestWindow> testWindow(new TestWindow());
Scene2DSharedObjectPtr sharedObject(new Scene2DSharedObject(nullptr));
QScopedPointer<Scene2D> scene2d(new Scene2D());
@@ -336,7 +330,8 @@ private Q_SLOTS:
QVector3D uvw(1.0, 0.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -350,7 +345,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 1.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -364,7 +360,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 0.0f, 1.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -378,7 +375,8 @@ private Q_SLOTS:
QVector3D uvw(1.0, 0.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -392,7 +390,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 1.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -406,7 +405,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 0.0f, 1.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -420,12 +420,13 @@ private Q_SLOTS:
QVector3D uvw(0.5f, 0.25f, 0.25f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
// THEN
- QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(512.0f, 768.0f)));
+ QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(512.0, 768.0)));
testWindow->clear();
}
@@ -434,14 +435,17 @@ private Q_SLOTS:
QVector3D uvw(0.875f, 0.09375f, 0.03125f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
// THEN
- QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(96.0f, 896.0f)));
+ QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(96.0, 896.0)));
testWindow->clear();
}
+
+ scene2d.reset();
}
};
diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp
index bfebe2467..d1578aee7 100644
--- a/tests/auto/render/shader/tst_shader.cpp
+++ b/tests/auto/render/shader/tst_shader.cpp
@@ -103,7 +103,7 @@ void tst_RenderShader::matchesFrontendPeer()
for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i)
QCOMPARE(backend.shaderCode()[i],
- frontend->shaderCode( static_cast<const Qt3DRender::QShaderProgram::ShaderType>(i)));
+ frontend->shaderCode(static_cast<Qt3DRender::QShaderProgram::ShaderType>(i)));
}
void tst_RenderShader::cleanupLeavesACoherentState()
diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
index 7a9e0fac4..7a08fe018 100644
--- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
+++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
@@ -36,7 +36,6 @@
#include "testrenderer.h"
#include "testpostmanarbiter.h"
-Q_DECLARE_METATYPE(Qt3DRender::Render::ShaderBuilder::ShaderType)
Q_DECLARE_METATYPE(Qt3DRender::QShaderProgram::ShaderType)
class tst_ShaderBuilder : public Qt3DCore::QBackendNodeTester
@@ -78,8 +77,8 @@ private slots:
// THEN
QVERIFY(!shaderBuilder.isEnabled());
QVERIFY(shaderBuilder.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QCOMPARE(shaderBuilder.shaderGraph(type), QUrl());
QCOMPARE(shaderBuilder.shaderCode(type), QByteArray());
QVERIFY(!shaderBuilder.isShaderCodeDirty(type));
@@ -158,29 +157,29 @@ private slots:
QCOMPARE(backend.enabledLayers(), frontend->enabledLayers());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Vertex), frontend->vertexShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Vertex), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Vertex), !frontend->vertexShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Vertex), frontend->vertexShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Vertex), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Vertex), !frontend->vertexShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationControl), frontend->tessellationControlShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationControl), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::TessellationControl), frontend->tessellationControlShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::TessellationControl), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::TessellationEvaluation), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Geometry), frontend->geometryShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Geometry), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Geometry), !frontend->geometryShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Geometry), frontend->geometryShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Geometry), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Geometry), !frontend->geometryShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Fragment), frontend->fragmentShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Fragment), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Fragment), !frontend->fragmentShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Fragment), frontend->fragmentShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Fragment), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Fragment), !frontend->fragmentShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Compute), frontend->computeShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Compute), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Compute), !frontend->computeShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Compute), frontend->computeShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Compute), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Compute), !frontend->computeShaderGraph().isEmpty());
// WHEN
backend.cleanup();
@@ -188,8 +187,8 @@ private slots:
// THEN
QVERIFY(!backend.isEnabled());
QVERIFY(backend.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QCOMPARE(backend.shaderGraph(type), QUrl());
QCOMPARE(backend.shaderCode(type), QByteArray());
QVERIFY(!backend.isShaderCodeDirty(type));
@@ -279,16 +278,16 @@ private slots:
const auto layers = QStringList() << "foo" << "bar";
static const std::pair<
- Qt3DRender::Render::ShaderBuilder::ShaderType,
+ Qt3DRender::QShaderProgram::ShaderType,
void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
>
shaderTypesToSetters[] = {
- {Qt3DRender::Render::ShaderBuilder::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ {Qt3DRender::QShaderProgram::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::QShaderProgram::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::QShaderProgram::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::QShaderProgram::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
};
@@ -303,8 +302,8 @@ private slots:
// THEN
QCOMPARE(backend.enabledLayers(), layers);
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -317,8 +316,8 @@ private slots:
// THEN
QCOMPARE(backend.enabledLayers(), layers);
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(!backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -331,8 +330,8 @@ private slots:
// THEN
QVERIFY(backend.shaderProgramId().isNull());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -347,8 +346,8 @@ private slots:
// THEN
QVERIFY(backend.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(!backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -358,32 +357,32 @@ private slots:
void shouldHandleShaderGraphPropertiesChanges_data()
{
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
QTest::addColumn<QUrl>("graphUrl");
- QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex
<< QUrl::fromEncoded("qrc:/vertex.json");
- QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl
<< QUrl::fromEncoded("qrc:/tesscontrol.json");
- QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation
<< QUrl::fromEncoded("qrc:/tesseval.json");
- QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry
<< QUrl::fromEncoded("qrc:/geometry.json");
- QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment
<< QUrl::fromEncoded("qrc:/fragment.json");
- QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute
<< QUrl::fromEncoded("qrc:/compute.json");
}
void shouldHandleShaderGraphPropertiesChanges()
{
// GIVEN
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
QFETCH(QUrl, graphUrl);
Qt3DRender::Render::ShaderBuilder backend;
@@ -393,16 +392,16 @@ private slots:
simulateInitializationSync(&frontend, &backend);
static const QHash<
- Qt3DRender::Render::ShaderBuilder::ShaderType,
+ Qt3DRender::QShaderProgram::ShaderType,
void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
>
shaderTypesToSetters = {
- {Qt3DRender::Render::ShaderBuilder::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
- {Qt3DRender::Render::ShaderBuilder::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ {Qt3DRender::QShaderProgram::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::QShaderProgram::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::QShaderProgram::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::QShaderProgram::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
};
// WHEN
@@ -455,14 +454,14 @@ private slots:
void shouldHandleShaderCodeGeneration_data()
{
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
-
- QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex;
- QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl;
- QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation;
- QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry;
- QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment;
- QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute;
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
+
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex;
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl;
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation;
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry;
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment;
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute;
}
void shouldHandleShaderCodeGeneration()
@@ -471,7 +470,7 @@ private slots:
Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json");
QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty());
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
const auto gl3Api = []{
auto api = Qt3DRender::GraphicsApiFilterData();
@@ -540,15 +539,15 @@ private slots:
void checkCodeUpdatedNotification_data()
{
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("notificationType");
- QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex << Qt3DRender::QShaderProgram::Vertex;
- QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl << Qt3DRender::QShaderProgram::TessellationControl;
- QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation << Qt3DRender::QShaderProgram::TessellationEvaluation;
- QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry << Qt3DRender::QShaderProgram::Geometry;
- QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment << Qt3DRender::QShaderProgram::Fragment;
- QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute << Qt3DRender::QShaderProgram::Compute;
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex << Qt3DRender::QShaderProgram::Vertex;
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl << Qt3DRender::QShaderProgram::TessellationControl;
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation << Qt3DRender::QShaderProgram::TessellationEvaluation;
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry << Qt3DRender::QShaderProgram::Geometry;
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment << Qt3DRender::QShaderProgram::Fragment;
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute << Qt3DRender::QShaderProgram::Compute;
}
@@ -559,7 +558,7 @@ private slots:
Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json");
QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty());
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
QFETCH(Qt3DRender::QShaderProgram::ShaderType, notificationType);
const auto gl3Api = []{
@@ -603,15 +602,6 @@ private slots:
QCOMPARE(backend.shaderGraph(type), graphUrl);
QVERIFY(!backend.isShaderCodeDirty(type));
QCOMPARE(backend.shaderCode(type), gl3Code);
-
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(arbiter.events.count(), 1);
- QCOMPARE(change->propertyName(), "generatedShaderCode");
- const QPair<int, QByteArray> value = change->value().value<QPair<int, QByteArray>>();
- QCOMPARE(value.first, int(notificationType));
- QCOMPARE(value.second, gl3Code);
-
- arbiter.events.clear();
}
};
diff --git a/tests/manual/compressed_textures/compressed_textures.pro b/tests/manual/compressed_textures/compressed_textures.pro
new file mode 100644
index 000000000..37871a4cb
--- /dev/null
+++ b/tests/manual/compressed_textures/compressed_textures.pro
@@ -0,0 +1,12 @@
+QT += 3dcore 3drender 3dinput 3dquick 3dlogic qml quick 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ compressed_textures.qrc
+
+DEFINES += DATA_DIR=\\\"$$PWD/data\\\"
diff --git a/tests/manual/compressed_textures/compressed_textures.qrc b/tests/manual/compressed_textures/compressed_textures.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/compressed_textures/compressed_textures.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/compressed_textures/data/16_16.png b/tests/manual/compressed_textures/data/16_16.png
new file mode 100644
index 000000000..aefb48dc4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16.png
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX
new file mode 100644
index 000000000..953f300ad
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX
new file mode 100644
index 000000000..4c23241e4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX
new file mode 100644
index 000000000..01646e99a
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX
new file mode 100644
index 000000000..2d2efff1b
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX
new file mode 100644
index 000000000..15e30abc8
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16-etc1.pkm b/tests/manual/compressed_textures/data/16x16-etc1.pkm
new file mode 100644
index 000000000..62ae2a11f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16-etc1.pkm
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16-etc2.pkm b/tests/manual/compressed_textures/data/16x16-etc2.pkm
new file mode 100644
index 000000000..be391113e
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16-etc2.pkm
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds
new file mode 100644
index 000000000..feacae8d1
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds
new file mode 100644
index 000000000..40da98cde
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds
new file mode 100644
index 000000000..1dd3e1e91
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds
new file mode 100644
index 000000000..e31f410d2
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds
new file mode 100644
index 000000000..76c820f31
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds
new file mode 100644
index 000000000..0a2964f12
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds
new file mode 100644
index 000000000..c8c94d85f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds
new file mode 100644
index 000000000..4a08d324a
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds
new file mode 100644
index 000000000..8fdd5e3e1
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds b/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds
new file mode 100644
index 000000000..82ab57958
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds
new file mode 100644
index 000000000..94d06c2c4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds b/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds
new file mode 100644
index 000000000..45635dd97
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds
new file mode 100644
index 000000000..209b796f0
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds
new file mode 100644
index 000000000..e79e29ab5
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds
new file mode 100644
index 000000000..de6796d9f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds
new file mode 100644
index 000000000..92b95ae73
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds
new file mode 100644
index 000000000..f56fa09fd
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds
new file mode 100644
index 000000000..31e137553
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds
new file mode 100644
index 000000000..644274601
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds
new file mode 100644
index 000000000..144515bb0
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds
new file mode 100644
index 000000000..baa884a36
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds b/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds
new file mode 100644
index 000000000..1a4e6f46f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds
new file mode 100644
index 000000000..318a0bd35
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds b/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds
new file mode 100644
index 000000000..1f3c8f9cf
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/main.cpp b/tests/manual/compressed_textures/main.cpp
new file mode 100644
index 000000000..ca4cf7c2d
--- /dev/null
+++ b/tests/manual/compressed_textures/main.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QQuickView>
+#include <QGuiApplication>
+#include <QQmlContext>
+#include <QDir>
+
+QStringList createTextureFileList()
+{
+ QDir dir(QString::fromUtf8(DATA_DIR));
+ return dir.entryList();
+}
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ QQuickView view;
+
+ QQmlContext *ctx =view.rootContext();
+ ctx->setContextProperty(QStringLiteral("_pathPrefix"), QString::fromUtf8(DATA_DIR));
+ ctx->setContextProperty(QStringLiteral("_texturesList"), createTextureFileList());
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/compressed_textures/main.qml b/tests/manual/compressed_textures/main.qml
new file mode 100644
index 000000000..b5ad0990e
--- /dev/null
+++ b/tests/manual/compressed_textures/main.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 QtQuick 2.12 as QQ2
+import QtQuick.Scene3D 2.12
+import QtQuick.Controls 2.12
+import Qt3D.Core 2.12
+import Qt3D.Render 2.12
+import Qt3D.Input 2.12
+import Qt3D.Extras 2.12
+
+QQ2.Item {
+ id: root
+ width: 1280
+ height: 720
+
+ readonly property string textureSource: "file://" + _pathPrefix + "/" + textureSelector.textAt(textureSelector.currentIndex)
+
+ Scene3D {
+ anchors.fill: parent
+ focus: true
+ aspects: ["input", "logic"]
+
+ 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, -2.0)
+ upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ }
+
+ OrbitCameraController {
+ camera: camera
+ }
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ clearColor: Qt.rgba(0, 0.5, 1, 1)
+ camera: camera
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { }
+ ]
+
+ Entity {
+ readonly property CuboidMesh mesh: CuboidMesh { }
+ readonly property DiffuseMapMaterial material: DiffuseMapMaterial {
+ diffuse: TextureLoader {
+ source: textureSource
+ }
+ }
+ components: [ mesh, material ]
+ }
+ }
+ }
+
+ ComboBox {
+ id: textureSelector
+ model: _texturesList
+ width: 200
+ }
+}
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 644c9ecf9..1182886d3 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -66,7 +66,8 @@ SUBDIRS += \
qtbug-72236 \
qtbug-76766 \
shader-image-qml \
- scene3d-in-sync
+ scene3d-in-sync \
+ compressed_textures
qtHaveModule(multimedia): {
SUBDIRS += \