summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-01-28 15:56:26 +0000
committerSean Harmer <sean.harmer@kdab.com>2017-01-29 10:17:49 +0000
commit8ef8c094dd55d198c5601689e0f1cc9fcc14274b (patch)
treefbdd6c1e35a6f2606286752a98a9018213fdb789 /src
parent9c5bf588ab310e274fddffb252962e8abfa66bd2 (diff)
parent2f3cfb7f19911f29e6ea7c0528b26f9263d38121 (diff)
Merge branch 'wip/qtquickintegration' into dev
Conflicts: src/quick3d/imports/render/qt3dquick3drenderplugin.cpp src/render/backend/triangleboundingvolume.cpp src/render/backend/triangleboundingvolume_p.h src/render/frontend/qrenderaspect.cpp src/render/frontend/sphere.cpp src/render/frontend/sphere_p.h src/render/jobs/pickboundingvolumejob.cpp src/render/jobs/pickboundingvolumejob_p.h src/render/picking/objectpicker.cpp src/render/raycasting/qcollisionqueryresult_p.h src/render/render.pro src/src.pro tests/auto/render/objectpicker/tst_objectpicker.cpp tests/auto/render/render.pro Change-Id: I95717c7855887850d5c90e7ad8f19f1ffb37a545
Diffstat (limited to 'src')
-rw-r--r--src/core/aspects/qabstractaspect.cpp6
-rw-r--r--src/core/aspects/qabstractaspect.h9
-rw-r--r--src/plugins/renderplugins/renderplugins.pro2
-rw-r--r--src/plugins/renderplugins/scene2d/main.cpp63
-rw-r--r--src/plugins/renderplugins/scene2d/scene2d.pro21
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.cpp111
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.h92
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.json3
-rw-r--r--src/quick3d/imports/render/qt3dquick3drenderplugin.cpp7
-rw-r--r--src/quick3d/quick3drender/qt3dquickrender_logging.cpp49
-rw-r--r--src/quick3d/quick3drender/qt3dquickrender_logging_p.h65
-rw-r--r--src/quick3d/quick3drender/quick3drender.pro7
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d.cpp697
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d.h117
-rw-r--r--src/quick3d/quick3drender/scene2d/qscene2d_p.h219
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d.cpp363
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d.pri10
-rw-r--r--src/quick3d/quick3drender/scene2d/scene2d_p.h127
-rw-r--r--src/render/backend/abstractrenderer_p.h3
-rw-r--r--src/render/backend/attachmentpack.cpp2
-rw-r--r--src/render/backend/backendnode.cpp16
-rw-r--r--src/render/backend/backendnode_p.h8
-rw-r--r--src/render/backend/managers_p.h10
-rw-r--r--src/render/backend/nodemanagers.cpp15
-rw-r--r--src/render/backend/nodemanagers_p.h16
-rw-r--r--src/render/backend/render-backend.pri6
-rw-r--r--src/render/backend/renderer.cpp25
-rw-r--r--src/render/backend/renderer_p.h4
-rw-r--r--src/render/backend/rendertargetoutput.cpp9
-rw-r--r--src/render/backend/rendertargetoutput_p.h3
-rw-r--r--src/render/backend/resourceaccessor.cpp94
-rw-r--r--src/render/backend/resourceaccessor_p.h93
-rw-r--r--src/render/backend/triangleboundingvolume.cpp17
-rw-r--r--src/render/backend/triangleboundingvolume_p.h2
-rw-r--r--src/render/backend/trianglesvisitor.cpp101
-rw-r--r--src/render/backend/trianglesvisitor_p.h42
-rw-r--r--src/render/frontend/qrenderaspect.cpp36
-rw-r--r--src/render/frontend/qrenderaspect.h2
-rw-r--r--src/render/frontend/qrenderaspect_p.h5
-rw-r--r--src/render/frontend/qrenderplugin_p.h89
-rw-r--r--src/render/frontend/qrenderpluginfactory.cpp99
-rw-r--r--src/render/frontend/qrenderpluginfactory_p.h75
-rw-r--r--src/render/frontend/qrenderpluginfactoryif.cpp65
-rw-r--r--src/render/frontend/qrenderpluginfactoryif_p.h82
-rw-r--r--src/render/frontend/render-frontend.pri9
-rw-r--r--src/render/frontend/sphere.cpp3
-rw-r--r--src/render/frontend/sphere_p.h2
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp77
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h11
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp1
-rw-r--r--src/render/picking/eventforward.cpp196
-rw-r--r--src/render/picking/eventforward_p.h105
-rw-r--r--src/render/picking/objectpicker.cpp20
-rw-r--r--src/render/picking/objectpicker_p.h3
-rw-r--r--src/render/picking/pickeventfilter.cpp21
-rw-r--r--src/render/picking/pickeventfilter_p.h7
-rw-r--r--src/render/picking/picking.pri11
-rw-r--r--src/render/picking/posteventstofrontend.cpp74
-rw-r--r--src/render/picking/posteventstofrontend_p.h81
-rw-r--r--src/render/picking/qeventforward.cpp285
-rw-r--r--src/render/picking/qeventforward.h105
-rw-r--r--src/render/picking/qeventforward_p.h101
-rw-r--r--src/render/picking/qobjectpicker.cpp33
-rw-r--r--src/render/picking/qobjectpicker.h6
-rw-r--r--src/render/picking/qobjectpicker_p.h3
-rw-r--r--src/render/raycasting/qabstractcollisionqueryservice.cpp6
-rw-r--r--src/render/raycasting/qabstractcollisionqueryservice_p.h3
-rw-r--r--src/render/raycasting/qboundingvolume_p.h3
-rw-r--r--src/render/raycasting/qcollisionqueryresult.cpp5
-rw-r--r--src/render/raycasting/qcollisionqueryresult_p.h21
-rw-r--r--src/render/raycasting/qraycastingservice.cpp8
-rw-r--r--src/render/render.pro3
-rw-r--r--src/render/texture/gltexture_p.h10
-rw-r--r--src/src.pro8
74 files changed, 4030 insertions, 78 deletions
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp
index c049d3503..8f1afb30e 100644
--- a/src/core/aspects/qabstractaspect.cpp
+++ b/src/core/aspects/qabstractaspect.cpp
@@ -157,6 +157,12 @@ void QAbstractAspect::registerBackendType(const QMetaObject &obj, const QBackend
d->m_backendCreatorFunctors.insert(&obj, functor);
}
+void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
+{
+ Q_D(QAbstractAspect);
+ d->m_backendCreatorFunctors.remove(&obj);
+}
+
void QAbstractAspectPrivate::sceneNodeAdded(QSceneChangePtr &change)
{
QNodeCreatedChangeBasePtr creationChange = qSharedPointerCast<QNodeCreatedChangeBase>(change);
diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h
index 86938d2d2..a4ad68c1d 100644
--- a/src/core/aspects/qabstractaspect.h
+++ b/src/core/aspects/qabstractaspect.h
@@ -76,6 +76,9 @@ protected:
template<class Frontend>
void registerBackendType(const QBackendNodeMapperPtr &functor);
void registerBackendType(const QMetaObject &, const QBackendNodeMapperPtr &functor);
+ template<class Frontend>
+ void unregisterBackendType();
+ void unregisterBackendType(const QMetaObject &);
private:
virtual QVariant executeCommand(const QStringList &args);
@@ -99,6 +102,12 @@ void QAbstractAspect::registerBackendType(const QBackendNodeMapperPtr &functor)
registerBackendType(Frontend::staticMetaObject, functor);
}
+template<class Frontend>
+void QAbstractAspect::unregisterBackendType()
+{
+ unregisterBackendType(Frontend::staticMetaObject);
+}
+
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/plugins/renderplugins/renderplugins.pro b/src/plugins/renderplugins/renderplugins.pro
new file mode 100644
index 000000000..1bc2f6c6c
--- /dev/null
+++ b/src/plugins/renderplugins/renderplugins.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += scene2d
diff --git a/src/plugins/renderplugins/scene2d/main.cpp b/src/plugins/renderplugins/scene2d/main.cpp
new file mode 100644
index 000000000..00a3db734
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene2dplugin.h"
+
+#include <private/qrenderpluginfactoryif_p.h>
+#include <private/qrenderplugin_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Scene2DPlugin : public Qt3DRender::Render::QRenderPluginFactoryIf
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QRenderPluginFactoryInterface_iid FILE "scene2dplugin.json")
+
+ Qt3DRender::Render::QRenderPlugin *create(const QString &key,
+ const QStringList &paramList) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(key)
+ Q_UNUSED(paramList)
+ return new Qt3DRender::Render::Scene2DPlugin();
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/renderplugins/scene2d/scene2d.pro b/src/plugins/renderplugins/scene2d/scene2d.pro
new file mode 100644
index 000000000..dbf9c3e36
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2d.pro
@@ -0,0 +1,21 @@
+TARGET = scene2d
+QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras 3dquickrender 3dquickrender-private
+
+# Qt3D is free of Q_FOREACH - make sure it stays that way:
+DEFINES += QT_NO_FOREACH
+
+HEADERS += \
+ scene2dplugin.h
+# scene2dnode_p.h
+
+SOURCES += \
+ main.cpp \
+ scene2dplugin.cpp
+# scene2dnode.cpp
+
+DISTFILES += \
+ scene2dplugin.json
+
+PLUGIN_TYPE = renderplugins
+PLUGIN_CLASS_NAME = Scene2DPlugin
+load(qt_plugin)
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
new file mode 100644
index 000000000..5621858ea
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene2dplugin.h"
+
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DQuickRender/qscene2d.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+template <typename Backend>
+class Scene2DBackendNodeMapper : public Qt3DCore::QBackendNodeMapper
+{
+public:
+ explicit Scene2DBackendNodeMapper(Render::AbstractRenderer *renderer,
+ Render::Scene2DNodeManager *manager)
+ : m_manager(manager)
+ , m_renderer(renderer)
+ {
+ }
+
+ Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const Q_DECL_FINAL
+ {
+ Backend *backend = m_manager->getOrCreateResource(change->subjectId());
+ backend->setRenderer(m_renderer);
+ return backend;
+ }
+
+ Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const Q_DECL_FINAL
+ {
+ return m_manager->lookupResource(id);
+ }
+
+ void destroy(Qt3DCore::QNodeId id) const Q_DECL_FINAL
+ {
+ m_manager->releaseResource(id);
+ }
+
+private:
+ Render::Scene2DNodeManager *m_manager;
+ Render::AbstractRenderer *m_renderer;
+};
+
+Scene2DPlugin::Scene2DPlugin()
+ : m_scene2dNodeManager(new Render::Scene2DNodeManager())
+{
+
+}
+
+Scene2DPlugin::~Scene2DPlugin()
+{
+ delete m_scene2dNodeManager;
+}
+
+bool Scene2DPlugin::registerBackendTypes(QRenderAspect *aspect,
+ AbstractRenderer *renderer)
+{
+ registerBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject,
+ QSharedPointer<Scene2DBackendNodeMapper<Render::Quick::Scene2D> >
+ ::create(renderer, m_scene2dNodeManager));
+ return true;
+}
+bool Scene2DPlugin::unregisterBackendTypes(QRenderAspect *aspect)
+{
+ unregisterBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject);
+ return true;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.h b/src/plugins/renderplugins/scene2d/scene2dplugin.h
new file mode 100644
index 000000000..f19093c7e
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** 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_SCENE2DPLUGIN_H
+#define QT3DRENDER_SCENE2DPLUGIN_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrenderaspect_p.h>
+#include <private/qrenderplugin_p.h>
+#include <private/abstractrenderer_p.h>
+#include <private/qresourcemanager_p.h>
+#include <private/scene2d_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class Scene2DNode;
+
+class Scene2DNodeManager : public Qt3DCore::QResourceManager<
+ Render::Quick::Scene2D,
+ Qt3DCore::QNodeId,
+ 16,
+ Qt3DCore::ArrayAllocatingPolicy,
+ Qt3DCore::ObjectLevelLockingPolicy>
+{
+};
+
+class Scene2DPlugin : public QRenderPlugin
+{
+public:
+ Scene2DPlugin();
+ ~Scene2DPlugin();
+ bool registerBackendTypes(QRenderAspect *aspect, AbstractRenderer *renderer) Q_DECL_OVERRIDE;
+ bool unregisterBackendTypes(QRenderAspect *aspect) Q_DECL_OVERRIDE;
+private:
+ Render::Scene2DNodeManager *m_scene2dNodeManager;
+};
+
+} // Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_SCENE2DPLUGIN_H
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.json b/src/plugins/renderplugins/scene2d/scene2dplugin.json
new file mode 100644
index 000000000..2eece1046
--- /dev/null
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.json
@@ -0,0 +1,3 @@
+{
+ "Keys": ["scene2d"]
+}
diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
index c6831dbce..bb0ac249c 100644
--- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
+++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
@@ -103,8 +103,11 @@
#include <Qt3DRender/qcamera.h>
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qpickingsettings.h>
+#include <Qt3DRender/qeventforward.h>
#include <Qt3DRender/qrendercapture.h>
#include <Qt3DRender/qmemorybarrier.h>
+
+#include <Qt3DQuickRender/qscene2d.h>
#include <Qt3DQuickRender/private/quick3dlayerfilter_p.h>
#include <Qt3DQuickRender/private/quick3dtechnique_p.h>
#include <Qt3DQuickRender/private/quick3dmaterial_p.h>
@@ -205,6 +208,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
// Picking
qmlRegisterType<Qt3DRender::QObjectPicker>(uri, 2, 0, "ObjectPicker");
+ qmlRegisterType<Qt3DRender::QEventForward>(uri, 2, 2, "EventForward");
qmlRegisterUncreatableType<Qt3DRender::QPickEvent>(uri, 2, 0, "PickEvent", QStringLiteral("Events cannot be created"));
// Compute Job
@@ -269,6 +273,9 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QSeamlessCubemap>(uri, 2, 0, "SeamlessCubemap");
qmlRegisterType<Qt3DRender::QStencilOperation>(uri, 2, 0, "StencilOperation");
qmlRegisterType<Qt3DRender::QStencilMask>(uri, 2, 0, "StencilMask");
+
+ // Scene2D
+ Qt3DRender::Quick::registerType<Qt3DRender::Quick::QScene2D>("QScene2D", "Qt3D.Render/Scene2D", uri, 2, 2, "Scene2D");
}
QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/qt3dquickrender_logging.cpp b/src/quick3d/quick3drender/qt3dquickrender_logging.cpp
new file mode 100644
index 000000000..b9e5d2e08
--- /dev/null
+++ b/src/quick3d/quick3drender/qt3dquickrender_logging.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt3dquickrender_logging_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Quick {
+
+Q_LOGGING_CATEGORY(Scene2D, "Qt3D.Scene2D")
+
+} // Quick
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/qt3dquickrender_logging_p.h b/src/quick3d/quick3drender/qt3dquickrender_logging_p.h
new file mode 100644
index 000000000..c34abfdd3
--- /dev/null
+++ b/src/quick3d/quick3drender/qt3dquickrender_logging_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DQUICKRENDER_LOGGING_P_H
+#define QT3DQUICKRENDER_LOGGING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Quick {
+
+Q_DECLARE_LOGGING_CATEGORY(Scene2D)
+
+} // Quick
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DQUICKRENDER_LOGGING_P_H
diff --git a/src/quick3d/quick3drender/quick3drender.pro b/src/quick3d/quick3drender/quick3drender.pro
index 88d7a9556..b1b904e12 100644
--- a/src/quick3d/quick3drender/quick3drender.pro
+++ b/src/quick3d/quick3drender/quick3drender.pro
@@ -14,16 +14,19 @@ gcov {
SOURCES += \
qt3dquickrender_global.cpp \
- qt3dquickrendernodefactory.cpp
+ qt3dquickrendernodefactory.cpp \
+ qt3dquickrender_logging.cpp
HEADERS += \
qt3dquickrendernodefactory_p.h \
qt3dquickrender_global_p.h \
- qt3dquickrender_global.h
+ qt3dquickrender_global.h \
+ qt3dquickrender_logging_p.h
# otherwise mingw headers do not declare common functions like ::strcasecmp
win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
include(./items/items.pri)
+include(./scene2d/scene2d.pri)
load(qt_module)
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d.cpp b/src/quick3d/quick3drender/scene2d/qscene2d.cpp
new file mode 100644
index 000000000..fa46cd3d2
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/qscene2d.cpp
@@ -0,0 +1,697 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscene2d.h"
+#include "qscene2d_p.h"
+#include "scene2d_p.h"
+
+#include <Qt3DCore/QPropertyUpdatedChange>
+
+#include <QtGui/QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DCore;
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+/*!
+ \class Qt3DRender::QScene2D
+ \inmodule Qt3DRender
+
+ \brief This class enables rendering qml into a texture, which then can be
+ used as a part of 3D scene.
+
+ The component uses QQuickRenderControl to render the given QML source into an
+ offscreen surface, which is attached to a texture provided by the user. This allows the
+ component to directly render into the texture without intermediate copy and the user to
+ freely specify how the texture is used in the 3D scene.
+
+ \since 5.9
+*/
+
+/*!
+ \qmltype Scene2D
+ \inqmlmodule Qt3D.Render
+ \since
+ \ingroup
+ \instantiates Qt3DRender::QScene2D
+ \brief Scene2D
+ */
+
+/*!
+ \enum QScene2D::RenderPolicy
+
+ This enum type describes types of render policies available.
+ \value Continuous The Scene2D is rendering continuously. This is the default render policy.
+ \value SingleShot The Scene2D renders to the texture only once after which the resources
+ allocated for rendering are released.
+*/
+
+/*!
+ \qmlproperty RenderTargetOutput Qt3D.Render::Scene2D::output
+ Holds the RenderTargetOutput, which specifies where the Scene2D is rendering to.
+ */
+
+/*!
+ \qmlproperty QUrl Qt3D.Render::Scene2D::source
+ Holds the qml source url.
+ */
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::Scene2D::renderPolicy
+ Holds the render policy of this Scene2D.
+ */
+
+/*!
+ \qmlproperty bool Qt3D.Render::Scene2D::loaded
+ Holds whether the source has been loaded.
+ */
+
+class RenderControl : public QQuickRenderControl
+{
+public:
+ RenderControl(QWindow *w) : m_window(w) { }
+ QWindow *renderWindow(QPoint *offset) Q_DECL_OVERRIDE;
+
+private:
+ QWindow *m_window;
+};
+
+QWindow *RenderControl::renderWindow(QPoint *offset)
+{
+ if (offset)
+ *offset = QPoint(0, 0);
+ return m_window;
+}
+
+/*!
+ \internal
+ Constructs object shared by the front-end and back-end to synchronize the rendering.
+ */
+Scene2DSharedObject::Scene2DSharedObject(Scene2DManager *manager)
+ : m_quit(false)
+ , m_requestSync(false)
+ , m_prepared(false)
+ , m_initialized(false)
+ , m_renderControl(nullptr)
+ , m_quickWindow(nullptr)
+ , m_renderManager(manager)
+ , m_surface(nullptr)
+ , m_renderObject(nullptr)
+ , m_disallowed(false)
+{
+}
+
+Scene2DSharedObject::~Scene2DSharedObject()
+{
+}
+
+void Scene2DSharedObject::cleanup()
+{
+ delete m_renderControl;
+ delete m_quickWindow;
+ delete m_surface;
+ m_renderControl = nullptr;
+ m_quickWindow = nullptr;
+ m_surface = nullptr;
+ m_initialized = false;
+}
+
+bool Scene2DSharedObject::canRender() const
+{
+ return m_initialized && m_prepared && !m_disallowed;
+}
+
+bool Scene2DSharedObject::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Scene2DSharedObject::disallowRender()
+{
+ m_disallowed = true;
+}
+
+void Scene2DSharedObject::setInitialized()
+{
+ m_initialized = true;
+}
+
+bool Scene2DSharedObject::isPrepared() const
+{
+ return m_prepared;
+}
+
+void Scene2DSharedObject::setPrepared()
+{
+ m_prepared = true;
+}
+
+// not protected, call only from main thread
+bool Scene2DSharedObject::isQuit() const
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ return m_quit;
+}
+
+// not protected, call only from main thread
+void Scene2DSharedObject::requestQuit()
+{
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ m_quit = true;
+ QCoreApplication::postEvent(m_renderObject, new QEvent(QUIT));
+}
+
+bool Scene2DSharedObject::isSyncRequested() const
+{
+ return m_requestSync;
+}
+
+void Scene2DSharedObject::requestRender(bool sync)
+{
+ m_requestSync = sync;
+ QCoreApplication::postEvent(m_renderObject, new QEvent(RENDER));
+}
+
+void Scene2DSharedObject::wait()
+{
+ m_cond.wait(&m_mutex);
+}
+
+void Scene2DSharedObject::wake()
+{
+ m_cond.wakeOne();
+}
+
+void Scene2DSharedObject::clearSyncRequest()
+{
+ m_requestSync = false;
+}
+
+/*!
+ \internal
+ Constructs qml render manager.
+ */
+Scene2DManager::Scene2DManager(QScene2DPrivate *priv)
+ : m_priv(priv)
+ , m_qmlEngine(nullptr)
+ , m_qmlComponent(nullptr)
+ , m_rootItem(nullptr)
+ , m_source(nullptr)
+ , m_requested(false)
+ , m_initialized(false)
+ , m_renderSyncRequested(false)
+ , m_sharedObject(new Scene2DSharedObject(this))
+ , m_renderPolicy(QScene2D::Continuous)
+ , m_backendInitialized(false)
+ , m_noSourceMode(false)
+ , m_item(nullptr)
+ , m_ownEngine(false)
+{
+ m_sharedObject->m_surface = new QOffscreenSurface;
+ m_sharedObject->m_surface->setFormat(QSurfaceFormat::defaultFormat());
+ m_sharedObject->m_surface->create();
+
+ // Create render control
+ m_sharedObject->m_renderControl = new RenderControl(nullptr);
+
+ // Create window to render the QML with
+ m_sharedObject->m_quickWindow = new QQuickWindow(m_sharedObject->m_renderControl);
+ m_sharedObject->m_quickWindow->setClearBeforeRendering(false);
+
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::renderRequested,
+ this, &Scene2DManager::requestRender);
+ connect(m_sharedObject->m_renderControl, &QQuickRenderControl::sceneChanged,
+ this, &Scene2DManager::requestRenderSync);
+}
+
+Scene2DManager::~Scene2DManager()
+{
+ m_sharedObject = nullptr;
+}
+
+void Scene2DManager::requestRender()
+{
+ // Don't request render until the backend is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new QEvent(RENDER));
+ }
+ }
+}
+
+void Scene2DManager::requestRenderSync()
+{
+ // Don't request render until the backed is initialized.
+ if (m_sharedObject->canRender()) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new QEvent(RENDERSYNC));
+ }
+ } else {
+ m_renderSyncRequested = true;
+ }
+}
+
+void Scene2DManager::startIfInitialized()
+{
+ if (!m_initialized && m_backendInitialized) {
+ if (m_source.isValid() && !m_noSourceMode) {
+ // Create a QML engine.
+ if (!m_qmlEngine) {
+ m_qmlEngine = new QQmlEngine;
+ if (!m_qmlEngine->incubationController()) {
+ m_qmlEngine->setIncubationController(m_sharedObject->m_quickWindow
+ ->incubationController());
+ }
+ }
+
+ // create component
+ m_ownEngine = true;
+ m_qmlComponent = new QQmlComponent(m_qmlEngine, m_source);
+ if (m_qmlComponent->isLoading()) {
+ connect(m_qmlComponent, &QQmlComponent::statusChanged,
+ this, &Scene2DManager::run);
+ } else {
+ run();
+ }
+ } else if (m_item != nullptr) {
+ m_rootItem = m_item;
+
+ // Associate root item with the window.
+ m_rootItem->setParentItem(m_sharedObject->m_quickWindow->contentItem());
+
+ // Update window size.
+ updateSizes();
+
+ m_initialized = true;
+ m_sharedObject->setInitialized();
+ }
+ }
+}
+
+void Scene2DManager::stopAndClean()
+{
+ if (m_sharedObject->isInitialized()) {
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestQuit();
+ m_sharedObject->wait();
+ m_sharedObject->cleanup();
+ if (m_ownEngine) {
+ QObject::disconnect(m_connection);
+ delete m_qmlEngine;
+ }
+ delete m_qmlComponent;
+ m_qmlEngine = nullptr;
+ m_qmlComponent = nullptr;
+ }
+}
+
+void Scene2DManager::run()
+{
+ disconnect(m_qmlComponent, &QQmlComponent::statusChanged, this, &Scene2DManager::run);
+
+ if (m_qmlComponent->isError()) {
+ QList<QQmlError> errorList = m_qmlComponent->errors();
+ for (const QQmlError &error: errorList)
+ qWarning() << error.url() << error.line() << error;
+ return;
+ }
+
+ QObject *rootObject = m_qmlComponent->create();
+ if (m_qmlComponent->isError()) {
+ QList<QQmlError> errorList = m_qmlComponent->errors();
+ for (const QQmlError &error: errorList)
+ qWarning() << error.url() << error.line() << error;
+ return;
+ }
+
+ m_rootItem = qobject_cast<QQuickItem *>(rootObject);
+ if (!m_rootItem) {
+ qWarning("QScene2D: Root item is not a QQuickItem.");
+ delete rootObject;
+ return;
+ }
+
+ // The root item is ready. Associate it with the window.
+ m_rootItem->setParentItem(m_sharedObject->m_quickWindow->contentItem());
+
+ // Update window size.
+ updateSizes();
+
+ m_initialized = true;
+ m_sharedObject->setInitialized();
+
+ emit onLoadedChanged();
+}
+
+void Scene2DManager::updateSizes()
+{
+ const int width = m_rootItem->width();
+ const int height = m_rootItem->height();
+ if (width == 0 || height == 0) {
+ qWarning() << "QScene2D: Root item size not set.";
+ return;
+ }
+ m_sharedObject->m_quickWindow->setGeometry(0, 0, width, height);
+}
+
+void Scene2DManager::setSource(const QUrl &url)
+{
+ m_source = url;
+ startIfInitialized();
+}
+
+void Scene2DManager::setItem(QQuickItem *item)
+{
+ m_noSourceMode = true;
+ m_item = item;
+ startIfInitialized();
+}
+
+bool Scene2DManager::event(QEvent *e)
+{
+ switch (e->type()) {
+
+ case RENDER: {
+ // just render request, don't need to call sync in render thread
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+ m_sharedObject->requestRender(false);
+ m_requested = false;
+ return true;
+ }
+
+ case RENDERSYNC: {
+ // sync and render request, main and render threads must be synchronized
+ if (!m_sharedObject->isQuit())
+ doRenderSync();
+ m_requested = false;
+ return true;
+ }
+
+ case PREPARE: {
+ m_sharedObject->m_renderControl->prepareThread(m_sharedObject->m_renderThread);
+ m_sharedObject->setPrepared();
+
+ if (m_renderSyncRequested) {
+ if (!m_requested) {
+ m_requested = true;
+ QCoreApplication::postEvent(this, new QEvent(RENDERSYNC));
+ }
+ m_renderSyncRequested = false;
+ }
+ return true;
+ }
+
+ case INITIALIZED: {
+ // backend is initialized, start the qml
+ m_backendInitialized = true;
+ startIfInitialized();
+ return true;
+ }
+
+ case RENDERED: {
+ // render is done, excellent, now clean anything not needed anymore.
+ stopAndClean();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+bool Scene2DManager::forwardEvent(QEvent *event)
+{
+ switch (event->type()) {
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent* me = static_cast<QMouseEvent *>(event);
+ QPointF pos = me->localPos();
+ pos = QPointF(pos.x() * m_rootItem->width(), pos.y() * m_rootItem->height());
+ QMouseEvent nme = QMouseEvent(me->type(), pos, pos, pos, me->button(), me->buttons(),
+ me->modifiers(), Qt::MouseEventSynthesizedByApplication);
+ QCoreApplication::sendEvent(m_sharedObject->m_quickWindow, &nme);
+ } break;
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ QCoreApplication::sendEvent(m_sharedObject->m_quickWindow, event);
+ } break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+void Scene2DManager::doRenderSync()
+{
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ m_sharedObject->requestRender(true);
+ m_sharedObject->m_renderControl->polishItems();
+
+ // begin waiting render thread
+ m_sharedObject->wait();
+ m_requested = false;
+}
+
+void Scene2DManager::cleanup()
+{
+ stopAndClean();
+}
+
+void Scene2DManager::setEngine(QQmlEngine *engine)
+{
+ m_qmlEngine = engine;
+ m_ownEngine = false;
+ if (engine) {
+ m_connection = QObject::connect(engine, &QObject::destroyed,
+ this, &Scene2DManager::engineDestroyed);
+ }
+}
+
+void Scene2DManager::engineDestroyed()
+{
+ QObject::disconnect(m_connection);
+ m_qmlEngine = nullptr;
+ m_ownEngine = false;
+}
+
+
+QScene2DPrivate::QScene2DPrivate()
+ : Qt3DCore::QNodePrivate()
+ , m_renderManager(new Scene2DManager(this))
+ , m_output(nullptr)
+{
+}
+
+QScene2DPrivate::~QScene2DPrivate()
+{
+ m_renderManager->cleanup();
+ delete m_renderManager;
+}
+
+
+/*!
+ The constructor creates a new QScene2D instance with the specified \a parent.
+ */
+QScene2D::QScene2D(Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QScene2DPrivate, parent)
+{
+ Q_D(QScene2D);
+ connect(d->m_renderManager, &Scene2DManager::onLoadedChanged,
+ this, &QScene2D::sourceLoaded);
+}
+
+QScene2D::QScene2D(QQmlEngine *engine, Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QScene2DPrivate, parent)
+{
+ Q_D(QScene2D);
+ connect(d->m_renderManager, &Scene2DManager::onLoadedChanged,
+ this, &QScene2D::sourceLoaded);
+ d->m_renderManager->setEngine(engine);
+}
+
+QScene2D::~QScene2D()
+{
+}
+
+bool QScene2D::loaded() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_initialized;
+}
+
+/*!
+ \property QScene2D::source
+ \brief Specifies the url for the qml.
+
+ This property specifies the url to the qml being rendered to the texture.
+ The source must specify QQuickItem as a root. The item must specify width
+ and height. The rendered qml is scaled to the texture size.
+ The property can not be changed after the rendering has been initialized.
+ */
+QUrl QScene2D::source() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_source;
+}
+
+void QScene2D::setSource(const QUrl &url)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_initialized) {
+ qWarning() << "Unable to set source after initialization.";
+ return;
+ }
+ if (d->m_renderManager->m_source != url) {
+ d->m_renderManager->setSource(url);
+ emit sourceChanged(url);
+ }
+}
+
+QQuickItem* QScene2D::item() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_item;
+}
+
+void QScene2D::setItem(QQuickItem *item)
+{
+ Q_D(QScene2D);
+ if (d->m_renderManager->m_initialized) {
+ qWarning() << "Unable to set item after initialization.";
+ return;
+ }
+ if (d->m_renderManager->m_item != item) {
+ d->m_renderManager->setItem(item);
+ emit itemChanged(item);
+ }
+}
+
+/*!
+ \property QScene2D::renderPolicy
+
+ Holds the render policy of this Scene2D.
+ */
+QScene2D::RenderPolicy QScene2D::renderPolicy() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_renderPolicy;
+}
+
+void QScene2D::setRenderPolicy(QScene2D::RenderPolicy renderPolicy)
+{
+ Q_D(const QScene2D);
+ if (d->m_renderManager->m_renderPolicy != renderPolicy) {
+ d->m_renderManager->m_renderPolicy = renderPolicy;
+ emit renderPolicyChanged(renderPolicy);
+ }
+}
+
+/*!
+ \property QScene2D::output
+ Holds the QRenderTargetOutput, which specifies where the QScene2D is
+ rendering to.
+ */
+Qt3DRender::QRenderTargetOutput *QScene2D::output() const
+{
+ Q_D(const QScene2D);
+ return d->m_output;
+}
+
+void QScene2D::setOutput(Qt3DRender::QRenderTargetOutput *output)
+{
+ Q_D(QScene2D);
+ if (d->m_output != output) {
+ if (d->m_output)
+ d->unregisterDestructionHelper(d->m_output);
+ d->m_output = output;
+ if (output)
+ d->registerDestructionHelper(output, &QScene2D::setOutput, d->m_output);
+ emit outputChanged(output);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QScene2D::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QScene2DData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QScene2D);
+ data.renderPolicy = d->m_renderManager->m_renderPolicy;
+ data.sharedObject = d->m_renderManager->m_sharedObject;
+ data.output = d->m_output ? d->m_output->id() : Qt3DCore::QNodeId();
+ return creationChange;
+}
+
+bool QScene2D::event(QEvent *event)
+{
+ Q_D(QScene2D);
+ d->m_renderManager->forwardEvent(event);
+ return true;
+}
+
+/*!
+ Returns the qml engine used by the QScene2D.
+ */
+QQmlEngine *QScene2D::engine() const
+{
+ Q_D(const QScene2D);
+ return d->m_renderManager->m_qmlEngine;
+}
+
+/*!
+ \internal
+ */
+void QScene2D::sourceLoaded()
+{
+ emit loadedChanged(true);
+}
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d.h b/src/quick3d/quick3drender/scene2d/qscene2d.h
new file mode 100644
index 000000000..0a7e943d6
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/qscene2d.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_QSCENE2D_H
+#define QT3DRENDER_QUICK3DRENDER_QSCENE2D_H
+
+#include <Qt3DQuickRender/qt3dquickrender_global.h>
+#include <Qt3DRender/qrendertargetoutput.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QEvent>
+
+#include <Qt3DCore/qnode.h>
+
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2DPrivate;
+
+class QT3DQUICKRENDERSHARED_EXPORT QScene2D : public Qt3DCore::QNode
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Qt3DRender::QRenderTargetOutput *output READ output WRITE setOutput NOTIFY outputChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QScene2D::RenderPolicy renderPolicy READ renderPolicy WRITE setRenderPolicy NOTIFY renderPolicyChanged)
+ Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
+ Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
+
+ Q_CLASSINFO("DefaultProperty", "item")
+
+public:
+
+ enum RenderPolicy {
+ Continuous,
+ SingleShot
+ };
+ Q_ENUM(RenderPolicy)
+
+ explicit QScene2D(Qt3DCore::QNode *parent = nullptr);
+ QScene2D(QQmlEngine *engine, Qt3DCore::QNode *parent = nullptr);
+ ~QScene2D();
+
+ Qt3DRender::QRenderTargetOutput *output() const;
+ QUrl source() const;
+ bool loaded() const;
+ QScene2D::RenderPolicy renderPolicy() const;
+ QQuickItem *item() const;
+ QQmlEngine *engine() const;
+ bool event(QEvent *event) Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void setOutput(Qt3DRender::QRenderTargetOutput *output);
+ void setSource(const QUrl &url);
+ void setRenderPolicy(QScene2D::RenderPolicy policy);
+ void setItem(QQuickItem *item);
+
+Q_SIGNALS:
+ void outputChanged(Qt3DRender::QRenderTargetOutput *output);
+ void sourceChanged(const QUrl &url);
+ void loadedChanged(bool loaded);
+ void renderPolicyChanged(QScene2D::RenderPolicy policy);
+ void itemChanged(QQuickItem *item);
+
+protected:
+ Q_DECLARE_PRIVATE(QScene2D)
+
+private:
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+
+ void sourceLoaded();
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QUICK3DRENDER_QSCENE2D_H
diff --git a/src/quick3d/quick3drender/scene2d/qscene2d_p.h b/src/quick3d/quick3drender/scene2d/qscene2d_p.h
new file mode 100644
index 000000000..34b54b231
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/qscene2d_p.h
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QUICK3DRENDER_QSCENE2D_P_H
+#define QT3DRENDER_QUICK3DRENDER_QSCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlComponent>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QQuickRenderControl>
+#include <QtGui/QOffscreenSurface>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QThread>
+
+#include <Qt3DQuickRender/qscene2d.h>
+#include <Qt3DRender/qabstracttexture.h>
+
+#include <private/qobject_p.h>
+#include <private/qnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Quick {
+
+class QScene2D;
+class Scene2DManager;
+
+// render thread -> render thread
+static const QEvent::Type INITIALIZE = QEvent::Type(QEvent::User + 1);
+
+// main thread -> main thread, render thread
+static const QEvent::Type RENDER = QEvent::Type(QEvent::User + 2);
+
+// main thread -> main thread
+static const QEvent::Type RENDERSYNC = QEvent::Type(QEvent::User + 3);
+
+// render thread -> main thread
+static const QEvent::Type PREPARE = QEvent::Type(QEvent::User + 4);
+static const QEvent::Type INITIALIZED = QEvent::Type(QEvent::User + 5);
+static const QEvent::Type RENDERED = QEvent::Type(QEvent::User + 6);
+
+// main thread -> render thread
+static const QEvent::Type QUIT = QEvent::Type(QEvent::User + 7);
+
+class Q_AUTOTEST_EXPORT Scene2DSharedObject
+{
+public:
+ Scene2DSharedObject(Scene2DManager *manager);
+ ~Scene2DSharedObject();
+
+ QQuickRenderControl *m_renderControl;
+ QQuickWindow *m_quickWindow;
+ Scene2DManager *m_renderManager;
+ QOffscreenSurface *m_surface;
+
+ QThread *m_renderThread;
+ QObject *m_renderObject;
+
+ QWaitCondition m_cond;
+ QMutex m_mutex;
+
+ bool isInitialized() const;
+ void setInitialized();
+
+ void requestQuit();
+ bool isQuit() const;
+
+ void requestRender(bool sync);
+
+ bool isSyncRequested() const;
+ void clearSyncRequest();
+
+ void wait();
+ void wake();
+
+ bool isPrepared() const;
+ void setPrepared();
+
+ void disallowRender();
+ bool canRender() const;
+
+ void cleanup();
+
+private:
+
+ bool m_disallowed;
+ bool m_quit;
+ bool m_requestSync;
+ bool m_requestRender;
+ bool m_prepared;
+ bool m_initialized;
+};
+
+typedef QSharedPointer<Scene2DSharedObject> Scene2DSharedObjectPtr;
+
+class Q_AUTOTEST_EXPORT QScene2DPrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QScene2D)
+
+ QScene2DPrivate();
+ ~QScene2DPrivate();
+
+ Scene2DManager *m_renderManager;
+ QMetaObject::Connection m_textureDestroyedConnection;
+ Qt3DRender::QRenderTargetOutput *m_output;
+};
+
+struct QScene2DData
+{
+ QScene2D::RenderPolicy renderPolicy;
+ Scene2DSharedObjectPtr sharedObject;
+ Qt3DCore::QNodeId output;
+};
+
+class Scene2DManager : public QObject
+{
+ Q_OBJECT
+public:
+ Scene2DManager(QScene2DPrivate *priv);
+ ~Scene2DManager();
+
+ QQmlEngine *m_qmlEngine;
+ QQmlComponent *m_qmlComponent;
+ QQuickItem *m_rootItem;
+ QQuickItem *m_item;
+
+ QScene2DPrivate *m_priv;
+ QSharedPointer<Scene2DSharedObject> m_sharedObject;
+
+ QUrl m_source;
+ Qt3DCore::QNodeId m_id;
+ QMetaObject::Connection m_connection;
+ QScene2D::RenderPolicy m_renderPolicy;
+
+ bool m_requested;
+ bool m_initialized;
+ bool m_renderSyncRequested;
+ bool m_backendInitialized;
+ bool m_noSourceMode;
+ bool m_ownEngine;
+
+ void requestRender();
+ void requestRenderSync();
+ void doRenderSync();
+ void startIfInitialized();
+ void stopAndClean();
+ void run();
+ void updateSizes();
+
+ void setSource(const QUrl &url);
+ void setItem(QQuickItem *item);
+
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+ bool forwardEvent(QEvent *event);
+
+ Q_SIGNAL void onLoadedChanged();
+
+ void cleanup();
+ void setEngine(QQmlEngine *engine);
+ void engineDestroyed();
+};
+
+} // namespace Quick
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::Quick::Scene2DSharedObjectPtr)
+
+#endif // QT3DRENDER_QUICK3DRENDER_QSCENE2D_P_H
diff --git a/src/quick3d/quick3drender/scene2d/scene2d.cpp b/src/quick3d/quick3drender/scene2d/scene2d.cpp
new file mode 100644
index 000000000..227829f3e
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/scene2d.cpp
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DQuickRender/qscene2d.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qatomic.h>
+
+#include <private/qscene2d_p.h>
+#include <private/scene2d_p.h>
+#include <private/graphicscontext_p.h>
+#include <private/texture_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/resourceaccessor_p.h>
+#include <private/attachmentpack_p.h>
+#include <private/qt3dquickrender_logging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
+using namespace Qt3DRender::Quick;
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace Quick {
+
+Q_GLOBAL_STATIC(QThread, renderThread)
+Q_GLOBAL_STATIC(QAtomicInt, renderThreadClientCount)
+
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
+RenderQmlEventHandler::RenderQmlEventHandler(Scene2D *node)
+ : QObject()
+ , m_node(node)
+{
+}
+
+// Event handler for the RenderQmlToTexture::renderThread
+bool RenderQmlEventHandler::event(QEvent *e)
+{
+ switch (e->type()) {
+
+ case RENDER: {
+ m_node->render();
+ return true;
+ }
+
+ case INITIALIZE: {
+ m_node->initializeRender();
+ return true;
+ }
+
+ case QUIT: {
+ m_node->cleanup();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+Scene2D::Scene2D()
+ : m_context(nullptr)
+ , m_shareContext(nullptr)
+ , m_sharedObject(nullptr)
+ , m_renderThread(nullptr)
+ , m_initialized(false)
+ , m_renderInitialized(false)
+ , m_renderPolicy(Qt3DRender::Quick::QScene2D::Continuous)
+ , m_fbo(0)
+ , m_rbo(0)
+{
+ renderThreadClientCount->fetchAndAddAcquire(1);
+}
+
+Scene2D::~Scene2D()
+{
+ // this gets called from aspect thread. Wait for the render thread then delete it.
+ // TODO: render thread deletion
+// if (m_renderThread) {
+// m_renderThread->wait(1000);
+// delete m_renderThread;
+// }
+}
+
+void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
+{
+ m_outputId = outputId;
+}
+
+void Scene2D::initializeSharedObject()
+{
+ if (!m_initialized) {
+
+ renderThread->setObjectName(QStringLiteral("Scene2D::renderThread"));
+ m_renderThread = renderThread;
+ m_sharedObject->m_renderThread = m_renderThread;
+
+ // Create event handler for the render thread
+ m_sharedObject->m_renderObject = new RenderQmlEventHandler(this);
+ m_sharedObject->m_renderObject->moveToThread(m_sharedObject->m_renderThread);
+ if (!m_sharedObject->m_renderThread->isRunning())
+ m_sharedObject->m_renderThread->start();
+
+ // Notify main thread we have been initialized
+ if (m_sharedObject->m_renderManager)
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(INITIALIZED));
+
+ // Initialize render thread
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject, new QEvent(INITIALIZE));
+
+ m_initialized = true;
+ }
+}
+
+void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
+ const auto &data = typedChange->data;
+ m_renderPolicy = data.renderPolicy;
+ setSharedObject(data.sharedObject);
+ setOutput(data.output);
+ m_shareContext = renderer()->shareContext();
+}
+
+void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ if (e->type() == 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("sharedObject")) {
+ const Scene2DSharedObjectPtr sharedObject
+ = propertyChange->value().value<Scene2DSharedObjectPtr>();
+ setSharedObject(sharedObject);
+ }
+ }
+ BackendNode::sceneChangeEvent(e);
+}
+
+void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
+{
+ m_sharedObject = sharedObject;
+ if (!m_initialized)
+ initializeSharedObject();
+}
+
+void Scene2D::initializeRender()
+{
+ if (!m_renderInitialized && m_sharedObject.data() != nullptr) {
+
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+
+ m_context = new QOpenGLContext();
+ m_context->setFormat(format);
+ m_context->setShareContext(m_shareContext);
+ m_context->create();
+
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->initialize(m_context);
+ m_context->doneCurrent();
+
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(PREPARE));
+ m_renderInitialized = true;
+ }
+}
+
+bool Scene2D::updateFbo(QOpenGLTexture *texture)
+{
+ QOpenGLFunctions *gl = m_context->functions();
+ if (m_fbo == 0) {
+ gl->glGenFramebuffers(1, &m_fbo);
+ gl->glGenRenderbuffers(1, &m_rbo);
+ }
+ // TODO: Add another codepath when GL_DEPTH24_STENCIL8 is not supported
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
+ gl->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ m_textureSize.width(), m_textureSize.height());
+ gl->glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+ gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture->textureId(), 0);
+ gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo);
+ GLenum status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ gl->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ return false;
+ return true;
+}
+
+void Scene2D::syncRenderControl()
+{
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+void Scene2D::render()
+{
+ if (m_initialized && m_renderInitialized && m_sharedObject.data() != nullptr) {
+
+ QMutexLocker lock(&m_sharedObject->m_mutex);
+
+ QOpenGLTexture *texture = nullptr;
+ const Qt3DRender::Render::Attachment *attachmentData = nullptr;
+ QMutex *textureLock = nullptr;
+
+ m_context->makeCurrent(m_sharedObject->m_surface);
+
+ if (resourceAccessor()->accessResource(m_outputId, (void**)&attachmentData, nullptr)) {
+ if (!resourceAccessor()->accessResource(attachmentData->m_textureUuid,
+ (void**)&texture, &textureLock)) {
+ // Need to call sync even if the texture is not in use
+ syncRenderControl();
+ m_context->doneCurrent();
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Texture not in use.";
+ QCoreApplication::postEvent(m_sharedObject->m_renderObject, new QEvent(RENDER));
+ return;
+ }
+ textureLock->lock();
+ const QSize textureSize = QSize(texture->width(), texture->height());
+ if (m_attachmentData.m_textureUuid != attachmentData->m_textureUuid
+ || m_attachmentData.m_point != attachmentData->m_point
+ || m_attachmentData.m_face != attachmentData->m_face
+ || m_attachmentData.m_layer != attachmentData->m_layer
+ || m_attachmentData.m_mipLevel != attachmentData->m_mipLevel
+ || m_textureSize != textureSize) {
+ m_textureSize = textureSize;
+ m_attachmentData = *attachmentData;
+ if (!updateFbo(texture)) {
+ // Need to call sync even if the fbo is not usable
+ syncRenderControl();
+ textureLock->unlock();
+ m_context->doneCurrent();
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO << "Fbo not initialized.";
+ return;
+ }
+ }
+ }
+
+ if (m_fbo != m_sharedObject->m_quickWindow->renderTargetId())
+ m_sharedObject->m_quickWindow->setRenderTarget(m_fbo, m_textureSize);
+
+ // Call disallow rendering while mutex is locked
+ if (m_renderPolicy == QScene2D::SingleShot)
+ m_sharedObject->disallowRender();
+
+ // Sync
+ if (m_sharedObject->isSyncRequested()) {
+
+ m_sharedObject->clearSyncRequest();
+
+ m_sharedObject->m_renderControl->sync();
+ }
+
+ // Render
+ m_sharedObject->m_renderControl->render();
+
+ // Tell main thread we are done so it can begin cleanup if this is final frame
+ if (m_renderPolicy == QScene2D::SingleShot)
+ QCoreApplication::postEvent(m_sharedObject->m_renderManager, new QEvent(RENDERED));
+
+ m_sharedObject->m_quickWindow->resetOpenGLState();
+ m_context->functions()->glFlush();
+ if (texture->isAutoMipMapGenerationEnabled())
+ texture->generateMipMaps();
+ textureLock->unlock();
+ m_context->doneCurrent();
+
+ // gui thread can now continue
+ m_sharedObject->wake();
+ }
+}
+
+// this function gets called while the main thread is waiting
+void Scene2D::cleanup()
+{
+ if (m_renderInitialized && m_initialized) {
+ m_context->makeCurrent(m_sharedObject->m_surface);
+ m_sharedObject->m_renderControl->invalidate();
+ m_context->functions()->glDeleteFramebuffers(1, &m_fbo);
+ m_context->functions()->glDeleteRenderbuffers(1, &m_rbo);
+ m_context->doneCurrent();
+ m_renderInitialized = false;
+ }
+ if (m_initialized) {
+ delete m_sharedObject->m_renderObject;
+ m_sharedObject->m_renderObject = nullptr;
+ delete m_context;
+ m_context = nullptr;
+ m_initialized = false;
+ }
+ // wake up the main thread
+ m_sharedObject->wake();
+ m_sharedObject = nullptr;
+
+ renderThreadClientCount->fetchAndSubAcquire(1);
+ if (renderThreadClientCount->load() == 0)
+ renderThread->quit();
+}
+
+} // namespace Quick
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3drender/scene2d/scene2d.pri b/src/quick3d/quick3drender/scene2d/scene2d.pri
new file mode 100644
index 000000000..4635c43e1
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/scene2d.pri
@@ -0,0 +1,10 @@
+HEADERS += \
+ $$PWD/qscene2d.h \
+ $$PWD/qscene2d_p.h \
+ $$PWD/scene2d_p.h
+
+SOURCES += \
+ $$PWD/qscene2d.cpp \
+ $$PWD/scene2d.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3drender/scene2d/scene2d_p.h b/src/quick3d/quick3drender/scene2d/scene2d_p.h
new file mode 100644
index 000000000..3a8ccf531
--- /dev/null
+++ b/src/quick3d/quick3drender/scene2d/scene2d_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QUICK_SCENE2D_P_H
+#define QT3DRENDER_RENDER_QUICK_SCENE2D_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DQuickRender/qscene2d.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QSemaphore>
+
+#include <private/qscene2d_p.h>
+#include <private/qrendertargetoutput_p.h>
+#include <private/backendnode_p.h>
+#include <private/attachmentpack_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class GraphicsContext;
+
+namespace Quick {
+
+class Scene2D;
+
+class RenderQmlEventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ RenderQmlEventHandler(Scene2D *node);
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+private:
+ Scene2D *m_node;
+};
+
+class QT3DQUICKRENDERSHARED_EXPORT Scene2D : public Qt3DRender::Render::BackendNode
+{
+public:
+ Scene2D();
+ ~Scene2D();
+
+ void render();
+ void initializeRender();
+ void setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject);
+ void cleanup();
+ void setOutput(Qt3DCore::QNodeId outputId);
+ void initializeSharedObject();
+
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_OVERRIDE;
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+
+ bool updateFbo(QOpenGLTexture *texture);
+ void syncRenderControl();
+
+ QOpenGLContext *m_context;
+ QOpenGLContext *m_shareContext;
+ QThread *m_renderThread;
+ Qt3DCore::QNodeId m_outputId;
+ QSharedPointer<Qt3DRender::Quick::Scene2DSharedObject> m_sharedObject;
+ Qt3DCore::QNodeId m_peerId;
+ Qt3DRender::Render::Attachment m_attachmentData;
+
+ GLuint m_fbo;
+ GLuint m_rbo;
+ QSize m_textureSize;
+
+ bool m_initialized;
+ bool m_renderInitialized;
+ Qt3DRender::Quick::QScene2D::RenderPolicy m_renderPolicy;
+};
+
+} // Quick
+} // Render
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QUICK_SCENE2D_P_H
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 8b17cbf45..f8d9850e7 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -56,6 +56,8 @@
#include <Qt3DCore/qnodeid.h>
#include <QtGui/qsurfaceformat.h>
+#include <QtGui/qopenglcontext.h>
+
QT_BEGIN_NAMESPACE
class QSurface;
@@ -153,6 +155,7 @@ public:
virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0;
virtual QSurfaceFormat format() = 0;
+ virtual QOpenGLContext *shareContext() const = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractRenderer::BackendNodeDirtySet)
diff --git a/src/render/backend/attachmentpack.cpp b/src/render/backend/attachmentpack.cpp
index d2bb5ee9a..6dee7587b 100644
--- a/src/render/backend/attachmentpack.cpp
+++ b/src/render/backend/attachmentpack.cpp
@@ -60,7 +60,7 @@ AttachmentPack::AttachmentPack(const RenderTargetSelector *selector, const Rende
for (Qt3DCore::QNodeId outputId : outputIds) {
const RenderTargetOutput *output = attachmentManager->lookupResource(outputId);
if (output)
- m_attachments.append(output->attachment());
+ m_attachments.append(*output->attachment());
}
// Create actual DrawBuffers list that is used for glDrawBuffers
diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp
index 7054db6a4..0dc8da237 100644
--- a/src/render/backend/backendnode.cpp
+++ b/src/render/backend/backendnode.cpp
@@ -37,7 +37,10 @@
**
****************************************************************************/
-#include "backendnode_p.h"
+#include <private/backendnode_p.h>
+#include <private/renderer_p.h>
+#include <private/resourceaccessor_p.h>
+#include <private/nodemanagers_p.h>
QT_BEGIN_NAMESPACE
@@ -61,12 +64,23 @@ void BackendNode::setRenderer(AbstractRenderer *renderer)
m_renderer = renderer;
}
+AbstractRenderer *BackendNode::renderer() const
+{
+ return m_renderer;
+}
+
void BackendNode::markDirty(AbstractRenderer::BackendNodeDirtySet changes)
{
Q_ASSERT(m_renderer);
m_renderer->markDirty(changes, this);
}
+QSharedPointer<RenderBackendResourceAccessor> BackendNode::resourceAccessor()
+{
+ Render::Renderer *r = static_cast<Render::Renderer *>(renderer());
+ return r->nodeManagers()->resourceAccessor();
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h
index 5688c2412..8db68b11d 100644
--- a/src/render/backend/backendnode_p.h
+++ b/src/render/backend/backendnode_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/qt3drender_global.h>
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DRender/private/abstractrenderer_p.h>
+#include <private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
@@ -61,13 +62,18 @@ namespace Qt3DRender {
namespace Render {
-class Q_AUTOTEST_EXPORT BackendNode : public Qt3DCore::QBackendNode
+class RenderBackendResourceAccessor;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT BackendNode : public Qt3DCore::QBackendNode
{
public:
BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
~BackendNode();
void setRenderer(AbstractRenderer *renderer);
+ AbstractRenderer *renderer() const;
+
+ QSharedPointer<RenderBackendResourceAccessor> resourceAccessor();
protected:
void markDirty(AbstractRenderer::BackendNodeDirtySet changes);
diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h
index ce6767958..d9e46db45 100644
--- a/src/render/backend/managers_p.h
+++ b/src/render/backend/managers_p.h
@@ -78,6 +78,7 @@
#include <Qt3DRender/private/openglvertexarrayobject_p.h>
#include <Qt3DRender/private/light_p.h>
#include <Qt3DRender/private/computecommand_p.h>
+#include <Qt3DRender/private/eventforward_p.h>
QT_BEGIN_NAMESPACE
@@ -359,6 +360,15 @@ class ObjectPickerManager : public Qt3DCore::QResourceManager<
{
};
+class EventForwardManager : public Qt3DCore::QResourceManager<
+ EventForward,
+ Qt3DCore::QNodeId,
+ 8,
+ Qt3DCore::ArrayAllocatingPolicy,
+ Qt3DCore::NonLockingPolicy>
+{
+};
+
#if 0
class BoundingVolumeDebugManager : public Qt3DCore::QResourceManager<
BoundingVolumeDebug,
diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp
index d83623ce2..f6a3441c2 100644
--- a/src/render/backend/nodemanagers.cpp
+++ b/src/render/backend/nodemanagers.cpp
@@ -46,6 +46,7 @@
#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
+#include <private/resourceaccessor_p.h>
#include <QOpenGLVertexArrayObject>
@@ -90,6 +91,8 @@ NodeManagers::NodeManagers()
, m_lightManager(new LightManager())
, m_computeJobManager(new ComputeCommandManager())
, m_renderStateManager(new RenderStateManager())
+ , m_eventForwardManager(new EventForwardManager())
+ , m_resourceAccessor(new ResourceAccessor(this))
{
}
@@ -129,6 +132,12 @@ NodeManagers::~NodeManagers()
delete m_computeJobManager;
delete m_renderStateManager;
delete m_renderNodesManager;
+ delete m_eventForwardManager;
+}
+
+QSharedPointer<ResourceAccessor> NodeManagers::resourceAccessor()
+{
+ return m_resourceAccessor;
}
template<>
@@ -323,6 +332,12 @@ RenderStateManager *NodeManagers::manager<RenderStateNode>() const Q_DECL_NOTHRO
return m_renderStateManager;
}
+template<>
+EventForwardManager *NodeManagers::manager<EventForward>() const Q_DECL_NOTHROW
+{
+ return m_eventForwardManager;
+}
+
} // Render
} // Qt3DRender
diff --git a/src/render/backend/nodemanagers_p.h b/src/render/backend/nodemanagers_p.h
index b1ea2a0de..993e6f5cc 100644
--- a/src/render/backend/nodemanagers_p.h
+++ b/src/render/backend/nodemanagers_p.h
@@ -98,6 +98,7 @@ class LevelOfDetailManager;
class LightManager;
class ComputeCommandManager;
class RenderStateManager;
+class EventForwardManager;
class FrameGraphNode;
class Entity;
@@ -125,12 +126,15 @@ class Attribute;
class Geometry;
class GeometryRenderer;
class ObjectPicker;
+class EventForward;
//class BoundingVolumeDebug;
class Light;
class ComputeCommand;
class RenderStateNode;
class OpenGLVertexArrayObject;
+class ResourceAccessor;
+
class QT3DRENDERSHARED_PRIVATE_EXPORT NodeManagers
{
public:
@@ -205,6 +209,9 @@ public:
inline LightManager *lightManager() const Q_DECL_NOEXCEPT { return m_lightManager; }
inline ComputeCommandManager *computeJobManager() const Q_DECL_NOEXCEPT { return m_computeJobManager; }
inline RenderStateManager *renderStateManager() const Q_DECL_NOEXCEPT { return m_renderStateManager; }
+ inline EventForwardManager *eventForwardManager() const Q_DECL_NOEXCEPT { return m_eventForwardManager; }
+
+ QSharedPointer<ResourceAccessor> resourceAccessor();
private:
CameraManager *m_cameraManager;
@@ -241,6 +248,9 @@ private:
LightManager *m_lightManager;
ComputeCommandManager *m_computeJobManager;
RenderStateManager *m_renderStateManager;
+ EventForwardManager *m_eventForwardManager;
+
+ QSharedPointer<ResourceAccessor> m_resourceAccessor;
};
// Specializations
@@ -329,6 +339,9 @@ QT3DRENDERSHARED_PRIVATE_EXPORT GeometryRendererManager *NodeManagers::manager<G
template<>
QT3DRENDERSHARED_PRIVATE_EXPORT ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const Q_DECL_NOEXCEPT;
+template<>
+QT3DRENDERSHARED_PRIVATE_EXPORT EventForwardManager *NodeManagers::manager<EventForward>() const Q_DECL_NOEXCEPT;
+
//template<>
//QT3DRENDERSHARED_PRIVATE_EXPORT BoundingVolumeDebugManager *NodeManagers::manager<BoundingVolumeDebug>() const Q_DECL_NOEXCEPT;
@@ -341,6 +354,9 @@ QT3DRENDERSHARED_PRIVATE_EXPORT ComputeCommandManager *NodeManagers::manager<Com
template<>
QT3DRENDERSHARED_PRIVATE_EXPORT RenderStateManager *NodeManagers::manager<RenderStateNode>() const Q_DECL_NOEXCEPT;
+template<>
+QT3DRENDERSHARED_PRIVATE_EXPORT EventForwardManager *NodeManagers::manager<EventForward>() const Q_DECL_NOEXCEPT;
+
} // Render
} // Qt3DRender
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 93e323caa..1cd911df8 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -41,7 +41,8 @@ HEADERS += \
$$PWD/shaderparameterpack_p.h \
$$PWD/renderviewbuilder_p.h \
$$PWD/frameprofiler_p.h \
- $$PWD/offscreensurfacehelper_p.h
+ $$PWD/offscreensurfacehelper_p.h \
+ $$PWD/resourceaccessor_p.h
SOURCES += \
$$PWD/renderthread.cpp \
@@ -75,5 +76,6 @@ SOURCES += \
$$PWD/uniform.cpp \
$$PWD/shaderparameterpack.cpp \
$$PWD/renderviewbuilder.cpp \
- $$PWD/offscreensurfacehelper.cpp
+ $$PWD/offscreensurfacehelper.cpp \
+ $$PWD/resourceaccessor.cpp
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index bc9dde83e..1c8875b58 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -154,6 +154,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_waitForInitializationToBeCompleted(0)
, m_pickEventFilter(new PickEventFilter())
, m_exposed(0)
+ , m_shareContext(nullptr)
, m_changeSet(0)
, m_lastFrameCorrect(0)
, m_glContext(nullptr)
@@ -273,6 +274,17 @@ NodeManagers *Renderer::nodeManagers() const
return m_nodesManager;
}
+/*!
+ \internal
+
+ Return context which can be used to share resources safely
+ with qt3d main render context.
+*/
+QOpenGLContext *Renderer::shareContext() const
+{
+ return m_shareContext ? m_shareContext : m_graphicsContext->openGLContext();
+}
+
void Renderer::setOpenGLContext(QOpenGLContext *context)
{
m_glContext = context;
@@ -314,6 +326,10 @@ void Renderer::initialize()
// Context is not owned by us, so we need to know if it gets destroyed
m_contextConnection = QObject::connect(m_glContext, &QOpenGLContext::aboutToBeDestroyed,
[this] { releaseGraphicsResources(); });
+ m_shareContext = new QOpenGLContext;
+ m_shareContext->setFormat(m_glContext->format());
+ m_shareContext->setShareContext(m_glContext);
+ m_shareContext->create();
}
// Note: we don't have a surface at this point
@@ -412,6 +428,8 @@ void Renderer::releaseGraphicsResources()
if (m_ownedContext)
delete context;
+ if (m_shareContext)
+ delete m_shareContext;
m_graphicsContext.reset(nullptr);
qCDebug(Backend) << Q_FUNC_INFO << "Renderer properly shutdown";
@@ -1686,7 +1704,12 @@ void Renderer::cleanGraphicsResources()
QList<QMouseEvent> Renderer::pendingPickingEvents() const
{
- return m_pickEventFilter->pendingEvents();
+ return m_pickEventFilter->pendingMouseEvents();
+}
+
+QList<QKeyEvent> Renderer::pendingKeyEvents() const
+{
+ return m_pickEventFilter->pendingKeyEvents();
}
const GraphicsApiFilterData *Renderer::contextInfo() const
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index 9b5c35ed1..079d30e23 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -209,6 +209,7 @@ public:
virtual void setSettings(RenderSettings *settings) Q_DECL_OVERRIDE;
virtual RenderSettings *settings() const Q_DECL_OVERRIDE;
+ QOpenGLContext *shareContext() const Q_DECL_OVERRIDE;
void updateGLResources();
void updateTexture(Texture *texture);
@@ -230,8 +231,8 @@ public:
inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; }
-
QList<QMouseEvent> pendingPickingEvents() const;
+ QList<QKeyEvent> pendingKeyEvents() const;
void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId);
const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests();
@@ -300,6 +301,7 @@ private:
BackendNodeDirtySet m_changeSet;
QAtomicInt m_lastFrameCorrect;
QOpenGLContext *m_glContext;
+ QOpenGLContext *m_shareContext;
PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
qint64 m_time;
diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp
index faebfacb6..cba92596d 100644
--- a/src/render/backend/rendertargetoutput.cpp
+++ b/src/render/backend/rendertargetoutput.cpp
@@ -121,9 +121,14 @@ void RenderTargetOutput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
BackendNode::sceneChangeEvent(e);
}
-Attachment RenderTargetOutput::attachment() const
+Qt3DRender::Render::Attachment *RenderTargetOutput::attachment()
{
- return m_attachmentData;
+ return &m_attachmentData;
+}
+
+const Attachment *RenderTargetOutput::attachment() const
+{
+ return &m_attachmentData;
}
} // namespace Render
diff --git a/src/render/backend/rendertargetoutput_p.h b/src/render/backend/rendertargetoutput_p.h
index 14daa84e9..b7867c2cb 100644
--- a/src/render/backend/rendertargetoutput_p.h
+++ b/src/render/backend/rendertargetoutput_p.h
@@ -77,7 +77,8 @@ public:
QAbstractTexture::CubeMapFace face() const;
QRenderTargetOutput::AttachmentPoint point() const;
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
- Attachment attachment() const;
+ Attachment *attachment();
+ const Attachment *attachment() const;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
diff --git a/src/render/backend/resourceaccessor.cpp b/src/render/backend/resourceaccessor.cpp
new file mode 100644
index 000000000..c02130aa9
--- /dev/null
+++ b/src/render/backend/resourceaccessor.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "resourceaccessor_p.h"
+
+#include <Qt3DRender/qrendertargetoutput.h>
+
+#include <private/qrendertargetoutput_p.h>
+#include <private/nodemanagers_p.h>
+#include <private/texture_p.h>
+#include <private/rendertargetoutput_p.h>
+#include <private/texturedatamanager_p.h>
+#include <private/gltexturemanager_p.h>
+#include <private/managers_p.h>
+#include <private/gltexture_p.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+ResourceAccessor::ResourceAccessor(NodeManagers *mgr)
+ : m_textureManager(mgr->textureManager())
+ , m_attachmentManager(mgr->attachmentManager())
+ , m_glTextureManager(mgr->glTextureManager())
+{
+
+}
+
+// called by render plugins from arbitrary thread
+bool ResourceAccessor::accessResource(Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock)
+{
+ Texture *tex = m_textureManager->lookupResource(nodeId);
+ if (!tex) {
+ RenderTargetOutput *output = m_attachmentManager->lookupResource(nodeId);
+ if (!output)
+ return false;
+
+ Attachment **attachmentData = reinterpret_cast<Attachment **>(handle);
+ *attachmentData = output->attachment();
+ return true;
+ }
+ GLTexture *glTex = m_glTextureManager->lookupResource(tex->peerId());
+ if (!glTex)
+ return false;
+
+ if (glTex->isDirty())
+ return false;
+
+ QOpenGLTexture** glTextureHandle = reinterpret_cast<QOpenGLTexture **>(handle);
+ *glTextureHandle = glTex->getOrCreateGLTexture();
+ *lock = glTex->textureLock();
+ return true;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/backend/resourceaccessor_p.h b/src/render/backend/resourceaccessor_p.h
new file mode 100644
index 000000000..653a8adda
--- /dev/null
+++ b/src/render/backend/resourceaccessor_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies).
+** 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_RENDER_RESOURCEACCESSOR_P_H
+#define QT3DRENDER_RENDER_RESOURCEACCESSOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qnodeid.h>
+
+#include <private/qt3drender_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMutex;
+
+namespace Qt3DRender
+{
+namespace Render {
+
+class TextureManager;
+class AttachmentManager;
+class GLTextureManager;
+class NodeManagers;
+
+class RenderBackendResourceAccessor
+{
+public:
+ virtual bool accessResource(Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock) = 0;
+};
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT ResourceAccessor : public RenderBackendResourceAccessor
+{
+public:
+ ResourceAccessor(NodeManagers *mgr);
+ bool accessResource(Qt3DCore::QNodeId nodeId, void **handle, QMutex **lock) Q_DECL_FINAL;
+private:
+ GLTextureManager *m_glTextureManager;
+ TextureManager *m_textureManager;
+ AttachmentManager *m_attachmentManager;
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RESOURCEACCESSOR_P_H
diff --git a/src/render/backend/triangleboundingvolume.cpp b/src/render/backend/triangleboundingvolume.cpp
index 80a23572c..ca2d26897 100644
--- a/src/render/backend/triangleboundingvolume.cpp
+++ b/src/render/backend/triangleboundingvolume.cpp
@@ -112,15 +112,18 @@ Qt3DCore::QNodeId TriangleBoundingVolume::id() const
return m_id;
}
-bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, QVector3D *q) const
+bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const
{
float t = 0.0f;
- QVector3D uvw;
- const bool intersected = intersectsSegmentTriangle(ray, m_c, m_b, m_a, uvw, t);
-
- if (intersected && q != nullptr)
- *q = ray.point(t * ray.distance());
-
+ QVector3D uvwr;
+ const float intersected = intersectsSegmentTriangle(ray, m_c, m_b, m_a, uvwr, t);
+
+ if (intersected) {
+ if (q != nullptr)
+ *q = ray.point(t);
+ if (uvw != nullptr)
+ *uvw = uvwr;
+ }
return intersected;
}
diff --git a/src/render/backend/triangleboundingvolume_p.h b/src/render/backend/triangleboundingvolume_p.h
index 1163efc46..3192ad456 100644
--- a/src/render/backend/triangleboundingvolume_p.h
+++ b/src/render/backend/triangleboundingvolume_p.h
@@ -78,7 +78,7 @@ public:
const QVector3D &c);
Qt3DCore::QNodeId id() const Q_DECL_FINAL;
- bool intersects(const RayCasting::QRay3D &ray, QVector3D *q) const Q_DECL_FINAL;
+ bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const Q_DECL_FINAL;
Type type() const Q_DECL_FINAL;
QVector3D a() const;
diff --git a/src/render/backend/trianglesvisitor.cpp b/src/render/backend/trianglesvisitor.cpp
index 35cdecc29..5453661e0 100644
--- a/src/render/backend/trianglesvisitor.cpp
+++ b/src/render/backend/trianglesvisitor.cpp
@@ -71,24 +71,6 @@ bool isTriangleBased(Qt3DRender::QGeometryRenderer::PrimitiveType type) Q_DECL_N
}
}
-struct BufferInfo
-{
- BufferInfo()
- : type(QAttribute::VertexBaseType::Float)
- , dataSize(0)
- , count(0)
- , byteStride(0)
- , byteOffset(0)
- {}
-
- QByteArray data;
- QAttribute::VertexBaseType type;
- uint dataSize;
- uint count;
- uint byteStride;
- uint byteOffset;
-};
-
// TO DO: Add methods for triangle strip adjacency
// What about primitive restart ?
@@ -328,6 +310,17 @@ void traverseTriangleAdjacency(Vertex *vertices,
}
}
+template<typename Coordinate>
+QVector4D readCoordinate(const BufferInfo &info, Coordinate *coordinates, uint index)
+{
+ const uint stride = info.byteStride / sizeof(Coordinate);
+ QVector4D ret(0, 0, 0, 1.0f);
+ coordinates += stride * index;
+ for (uint e = 0; e < info.dataSize; ++e)
+ ret[e] = coordinates[e];
+ return ret;
+}
+
template <QAttribute::VertexBaseType> struct EnumToType;
template <> struct EnumToType<QAttribute::Byte> { typedef const char type; };
@@ -370,6 +363,31 @@ void processBuffer(const BufferInfo &info, Func &f)
}
}
+QVector4D readBuffer(const BufferInfo &info, uint index)
+{
+ switch (info.type) {
+ case QAttribute::Byte:
+ return readCoordinate(info, castToType<QAttribute::Byte>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedByte:
+ return readCoordinate(info, castToType<QAttribute::UnsignedByte>(info.data, info.byteOffset), index);
+ case QAttribute::Short:
+ return readCoordinate(info, castToType<QAttribute::Short>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedShort:
+ return readCoordinate(info, castToType<QAttribute::UnsignedShort>(info.data, info.byteOffset), index);
+ case QAttribute::Int:
+ return readCoordinate(info, castToType<QAttribute::Int>(info.data, info.byteOffset), index);
+ case QAttribute::UnsignedInt:
+ return readCoordinate(info, castToType<QAttribute::UnsignedInt>(info.data, info.byteOffset), index);
+ case QAttribute::Float:
+ return readCoordinate(info, castToType<QAttribute::Float>(info.data, info.byteOffset), index);
+ case QAttribute::Double:
+ return readCoordinate(info, castToType<QAttribute::Double>(info.data, info.byteOffset), index);
+ default:
+ break;
+ }
+ return QVector4D();
+}
+
template<typename Index>
struct IndexedVertexExecutor
{
@@ -530,6 +548,53 @@ void TrianglesVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::Q
}
}
+bool CoordinateReader::setGeometry(const GeometryRenderer *renderer, const QString &attributeName)
+{
+ if (renderer == nullptr || renderer->instanceCount() != 1
+ || !isTriangleBased(renderer->primitiveType())) {
+ return false;
+ }
+
+ Geometry *geom = m_manager->lookupResource<Geometry, GeometryManager>(renderer->geometryId());
+
+ if (!geom)
+ return false;
+
+ Attribute *attribute = nullptr;
+
+ const auto attrIds = geom->attributes();
+ for (const Qt3DCore::QNodeId attrId : attrIds) {
+ attribute = m_manager->lookupResource<Attribute, AttributeManager>(attrId);
+ if (attribute){
+ if (attribute->name() == attributeName
+ || (attributeName == QStringLiteral("default")
+ && attribute->name() == QAttribute::defaultTextureCoordinateAttributeName())) {
+ break;
+ }
+ }
+ attribute = nullptr;
+ }
+
+ if (!attribute)
+ return false;
+
+ m_attribute = attribute;
+ m_buffer = m_manager->lookupResource<Buffer, BufferManager>(attribute->bufferId());
+
+ m_bufferInfo.data = m_buffer->data();
+ m_bufferInfo.type = m_attribute->vertexBaseType();
+ m_bufferInfo.byteOffset = m_attribute->byteOffset();
+ m_bufferInfo.byteStride = m_attribute->byteStride();
+ m_bufferInfo.dataSize = m_attribute->vertexSize();
+ m_bufferInfo.count = m_attribute->count();
+ return true;
+}
+
+QVector4D CoordinateReader::getCoordinate(uint vertexIndex)
+{
+ return readBuffer(m_bufferInfo, vertexIndex);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/trianglesvisitor_p.h b/src/render/backend/trianglesvisitor_p.h
index 5f7cff9c0..a0fa89efb 100644
--- a/src/render/backend/trianglesvisitor_p.h
+++ b/src/render/backend/trianglesvisitor_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DRender/QAttribute>
QT_BEGIN_NAMESPACE
@@ -65,6 +66,26 @@ namespace Render {
class GeometryRenderer;
class NodeManagers;
+class Attribute;
+class Buffer;
+
+struct BufferInfo
+{
+ BufferInfo()
+ : type(QAttribute::VertexBaseType::Float)
+ , dataSize(0)
+ , count(0)
+ , byteStride(0)
+ , byteOffset(0)
+ {}
+
+ QByteArray data;
+ QAttribute::VertexBaseType type;
+ uint dataSize;
+ uint count;
+ uint byteStride;
+ uint byteOffset;
+};
class Q_AUTOTEST_EXPORT TrianglesVisitor
{
@@ -84,6 +105,27 @@ protected:
Qt3DCore::QNodeId m_nodeId;
};
+class Q_AUTOTEST_EXPORT CoordinateReader
+{
+public:
+ explicit CoordinateReader(NodeManagers *manager)
+ : m_manager(manager)
+ , m_attribute(nullptr)
+ , m_buffer(nullptr)
+ {
+ }
+
+ bool setGeometry(const GeometryRenderer *renderer, const QString &attributeName);
+
+ QVector4D getCoordinate(uint vertexIndex);
+
+protected:
+ NodeManagers *m_manager;
+ Attribute *m_attribute;
+ Buffer *m_buffer;
+ BufferInfo m_bufferInfo;
+};
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index d9b45b7a7..0eb180650 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -81,6 +81,8 @@
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qrendercapture.h>
#include <Qt3DRender/qmemorybarrier.h>
+#include <Qt3DRender/qeventforward.h>
+
#include <Qt3DRender/private/cameraselectornode_p.h>
#include <Qt3DRender/private/layerfilternode_p.h>
#include <Qt3DRender/private/filterkey_p.h>
@@ -127,6 +129,10 @@
#include <Qt3DRender/private/technique_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
+#include <Qt3DRender/private/eventforward_p.h>
+
+#include <private/qrenderpluginfactory_p.h>
+#include <private/qrenderplugin_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
@@ -162,8 +168,8 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type)
, m_renderType(type)
, m_offscreenHelper(nullptr)
{
- // Load the scene parsers
loadSceneParsers();
+ loadRenderPlugins();
}
/*! \internal */
@@ -242,11 +248,17 @@ void QRenderAspectPrivate::registerBackendTypes()
// Picking
q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
+ q->registerBackendType<QEventForward>(QSharedPointer<Render::NodeFunctor<Render::EventForward, Render::EventForwardManager> >::create(m_renderer));
+
+ // Plugins
+ for (Render::QRenderPlugin *plugin : m_renderPlugins)
+ plugin->registerBackendTypes(q, m_renderer);
}
/*! \internal */
void QRenderAspectPrivate::unregisterBackendTypes()
{
+ Q_Q(QRenderAspect);
unregisterBackendType<Qt3DCore::QEntity>();
unregisterBackendType<Qt3DCore::QTransform>();
@@ -299,6 +311,18 @@ void QRenderAspectPrivate::unregisterBackendTypes()
// Picking
unregisterBackendType<QObjectPicker>();
+ unregisterBackendType<QEventForward>();
+
+ // Plugins
+ for (Render::QRenderPlugin *plugin : m_renderPlugins)
+ plugin->unregisterBackendTypes(q);
+}
+
+void QRenderAspectPrivate::registerBackendType(const QMetaObject &obj,
+ const QBackendNodeMapperPtr &functor)
+{
+ Q_Q(QRenderAspect);
+ q->registerBackendType(obj, functor);
}
/*!
@@ -537,6 +561,16 @@ void QRenderAspectPrivate::loadSceneParsers()
}
}
+void QRenderAspectPrivate::loadRenderPlugins()
+{
+ const QStringList keys = Render::QRenderPluginFactory::keys();
+ for (const QString &key : keys) {
+ Render::QRenderPlugin *plugin = Render::QRenderPluginFactory::create(key, QStringList());
+ if (plugin != nullptr)
+ m_renderPlugins.append(plugin);
+ }
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderaspect.h b/src/render/frontend/qrenderaspect.h
index 72e8e4bdb..48ef5b164 100644
--- a/src/render/frontend/qrenderaspect.h
+++ b/src/render/frontend/qrenderaspect.h
@@ -56,6 +56,7 @@ class TestAspect;
namespace Render {
class Renderer;
+class QRenderPlugin;
}
class QRenderAspectPrivate;
@@ -92,6 +93,7 @@ private:
void onEngineStartup() Q_DECL_OVERRIDE;
friend class Render::Renderer;
+ friend class Render::QRenderPlugin;
#if defined(QT_BUILD_INTERNAL)
friend class QRenderAspectTester;
friend class TestAspect;
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 72183ef87..1fa0b26df 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -62,9 +62,11 @@ class QSurface;
namespace Qt3DRender {
class QSceneImporter;
+
namespace Render {
class AbstractRenderer;
class NodeManagers;
+class QRenderPlugin;
}
namespace Render {
@@ -82,9 +84,11 @@ public:
void registerBackendTypes();
void unregisterBackendTypes();
void loadSceneParsers();
+ void loadRenderPlugins();
void renderInitialize(QOpenGLContext *context);
void renderSynchronous();
void renderShutdown();
+ void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor);
QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs();
Render::NodeManagers *m_nodeManagers;
@@ -92,6 +96,7 @@ public:
bool m_initialized;
QList<QSceneImporter *> m_sceneImporter;
+ QVector<Render::QRenderPlugin *> m_renderPlugins;
QRenderAspect::RenderType m_renderType;
Render::OffscreenSurfaceHelper *m_offscreenHelper;
};
diff --git a/src/render/frontend/qrenderplugin_p.h b/src/render/frontend/qrenderplugin_p.h
new file mode 100644
index 000000000..5144448c1
--- /dev/null
+++ b/src/render/frontend/qrenderplugin_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt3drender_global_p.h>
+
+#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DRender/qrenderaspect.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class AbstractRenderer;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPlugin
+{
+public:
+ virtual bool registerBackendTypes(QRenderAspect *aspect, AbstractRenderer *renderer) = 0;
+ virtual bool unregisterBackendTypes(QRenderAspect *aspect) = 0;
+
+protected:
+ void registerBackendType(QRenderAspect *aspect, const QMetaObject &obj, const Qt3DCore::QBackendNodeMapperPtr &functor)
+ {
+ aspect->registerBackendType(obj, functor);
+ }
+ void unregisterBackendType(QRenderAspect *aspect, const QMetaObject &obj)
+ {
+ aspect->unregisterBackendType(obj);
+ }
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QRENDERPLUGIN_P_H
diff --git a/src/render/frontend/qrenderpluginfactory.cpp b/src/render/frontend/qrenderpluginfactory.cpp
new file mode 100644
index 000000000..51fa068c6
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactory.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrenderpluginfactory_p.h"
+#include "qrenderpluginfactoryif_p.h"
+#include "qrenderplugin_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+
+#include <private/qfactoryloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QRenderPluginFactoryInterface_iid, QLatin1String("/renderplugins"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, (QRenderPluginFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
+#endif
+
+QStringList QRenderPluginFactory::keys(const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ QStringList list;
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ list = directLoader()->keyMap().values();
+ if (!list.isEmpty()) {
+ const QString postFix = QLatin1String(" (from ")
+ + QDir::toNativeSeparators(pluginPath)
+ + QLatin1Char(')');
+ const QStringList::iterator end = list.end();
+ for (QStringList::iterator it = list.begin(); it != end; ++it)
+ (*it).append(postFix);
+ }
+ }
+ list.append(loader()->keyMap().values());
+ return list;
+#else
+ return QStringList();
+#endif
+}
+
+QRenderPlugin *QRenderPluginFactory::create(const QString &name, const QStringList &args,
+ const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ if (QRenderPlugin *ret
+ = qLoadPlugin<QRenderPlugin, QRenderPluginFactoryIf>(directLoader(), name, args)) {
+ return ret;
+ }
+ }
+ if (QRenderPlugin *ret = qLoadPlugin<QRenderPlugin, QRenderPluginFactoryIf>(loader(), name, args))
+ return ret;
+#endif
+ return nullptr;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderpluginfactory_p.h b/src/render/frontend/qrenderpluginfactory_p.h
new file mode 100644
index 000000000..9cffd500a
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactory_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qt3drender_global_p.h>
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class QRenderPlugin;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPluginFactory
+{
+public:
+ static QStringList keys(const QString &pluginPath = QString());
+ static QRenderPlugin *create(const QString &name, const QStringList &args,
+ const QString &pluginPath = QString());
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QRENDERPLUGINFACTORY_P_H
diff --git a/src/render/frontend/qrenderpluginfactoryif.cpp b/src/render/frontend/qrenderpluginfactoryif.cpp
new file mode 100644
index 000000000..af567084c
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactoryif.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrenderpluginfactoryif_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+QRenderPluginFactoryIf::QRenderPluginFactoryIf(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+QRenderPluginFactoryIf::~QRenderPluginFactoryIf()
+{
+
+}
+
+QRenderPlugin *QRenderPluginFactoryIf::create(const QString &key, const QStringList &paramList)
+{
+ Q_UNUSED(key)
+ Q_UNUSED(paramList)
+ return nullptr;
+}
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/frontend/qrenderpluginfactoryif_p.h b/src/render/frontend/qrenderpluginfactoryif_p.h
new file mode 100644
index 000000000..d5f0008d2
--- /dev/null
+++ b/src/render/frontend/qrenderpluginfactoryif_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_QRENDERPLUGINFACTORYIF_P_H
+#define QT3DRENDER_RENDER_QRENDERPLUGINFACTORYIF_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+#include <private/qt3drender_global_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+#define QRenderPluginFactoryInterface_iid "org.qt-project.Qt3DRender.QRenderPluginFactoryInterface 5.9"
+
+class QRenderPlugin;
+
+class QT3DRENDERSHARED_PRIVATE_EXPORT QRenderPluginFactoryIf : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QRenderPluginFactoryIf(QObject *parent = nullptr);
+ ~QRenderPluginFactoryIf();
+
+ virtual QRenderPlugin *create(const QString &key, const QStringList &paramList);
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QRENDERPLUGINFACTORYIF_P_H
diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri
index 0e78f9cff..7a27ba095 100644
--- a/src/render/frontend/render-frontend.pri
+++ b/src/render/frontend/render-frontend.pri
@@ -26,7 +26,10 @@ HEADERS += \
$$PWD/qpickingsettings.h \
$$PWD/qpickingsettings_p.h \
$$PWD/qcomputecommand_p.h \
- $$PWD/qcomputecommand.h
+ $$PWD/qcomputecommand.h \
+ $$PWD/qrenderplugin_p.h \
+ $$PWD/qrenderpluginfactory_p.h \
+ $$PWD/qrenderpluginfactoryif_p.h
SOURCES += \
$$PWD/qabstractfunctor.cpp \
@@ -43,5 +46,7 @@ SOURCES += \
$$PWD/qrendersettings.cpp \
$$PWD/qpickingsettings.cpp \
$$PWD/qrendertargetoutput.cpp \
- $$PWD/qcomputecommand.cpp
+ $$PWD/qcomputecommand.cpp \
+ $$PWD/qrenderpluginfactory.cpp \
+ $$PWD/qrenderpluginfactoryif.cpp
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 80926efb9..2c22e0da4 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -223,8 +223,9 @@ Qt3DCore::QNodeId Sphere::id() const
return m_id;
}
-bool Sphere::intersects(const RayCasting::QRay3D &ray, QVector3D *q) const
+bool Sphere::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const
{
+ Q_UNUSED(uvw);
return intersectRaySphere(ray, *this, q);
}
diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h
index 1defbf059..1587aecab 100644
--- a/src/render/frontend/sphere_p.h
+++ b/src/render/frontend/sphere_p.h
@@ -106,7 +106,7 @@ public:
}
Qt3DCore::QNodeId id() const Q_DECL_FINAL;
- bool intersects(const RayCasting::QRay3D &ray, QVector3D *q) const Q_DECL_FINAL;
+ bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw = nullptr) const Q_DECL_FINAL;
Type type() const Q_DECL_FINAL;
static Sphere fromPoints(const QVector<QVector3D> &points);
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index 6b8b93647..7285bcfb7 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -59,6 +59,8 @@ namespace Render {
namespace {
+typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList;
+
void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers)
{
switch (event.button()) {
@@ -120,6 +122,11 @@ void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEven
m_pendingMouseEvents = pendingEvents;
}
+void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents)
+{
+ m_pendingKeyEvents = pendingEvents;
+}
+
void PickBoundingVolumeJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot)
{
m_frameGraphRoot = frameGraphRoot;
@@ -148,9 +155,10 @@ bool PickBoundingVolumeJob::runHelper()
// Move to clear the events so that we don't process them several times
// if run is called several times
const auto mouseEvents = std::move(m_pendingMouseEvents);
+ const auto keyEvents = std::move(m_pendingKeyEvents);
// If we have no events return early
- if (mouseEvents.empty())
+ if (mouseEvents.empty() && keyEvents.empty())
return false;
// Quickly look which picker settings we've got
@@ -219,6 +227,23 @@ bool PickBoundingVolumeJob::runHelper()
// that the tree structure has changed
PickingUtils::EntityGatherer entitiesGatherer(m_node);
+ // Forward keyboard events
+ if (keyEvents.size() > 0) {
+ for (Entity *e : entitiesGatherer.entities()) {
+ ObjectPicker *picker = e->renderComponent<ObjectPicker>();
+ if (picker != nullptr) {
+ if (picker->isEventForwardingEnabled()) {
+ EventForward *eventForward
+ = m_manager->eventForwardManager()->lookupResource(picker->eventForward());
+ if (eventForward->focus() && eventForward->forwardKeyboardEvents()) {
+ eventForward->forward(keyEvents);
+ break;
+ }
+ }
+ }
+ }
+ }
+
// Store the reducer function which varies depending on the picking settings set on the renderer
using ReducerFunction = PickingUtils::CollisionVisitor::HitList (*)(PickingUtils::CollisionVisitor::HitList &results, const PickingUtils::CollisionVisitor::HitList &intermediate);
@@ -244,7 +269,6 @@ bool PickBoundingVolumeJob::runHelper()
// For each triplet of Viewport / Camera and Area
for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) {
- typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList;
HitList sphereHits;
QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId);
if (trianglePickingRequested) {
@@ -262,7 +286,8 @@ bool PickBoundingVolumeJob::runHelper()
}
// Dispatch events based on hit results
- dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, trianglePickingRequested, allHitsRequested);
+ dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers,
+ trianglePickingRequested, allHitsRequested, ray);
}
}
@@ -296,7 +321,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
int eventButtons,
int eventModifiers,
bool trianglePickingRequested,
- bool allHitsRequested)
+ bool allHitsRequested,
+ const RayCasting::QRay3D &ray)
{
ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker);
// If we have hits
@@ -389,6 +415,49 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
default:
break;
}
+ if (objectPicker->isEventForwardingEnabled()) {
+ EventForward *eventForward
+ = m_manager->eventForwardManager()->lookupResource(objectPicker->eventForward());
+ QCollisionQueryResult::Hit triangleHit = hit;
+ bool valid = true;
+ if (eventForward->isEnabled() && eventForward->forwardMouseEvents()) {
+ if (!trianglePickingRequested) {
+ // Triangle picking is not enables so the triangle is not already in the
+ // query results. We need to redo the picking to get the triangle.
+ Qt3DRender::QRayCastingService rayCasting;
+ PickingUtils::TriangleCollisionGathererFunctor gathererFunctor;
+ const bool frontFaceRequested =
+ m_renderSettings->faceOrientationPickingMode() != QPickingSettings::BackFace;
+ const bool backFaceRequested =
+ m_renderSettings->faceOrientationPickingMode() != QPickingSettings::FrontFace;
+ gathererFunctor.m_frontFaceRequested = frontFaceRequested;
+ gathererFunctor.m_backFaceRequested = backFaceRequested;
+ gathererFunctor.m_manager = m_manager;
+ gathererFunctor.m_ray = ray;
+
+ // The bounding method is inaccurate so the triangle picking doesn't
+ // necessarely produce any results
+ HitList hitlist = gathererFunctor.pick(&rayCasting, entity);
+ if (hitlist.size() > 0)
+ triangleHit = hitlist.at(0);
+ else
+ valid = false;
+ }
+ if (valid) {
+ CoordinateReader reader(m_manager);
+ if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(),
+ eventForward->coordinateAttribute())) {
+ QVector4D c0 = reader.getCoordinate(triangleHit.m_vertexIndex[0]);
+ QVector4D c1 = reader.getCoordinate(triangleHit.m_vertexIndex[1]);
+ QVector4D c2 = reader.getCoordinate(triangleHit.m_vertexIndex[2]);
+ QVector4D ci = c2 * triangleHit.m_uvw.x()
+ + c1 * triangleHit.m_uvw.y() + c0 * triangleHit.m_uvw.z();
+ ci.setW(1.0f);
+ eventForward->forward(event, ci);
+ }
+ }
+ }
+ }
}
// The ObjectPicker was hit -> it is still being hovered
diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h
index 9f52943d1..cd8b9a95d 100644
--- a/src/render/jobs/pickboundingvolumejob_p.h
+++ b/src/render/jobs/pickboundingvolumejob_p.h
@@ -59,6 +59,7 @@
#include <Qt3DRender/private/pickboundingvolumeutils_p.h>
#include <Qt3DRender/qpickevent.h>
#include <QMouseEvent>
+#include <QKeyEvent>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -82,6 +83,7 @@ public:
void setRoot(Entity *root);
void setMouseEvents(const QList<QMouseEvent> &pendingEvents);
+ void setKeyEvents(const QList<QKeyEvent> &pendingEvents);
void setFrameGraphRoot(FrameGraphNode *frameGraphRoot);
void setRenderSettings(RenderSettings *settings);
void setManagers(NodeManagers *manager);
@@ -102,8 +104,11 @@ protected:
void run() Q_DECL_FINAL;
void dispatchPickEvents(const QMouseEvent &event, const PickingUtils::CollisionVisitor::HitList &sphereHits,
QPickEvent::Buttons eventButton,
- int eventButtons, int eventModifiers,
- bool trianglePickingRequested, bool allHitsRequested);
+ int eventButtons,
+ int eventModifiers,
+ bool trianglePickingRequested,
+ bool allHitsRequested,
+ const RayCasting::QRay3D &ray);
private:
NodeManagers *m_manager;
@@ -115,6 +120,8 @@ private:
bool m_oneEnabledAtLeast;
bool m_oneHoverAtLeast;
+ QList<QKeyEvent> m_pendingKeyEvents;
+
void viewMatrixForCamera(Qt3DCore::QNodeId cameraId,
QMatrix4x4 &viewMatrix,
QMatrix4x4 &projectionMatrix) const;
diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp
index 1573aa112..8609906e9 100644
--- a/src/render/jobs/pickboundingvolumeutils.cpp
+++ b/src/render/jobs/pickboundingvolumeutils.cpp
@@ -175,6 +175,7 @@ bool CollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a,
queryResult.m_vertexIndex[0] = andx;
queryResult.m_vertexIndex[1] = bndx;
queryResult.m_vertexIndex[2] = cndx;
+ queryResult.m_uvw = uvw;
queryResult.m_intersection = m_ray.point(t * m_ray.distance());
queryResult.m_distance = m_ray.projectedDistance(queryResult.m_intersection);
hits.push_back(queryResult);
diff --git a/src/render/picking/eventforward.cpp b/src/render/picking/eventforward.cpp
new file mode 100644
index 000000000..0216542bd
--- /dev/null
+++ b/src/render/picking/eventforward.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DRender/qeventforward.h>
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <private/qeventforward_p.h>
+#include <private/eventforward_p.h>
+#include <private/posteventstofrontend_p.h>
+
+#include <QtGui/qevent.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+EventForward::EventForward()
+ : BackendNode(QBackendNode::ReadWrite)
+ , m_forwardMouseEvents(false)
+ , m_forwardKeyboardEvents(false)
+ , m_focus(false)
+{
+
+}
+
+EventForward::~EventForward()
+{
+
+}
+
+void EventForward::cleanup()
+{
+ setEnabled(false);
+ m_coordinateAttribute = "";
+ m_coordinateTransform.setToIdentity();
+ m_forwardMouseEvents = false;
+ m_forwardKeyboardEvents = false;
+ m_focus = false;
+}
+
+QString EventForward::coordinateAttribute() const
+{
+ return m_coordinateAttribute;
+}
+
+QMatrix4x4 EventForward::coordinateTransform() const
+{
+ return m_coordinateTransform;
+}
+
+bool EventForward::forwardMouseEvents() const
+{
+ return m_forwardMouseEvents;
+}
+
+bool EventForward::forwardKeyboardEvents() const
+{
+ return m_forwardKeyboardEvents;
+}
+
+bool EventForward::focus() const
+{
+ return m_focus;
+}
+
+void EventForward::setCoordinateTransform(const QMatrix4x4 &transform)
+{
+ m_coordinateTransform = transform;
+}
+
+void EventForward::setCoordinateAttribute(const QString &attribute)
+{
+ m_coordinateAttribute = attribute;
+}
+
+void EventForward::setForwardMouseEvents(bool enabled)
+{
+ m_forwardMouseEvents = enabled;
+}
+
+void EventForward::setForwardKeyboardEvents(bool enabled)
+{
+ m_forwardKeyboardEvents = enabled;
+}
+
+void EventForward::setFocus(bool focus)
+{
+ m_focus = focus;
+}
+
+void EventForward::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+{
+ const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEventForwardData>>(change);
+ const auto &data = typedChange->data;
+ setCoordinateAttribute(data.coordinateAttribute);
+ setCoordinateTransform(data.coordinateTransform);
+ setForwardMouseEvents(data.forwardMouseEvents);
+ setForwardKeyboardEvents(data.forwardKeyboardEvents);
+ setFocus(data.focus);
+}
+
+void EventForward::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+{
+ if (e->type() == Qt3DCore::PropertyUpdated) {
+ const Qt3DCore::QPropertyUpdatedChangePtr propertyChange
+ = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+
+ if (propertyChange->propertyName() == QByteArrayLiteral("coordinateTransform"))
+ setCoordinateTransform(propertyChange->value().value<QMatrix4x4>());
+ else if (propertyChange->propertyName() == QByteArrayLiteral("coordinateAttribute"))
+ setCoordinateAttribute(propertyChange->value().toString());
+ else if (propertyChange->propertyName() == QByteArrayLiteral("forwardMouseEvents"))
+ setForwardMouseEvents(propertyChange->value().toBool());
+ else if (propertyChange->propertyName() == QByteArrayLiteral("forwardKeyboardEvents"))
+ setForwardKeyboardEvents(propertyChange->value().toBool());
+ else if (propertyChange->propertyName() == QByteArrayLiteral("focus"))
+ setFocus(propertyChange->value().toBool());
+ }
+
+ BackendNode::sceneChangeEvent(e);
+}
+
+void EventForward::forward(const QMouseEvent &event, const QVector4D &coordinate)
+{
+ const QVector4D transformedCoordinate = m_coordinateTransform * coordinate;
+ const QPointF local = QPointF(transformedCoordinate.x(), transformedCoordinate.y());
+ QMouseEvent *mouseEvent = new QMouseEvent(event.type(), local, local, local, event.button(),
+ event.buttons(), event.modifiers(),
+ Qt::MouseEventSynthesizedByApplication);
+
+ PostEventsToFrontendPtr events = PostEventsToFrontendPtr::create(mouseEvent);
+
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("events");
+ e->setValue(QVariant::fromValue(events));
+ notifyObservers(e);
+}
+
+void EventForward::forward(const QList<QKeyEvent> &keyEvents)
+{
+ QVector<QEvent *> eventsToSend;
+ for (const QKeyEvent &e : keyEvents) {
+ QKeyEvent *keyEvent = new QKeyEvent(e.type(), e.key(), e.modifiers(), e.nativeScanCode(),
+ e.nativeVirtualKey(), e.nativeModifiers());
+ eventsToSend.append(keyEvent);
+ }
+ PostEventsToFrontendPtr events = PostEventsToFrontendPtr::create(eventsToSend);
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
+ e->setPropertyName("events");
+ e->setValue(QVariant::fromValue(events));
+ notifyObservers(e);
+}
+
+} // Render
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/picking/eventforward_p.h b/src/render/picking/eventforward_p.h
new file mode 100644
index 000000000..663298e40
--- /dev/null
+++ b/src/render/picking/eventforward_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_EVENTFORWARD_P_H
+#define QT3DRENDER_RENDER_EVENTFORWARD_P_H
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/backendnode_p.h>
+
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT EventForward : public BackendNode
+{
+public:
+ EventForward();
+ ~EventForward();
+
+ void cleanup();
+
+ QString coordinateAttribute() const;
+ QMatrix4x4 coordinateTransform() const;
+ bool forwardMouseEvents() const;
+ bool forwardKeyboardEvents() const;
+ bool focus() const;
+
+ void setTarget(QObject *target);
+ void setCoordinateTransform(const QMatrix4x4 &transform);
+ void setCoordinateAttribute(const QString &attribute);
+ void setForwardMouseEvents(bool enabled);
+ void setForwardKeyboardEvents(bool enabled);
+ void setFocus(bool focus);
+
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL;
+
+ void forward(const QMouseEvent &event, const QVector4D &coordinate);
+ void forward(const QList<QKeyEvent> &keyEvents);
+
+private:
+ void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+
+ QString m_coordinateAttribute;
+ QMatrix4x4 m_coordinateTransform;
+ bool m_forwardMouseEvents;
+ bool m_forwardKeyboardEvents;
+ bool m_focus;
+};
+
+} // Render
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_EVENTFORWARD_P_H
diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp
index b85bdc723..6d84ec2a0 100644
--- a/src/render/picking/objectpicker.cpp
+++ b/src/render/picking/objectpicker.cpp
@@ -70,6 +70,7 @@ void ObjectPicker::cleanup()
m_isPressed = false;
m_hoverEnabled = false;
m_dragEnabled = false;
+ m_eventForward = Qt3DCore::QNodeId();
notifyJob();
}
@@ -79,6 +80,7 @@ void ObjectPicker::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
const auto &data = typedChange->data;
m_hoverEnabled = data.hoverEnabled;
m_dragEnabled = data.dragEnabled;
+ m_eventForward = data.eventForward;
notifyJob();
}
@@ -92,17 +94,13 @@ void ObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
{
if (e->type() == Qt3DCore::PropertyUpdated) {
const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- bool notifyPickJob = false;
if (propertyChange->propertyName() == QByteArrayLiteral("hoverEnabled")) {
m_hoverEnabled = propertyChange->value().toBool();
- notifyPickJob = true;
} else if (propertyChange->propertyName() == QByteArrayLiteral("dragEnabled")) {
m_dragEnabled = propertyChange->value().toBool();
- notifyPickJob = true;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
- notifyPickJob = true;
- // actual value change handled in BackendNode::sceneChangeEvent
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("eventForward")) {
+ m_eventForward = propertyChange->value().value<Qt3DCore::QNodeId>();
}
markDirty(AbstractRenderer::AllDirty);
@@ -127,6 +125,16 @@ bool ObjectPicker::isDragEnabled() const
return m_dragEnabled;
}
+bool ObjectPicker::isEventForwardingEnabled() const
+{
+ return Qt3DCore::QNodeId() != m_eventForward;
+}
+
+Qt3DCore::QNodeId ObjectPicker::eventForward() const
+{
+ return m_eventForward;
+}
+
void ObjectPicker::onClicked(QPickEventPtr event)
{
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h
index 2c2cc361e..68231073d 100644
--- a/src/render/picking/objectpicker_p.h
+++ b/src/render/picking/objectpicker_p.h
@@ -73,6 +73,8 @@ public:
bool isPressed() const;
bool isHoverEnabled() const;
bool isDragEnabled() const;
+ bool isEventForwardingEnabled() const;
+ Qt3DCore::QNodeId eventForward() const;
void onClicked(QPickEventPtr event);
void onMoved(QPickEventPtr event);
@@ -88,6 +90,7 @@ private:
bool m_isPressed;
bool m_hoverEnabled;
bool m_dragEnabled;
+ Qt3DCore::QNodeId m_eventForward;
};
} // Render
diff --git a/src/render/picking/pickeventfilter.cpp b/src/render/picking/pickeventfilter.cpp
index a1ae52068..19d3b6b6e 100644
--- a/src/render/picking/pickeventfilter.cpp
+++ b/src/render/picking/pickeventfilter.cpp
@@ -61,11 +61,19 @@ PickEventFilter::~PickEventFilter()
Called from a worker thread in the thread pool so be sure to
mutex protect the data.
*/
-QList<QMouseEvent> PickEventFilter::pendingEvents()
+QList<QMouseEvent> PickEventFilter::pendingMouseEvents()
{
QMutexLocker locker(&m_mutex);
- QList<QMouseEvent> pendingEvents(m_pendingEvents);
- m_pendingEvents.clear();
+ QList<QMouseEvent> pendingEvents(m_pendingMouseEvents);
+ m_pendingMouseEvents.clear();
+ return pendingEvents;
+}
+
+QList<QKeyEvent> PickEventFilter::pendingKeyEvents()
+{
+ QMutexLocker locker(&m_mutex);
+ QList<QKeyEvent> pendingEvents(m_pendingKeyEvents);
+ m_pendingKeyEvents.clear();
return pendingEvents;
}
@@ -82,7 +90,12 @@ bool PickEventFilter::eventFilter(QObject *obj, QEvent *e)
case QEvent::MouseMove:
case QEvent::HoverMove: {
QMutexLocker locker(&m_mutex);
- m_pendingEvents.push_back(QMouseEvent(*static_cast<QMouseEvent *>(e)));
+ m_pendingMouseEvents.push_back(QMouseEvent(*static_cast<QMouseEvent *>(e)));
+ } break;
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: {
+ QMutexLocker locker(&m_mutex);
+ m_pendingKeyEvents.push_back(QKeyEvent(*static_cast<QKeyEvent *>(e)));
}
default:
break;
diff --git a/src/render/picking/pickeventfilter_p.h b/src/render/picking/pickeventfilter_p.h
index df94a3085..fc4b00ddc 100644
--- a/src/render/picking/pickeventfilter_p.h
+++ b/src/render/picking/pickeventfilter_p.h
@@ -53,6 +53,7 @@
#include <QObject>
#include <QMouseEvent>
+#include <QKeyEvent>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -68,13 +69,15 @@ public:
explicit PickEventFilter(QObject *parent = nullptr);
~PickEventFilter();
- QList<QMouseEvent> pendingEvents();
+ QList<QMouseEvent> pendingMouseEvents();
+ QList<QKeyEvent> pendingKeyEvents();
protected:
bool eventFilter(QObject *obj, QEvent *e) Q_DECL_FINAL;
private:
- QList<QMouseEvent> m_pendingEvents;
+ QList<QMouseEvent> m_pendingMouseEvents;
+ QList<QKeyEvent> m_pendingKeyEvents;
QMutex m_mutex;
};
diff --git a/src/render/picking/picking.pri b/src/render/picking/picking.pri
index c4c188a82..c2eb8f50b 100644
--- a/src/render/picking/picking.pri
+++ b/src/render/picking/picking.pri
@@ -7,11 +7,18 @@ HEADERS += \
$$PWD/qpicktriangleevent.h \
$$PWD/objectpicker_p.h \
$$PWD/pickeventfilter_p.h \
- $$PWD/qobjectpicker_p.h
+ $$PWD/qobjectpicker_p.h \
+ $$PWD/qeventforward.h \
+ $$PWD/qeventforward_p.h \
+ $$PWD/eventforward_p.h \
+ $$PWD/posteventstofrontend_p.h
SOURCES += \
$$PWD/qobjectpicker.cpp \
$$PWD/qpickevent.cpp \
$$PWD/qpicktriangleevent.cpp \
$$PWD/objectpicker.cpp \
- $$PWD/pickeventfilter.cpp
+ $$PWD/pickeventfilter.cpp \
+ $$PWD/qeventforward.cpp \
+ $$PWD/eventforward.cpp \
+ $$PWD/posteventstofrontend.cpp
diff --git a/src/render/picking/posteventstofrontend.cpp b/src/render/picking/posteventstofrontend.cpp
new file mode 100644
index 000000000..51f986902
--- /dev/null
+++ b/src/render/picking/posteventstofrontend.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "posteventstofrontend_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+PostEventsToFrontend::PostEventsToFrontend()
+ : QObject()
+{
+
+}
+
+PostEventsToFrontend::PostEventsToFrontend(QEvent *event)
+ : QObject()
+{
+ m_events.append(event);
+}
+
+PostEventsToFrontend::PostEventsToFrontend(const QVector<QEvent *> &events)
+ : QObject()
+{
+ m_events = events;
+}
+
+PostEventsToFrontend::~PostEventsToFrontend()
+{
+ for (QEvent *e : m_events)
+ delete e;
+}
+
+QVector<QEvent *> &PostEventsToFrontend::events()
+{
+ return m_events;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/render/picking/posteventstofrontend_p.h b/src/render/picking/posteventstofrontend_p.h
new file mode 100644
index 000000000..5dd29b047
--- /dev/null
+++ b/src/render/picking/posteventstofrontend_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_POSTEVENTSTOFRONTEND_P_H
+#define QT3DRENDER_POSTEVENTSTOFRONTEND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qevent.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Q_AUTOTEST_EXPORT PostEventsToFrontend : public QObject
+{
+ Q_OBJECT
+public:
+ PostEventsToFrontend();
+ PostEventsToFrontend(QEvent *event);
+ PostEventsToFrontend(const QVector<QEvent *> &events);
+ ~PostEventsToFrontend();
+
+ QVector<QEvent *> &events();
+private:
+ QVector<QEvent *> m_events;
+};
+
+typedef QSharedPointer<PostEventsToFrontend> PostEventsToFrontendPtr;
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::PostEventsToFrontend*)
+
+#endif // QT3DRENDER_POSTEVENTSTOFRONTEND_P_H
diff --git a/src/render/picking/qeventforward.cpp b/src/render/picking/qeventforward.cpp
new file mode 100644
index 000000000..08546fabd
--- /dev/null
+++ b/src/render/picking/qeventforward.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventforward.h"
+#include "qeventforward_p.h"
+#include "posteventstofrontend_p.h"
+
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DRender::QEventForward
+ \inmodule Qt3DRender
+
+ \brief The QEventForward class instantiates a node that can
+ be used to forward events from the scene.
+
+ An QEventForward class can be used to forward pick events and keyboard events
+ from entities having a QObjectPicker. When the QObjectPicker handles pick event,
+ it hands it to the QEventForward, which converts it to QMouseEvent. The event
+ mouse coordinates are calculated by interpolating the given coordinate attribute
+ on the position the pick ray intersected the triangle, and then multiplying the
+ interpolated coordinate with the given transformation matrix. The event is then
+ sent and to the target object.
+
+ \since 5.9
+*/
+
+/*!
+ \qmltype EventForward
+ \instantiates Qt3DRender::QEventForward
+ \inherits Node
+ \inqmlmodule Qt3D.Render
+ \brief The EventForward type instantiates a node that can
+ be used to forward events from the scene.
+
+ An EventForward type can be used to forward pick events and keyboard events
+ from entities having a ObjectPicker. When the ObjectPicker handles pick event,
+ it hands it to the EventForward, which converts it to MouseEvent. The event
+ mouse coordinates are calculated by interpolating the given coordinate attribute
+ on the position the pick ray intersected the triangle, and then multiplying the
+ interpolated coordinate with the given transformation matrix. The event is then
+ sent and to the target object.
+
+ */
+
+/*!
+ \qmlproperty Object Qt3D.Render::EventForward::target
+ Holds the object the events are sent to.
+*/
+/*!
+ \qmlproperty bool Qt3D.Render::EventForward::forwardMouseEvents
+ Holds whether mouse event forwarding is enabled.
+*/
+/*!
+ \qmlproperty bool Qt3D.Render::EventForward::forwardKeyboardEvents
+ Holds whether keyboard event forwarding is enabled.
+*/
+/*!
+ \qmlproperty Matrix4x4 Qt3D.Render::EventForward::coordinateTransform
+ Holds the coordinate transformation.
+*/
+/*!
+ \qmlproperty string Qt3D.Render::EventForward::coordinateAttribute
+ Holds the name of the coordinate attribute the mouse coordinates are calculated from.
+*/
+/*!
+ \qmlproperty bool Qt3D.Render::EventForward::focus
+ Holds whether the QObjectPicker has focus.
+*/
+
+/*!
+ \property QEventForward::target
+ Holds the object the events are sent to.
+*/
+/*!
+ \property QEventForward::forwardMouseEvents
+ Holds whether mouse event forwarding is enabled.
+*/
+/*!
+ \property QEventForward::forwardKeyboardEvents
+ Holds whether keyboard event forwarding is enabled.
+*/
+/*!
+ \property QEventForward::coordinateTransform
+ Holds the coordinate transformation.
+*/
+/*!
+ \property QEventForward::coordinateAttribute
+ Holds the name of the coordinate attribute the mouse coordinates are calculated from.
+*/
+/*!
+ \property QEventForward::focus
+ Holds whether the ObjectPicker has focus.
+ */
+
+/*!
+
+ */
+QEventForward::QEventForward(Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QEventForwardPrivate(), parent)
+{
+}
+
+/*! \internal */
+QEventForward::~QEventForward()
+{
+}
+
+QObject *QEventForward::target() const
+{
+ Q_D(const QEventForward);
+ return d->m_target;
+}
+
+void QEventForward::targetDestroyed(QObject *target)
+{
+ Q_D(QEventForward);
+ Q_ASSERT(target == d->m_target);
+ setTarget(nullptr);
+}
+
+void QEventForward::setTarget(QObject *target)
+{
+ Q_D(QEventForward);
+ if (target != d->m_target) {
+ if (d->m_target != nullptr)
+ QObject::disconnect(d->m_destructionConnection);
+ d->m_target = target;
+ if (d->m_target) {
+ d->m_destructionConnection = QObject::connect(target, &QObject::destroyed,
+ this, &QEventForward::targetDestroyed);
+ }
+ emit targetChanged(target);
+ }
+}
+
+QMatrix4x4 QEventForward::coordinateTransform() const
+{
+ Q_D(const QEventForward);
+ return d->m_transform;
+}
+
+void QEventForward::setCoordinateTransform(const QMatrix4x4 &coordinateTransform)
+{
+ Q_D(QEventForward);
+ if (coordinateTransform != d->m_transform) {
+ d->m_transform = coordinateTransform;
+ emit coordinateTransformChanged(coordinateTransform);
+ }
+}
+
+QString QEventForward::coordinateAttribute() const
+{
+ Q_D(const QEventForward);
+ return d->m_attribute;
+}
+
+void QEventForward::setCoordinateAttribute(const QString &coordinateAttribute)
+{
+ Q_D(QEventForward);
+ if (coordinateAttribute != d->m_attribute) {
+ d->m_attribute = coordinateAttribute;
+ emit coordinateAttributeChanged(coordinateAttribute);
+ }
+}
+
+bool QEventForward::forwardMouseEvents() const
+{
+ Q_D(const QEventForward);
+ return d->m_forwardMouseEvents;
+}
+
+void QEventForward::setForwardMouseEvents(bool forward)
+{
+ Q_D(QEventForward);
+ if (forward != d->m_forwardMouseEvents) {
+ d->m_forwardMouseEvents = forward;
+ emit forwardMouseEventsChanged(forward);
+ }
+}
+
+bool QEventForward::forwardKeyboardEvents() const
+{
+ Q_D(const QEventForward);
+ return d->m_forwardKeyboardEvents;
+}
+
+void QEventForward::setForwardKeyboardEvents(bool forward)
+{
+ Q_D(QEventForward);
+ if (forward != d->m_forwardKeyboardEvents) {
+ d->m_forwardKeyboardEvents = forward;
+ emit forwardKeyboardEventsChanged(forward);
+ }
+}
+
+bool QEventForward::focus() const
+{
+ Q_D(const QEventForward);
+ return d->m_focus;
+}
+
+void QEventForward::setFocus(bool focus)
+{
+ Q_D(QEventForward);
+ if (d->m_focus != focus) {
+ d->m_focus = focus;
+ emit focusChanged(focus);
+ }
+}
+
+/*!
+ \internal
+ */
+Qt3DCore::QNodeCreatedChangeBasePtr QEventForward::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QEventForwardData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QEventForward);
+ data.target = d->m_target;
+ data.coordinateTransform = d->m_transform;
+ data.coordinateAttribute = d->m_attribute;
+ data.forwardMouseEvents = d->m_forwardMouseEvents;
+ data.forwardKeyboardEvents = d->m_forwardKeyboardEvents;
+ data.focus = d->m_focus;
+ return creationChange;
+}
+
+void QEventForward::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+{
+ Q_D(QEventForward);
+ Qt3DCore::QPropertyUpdatedChangePtr e
+ = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (e->type() == Qt3DCore::PropertyUpdated && d->m_target != nullptr) {
+ if (e->propertyName() == QByteArrayLiteral("events")) {
+ PostEventsToFrontendPtr postedEvents = e->value().value<PostEventsToFrontendPtr>();
+ for (QEvent *event : postedEvents->events())
+ QCoreApplication::sendEvent(d->m_target, event);
+ }
+ }
+}
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/picking/qeventforward.h b/src/render/picking/qeventforward.h
new file mode 100644
index 000000000..ee8100318
--- /dev/null
+++ b/src/render/picking/qeventforward.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QEVENTFORWARD_H
+#define QT3DRENDER_QEVENTFORWARD_H
+
+#include <Qt3DRender/qt3drender_global.h>
+
+#include <Qt3DCore/qnode.h>
+
+#include <QtGui/qmatrix4x4.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QEventForwardPrivate;
+
+class QT3DRENDERSHARED_EXPORT QEventForward : public Qt3DCore::QNode
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(bool forwardMouseEvents READ forwardMouseEvents WRITE setForwardMouseEvents NOTIFY forwardMouseEventsChanged)
+ Q_PROPERTY(bool forwardKeyboardEvents READ forwardKeyboardEvents WRITE setForwardKeyboardEvents NOTIFY forwardKeyboardEventsChanged)
+ Q_PROPERTY(QMatrix4x4 coordinateTransform READ coordinateTransform WRITE setCoordinateTransform NOTIFY coordinateTransformChanged)
+ Q_PROPERTY(QString coordinateAttribute READ coordinateAttribute WRITE setCoordinateAttribute NOTIFY coordinateAttributeChanged)
+ Q_PROPERTY(bool focus READ focus WRITE setFocus NOTIFY focusChanged)
+
+public:
+ explicit QEventForward(Qt3DCore::QNode *parent = nullptr);
+ ~QEventForward();
+
+ QObject *target() const;
+ QMatrix4x4 coordinateTransform() const;
+ QString coordinateAttribute() const;
+ bool forwardMouseEvents() const;
+ bool forwardKeyboardEvents() const;
+ bool focus() const;
+
+public Q_SLOTS:
+ void setTarget(QObject *target);
+ void setCoordinateTransform(const QMatrix4x4 &coordinateTransform);
+ void setCoordinateAttribute(const QString &coordinateAttribute);
+ void setForwardMouseEvents(bool forward);
+ void setForwardKeyboardEvents(bool forward);
+ void setFocus(bool focus);
+
+Q_SIGNALS:
+ void targetChanged(QObject *target);
+ void coordinateTransformChanged(const QMatrix4x4 &coordinateTransform);
+ void coordinateAttributeChanged(const QString &coordinateAttribute);
+ void forwardMouseEventsChanged(bool forward);
+ void forwardKeyboardEventsChanged(bool forward);
+ void focusChanged(bool focus);
+
+protected:
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
+
+private:
+ Q_DECLARE_PRIVATE(QEventForward)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+ void targetDestroyed(QObject *target);
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::QEventForward*)
+
+#endif // QT3DRENDER_QEVENTFORWARD_H
diff --git a/src/render/picking/qeventforward_p.h b/src/render/picking/qeventforward_p.h
new file mode 100644
index 000000000..c087bc8f5
--- /dev/null
+++ b/src/render/picking/qeventforward_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QEVENTFORWARD_P_H
+#define QT3DRENDER_QEVENTFORWARD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qnode_p.h>
+#include <Qt3DCore/qnodeid.h>
+#include <qmatrix4x4.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \internal
+*/
+class QEventForwardPrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ QEventForwardPrivate()
+ : QNodePrivate()
+ , m_target(nullptr)
+ , m_attribute("default")
+ , m_forwardMouseEvents(true)
+ , m_forwardKeyboardEvents(false)
+ , m_focus(false)
+ {
+
+ }
+
+ Q_DECLARE_PUBLIC(QEventForward)
+
+ QObject *m_target;
+ QMatrix4x4 m_transform;
+ QString m_attribute;
+ bool m_forwardMouseEvents;
+ bool m_forwardKeyboardEvents;
+ bool m_focus;
+ QMetaObject::Connection m_destructionConnection;
+};
+
+struct QEventForwardData
+{
+ QObject *target;
+ QMatrix4x4 coordinateTransform;
+ QString coordinateAttribute;
+ bool forwardMouseEvents;
+ bool forwardKeyboardEvents;
+ bool focus;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QEVENTFORWARD_P_H
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index 1842b7fee..9fa8b774c 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -43,6 +43,7 @@
#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qpickevent.h>
+#include <Qt3DRender/qeventforward.h>
QT_BEGIN_NAMESPACE
@@ -203,6 +204,37 @@ void QObjectPicker::setDragEnabled(bool dragEnabled)
}
/*!
+ \qmlproperty EventForward Qt3D.Render::ObjectPicker::eventForward
+ Holds the EventForward type.
+*/
+/*!
+ \property Qt3DRender::QObjectPicker::eventForward
+ Holds the EventForward type.
+ */
+QEventForward *QObjectPicker::eventForward() const
+{
+ Q_D(const QObjectPicker);
+ return d->m_eventForward;
+}
+
+void QObjectPicker::setEventForward(QEventForward *eventForward)
+{
+ Q_D(QObjectPicker);
+ if (d->m_eventForward != eventForward) {
+ if (d->m_eventForward)
+ d->unregisterDestructionHelper(d->m_eventForward);
+ d->m_eventForward = eventForward;
+ if (eventForward) {
+ if (eventForward->parent() == nullptr)
+ eventForward->setParent(this);
+ d->registerDestructionHelper(eventForward, &QObjectPicker::setEventForward,
+ d->m_eventForward);
+ }
+ emit eventForwardChanged(eventForward);
+ }
+}
+
+/*!
\qmlproperty bool Qt3D.Render::ObjectPicker::dragEnabled
*/
/*!
@@ -402,6 +434,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QObjectPicker::createNodeCreationChange() co
Q_D(const QObjectPicker);
data.hoverEnabled = d->m_hoverEnabled;
data.dragEnabled = d->m_dragEnabled;
+ data.eventForward = Qt3DCore::qIdForNode(d->m_eventForward);
return creationChange;
}
diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h
index 950fff2cc..b00178851 100644
--- a/src/render/picking/qobjectpicker.h
+++ b/src/render/picking/qobjectpicker.h
@@ -41,6 +41,7 @@
#define QT3DRENDER_QOBJECTPICKER_H
#include <Qt3DCore/qcomponent.h>
+#include <Qt3DRender/qeventforward.h>
#include <Qt3DRender/qt3drender_global.h>
QT_BEGIN_NAMESPACE
@@ -58,6 +59,7 @@ class QT3DRENDERSHARED_EXPORT QObjectPicker : public Qt3DCore::QComponent
Q_PROPERTY(bool dragEnabled READ isDragEnabled WRITE setDragEnabled NOTIFY dragEnabledChanged)
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
+ Q_PROPERTY(Qt3DRender::QEventForward *eventForward READ eventForward WRITE setEventForward NOTIFY eventForwardChanged)
public:
explicit QObjectPicker(QNode *parent = nullptr);
@@ -69,9 +71,12 @@ public:
bool containsMouse() const;
bool isPressed() const;
+ QEventForward *eventForward() const;
+
public Q_SLOTS:
void setHoverEnabled(bool hoverEnabled);
void setDragEnabled(bool dragEnabled);
+ void setEventForward(QEventForward *eventForward);
Q_SIGNALS:
void pressed(Qt3DRender::QPickEvent *pick);
@@ -84,6 +89,7 @@ Q_SIGNALS:
void dragEnabledChanged(bool dragEnabled);
void pressedChanged(bool pressed);
void containsMouseChanged(bool containsMouse);
+ void eventForwardChanged(QEventForward *eventForward);
protected:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE;
diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h
index 884e5673b..bddc213cc 100644
--- a/src/render/picking/qobjectpicker_p.h
+++ b/src/render/picking/qobjectpicker_p.h
@@ -68,6 +68,7 @@ public:
, m_pressed(false)
, m_containsMouse(false)
, m_acceptedLastPressedEvent(true)
+ , m_eventForward(nullptr)
{
m_shareable = false;
}
@@ -78,6 +79,7 @@ public:
bool m_pressed;
bool m_containsMouse;
bool m_acceptedLastPressedEvent;
+ QEventForward *m_eventForward;
enum EventType {
Pressed,
@@ -101,6 +103,7 @@ struct QObjectPickerData
{
bool hoverEnabled;
bool dragEnabled;
+ Qt3DCore::QNodeId eventForward;
};
} // namespace Qt3DRender
diff --git a/src/render/raycasting/qabstractcollisionqueryservice.cpp b/src/render/raycasting/qabstractcollisionqueryservice.cpp
index 132af00c9..993ad840e 100644
--- a/src/render/raycasting/qabstractcollisionqueryservice.cpp
+++ b/src/render/raycasting/qabstractcollisionqueryservice.cpp
@@ -61,9 +61,11 @@ void QAbstractCollisionQueryService::setResultHandle(QCollisionQueryResult &resu
result.d_func()->setHandle(handle);
}
-void QAbstractCollisionQueryService::addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance)
+void QAbstractCollisionQueryService::addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity,
+ const QVector3D& intersection, float distance,
+ const QVector3D& uvw)
{
- result.d_func()->addEntityHit(entity, intersection, distance);
+ result.d_func()->addEntityHit(entity, intersection, distance, uvw);
}
} // RayCasting
diff --git a/src/render/raycasting/qabstractcollisionqueryservice_p.h b/src/render/raycasting/qabstractcollisionqueryservice_p.h
index e2f9fb65a..806c33d5b 100644
--- a/src/render/raycasting/qabstractcollisionqueryservice_p.h
+++ b/src/render/raycasting/qabstractcollisionqueryservice_p.h
@@ -96,7 +96,8 @@ protected:
QAbstractCollisionQueryService(QAbstractCollisionQueryServicePrivate &dd);
void setResultHandle(QCollisionQueryResult &result, const QQueryHandle &handle);
- void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D &intersection, float distance);
+ void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D &intersection,
+ float distance, const QVector3D &uvw);
private:
Q_DECLARE_PRIVATE(QAbstractCollisionQueryService)
diff --git a/src/render/raycasting/qboundingvolume_p.h b/src/render/raycasting/qboundingvolume_p.h
index f29d08d52..8267c2b18 100644
--- a/src/render/raycasting/qboundingvolume_p.h
+++ b/src/render/raycasting/qboundingvolume_p.h
@@ -72,7 +72,8 @@ public:
};
virtual Qt3DCore::QNodeId id() const = 0;
- virtual bool intersects(const QRay3D &ray, QVector3D *q = nullptr) const = 0;
+ virtual bool intersects(const QRay3D &ray, QVector3D *q = nullptr,
+ QVector3D *uvw = nullptr) const = 0;
virtual Type type() const = 0;
};
diff --git a/src/render/raycasting/qcollisionqueryresult.cpp b/src/render/raycasting/qcollisionqueryresult.cpp
index 4d887d287..62975200c 100644
--- a/src/render/raycasting/qcollisionqueryresult.cpp
+++ b/src/render/raycasting/qcollisionqueryresult.cpp
@@ -56,9 +56,10 @@ QCollisionQueryResultPrivate::QCollisionQueryResultPrivate(const QCollisionQuery
{
}
-void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance)
+void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection,
+ float distance, const QVector3D& uvw)
{
- m_hits.append(QCollisionQueryResult::Hit(entity, intersection, distance));
+ m_hits.append(QCollisionQueryResult::Hit(entity, intersection, distance, uvw));
}
void QCollisionQueryResultPrivate::setHandle(const QQueryHandle &handle)
diff --git a/src/render/raycasting/qcollisionqueryresult_p.h b/src/render/raycasting/qcollisionqueryresult_p.h
index 18b45370a..e13dda74a 100644
--- a/src/render/raycasting/qcollisionqueryresult_p.h
+++ b/src/render/raycasting/qcollisionqueryresult_p.h
@@ -69,13 +69,27 @@ class QT3DRENDERSHARED_EXPORT QCollisionQueryResult
{
public:
struct Hit {
- Hit() : m_distance(-1.f), m_triangleIndex(0) { m_vertexIndex[0] = m_vertexIndex[1] = m_vertexIndex[2] = 0; }
- Hit(const Qt3DCore::QNodeId &entity, const QVector3D &intersection, float distance) : m_entityId(entity), m_intersection(intersection), m_distance(distance) { }
+ Hit()
+ : m_distance(-1.f)
+ , m_triangleIndex(0)
+ {
+ m_vertexIndex[0] = m_vertexIndex[1] = m_vertexIndex[2] = 0;
+ }
+
+ Hit(Qt3DCore::QNodeId entity, const QVector3D &intersection, float distance, const QVector3D &uvw)
+ : m_entityId(entity)
+ , m_intersection(intersection)
+ , m_distance(distance)
+ , m_uvw(uvw)
+ {
+ }
+
Qt3DCore::QNodeId m_entityId;
QVector3D m_intersection;
float m_distance;
uint m_triangleIndex;
uint m_vertexIndex[3];
+ QVector3D m_uvw;
};
QCollisionQueryResult();
@@ -123,7 +137,8 @@ public:
explicit QCollisionQueryResultPrivate(const QCollisionQueryResultPrivate &copy);
void setHandle(const QQueryHandle &handle);
- void addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance);
+ void addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance,
+ const QVector3D& uvw);
QQueryHandle m_handle;
QVector<QCollisionQueryResult::Hit> m_hits;
diff --git a/src/render/raycasting/qraycastingservice.cpp b/src/render/raycasting/qraycastingservice.cpp
index e92234836..e0c7b6199 100644
--- a/src/render/raycasting/qraycastingservice.cpp
+++ b/src/render/raycasting/qraycastingservice.cpp
@@ -68,6 +68,7 @@ struct Hit
float distance;
Qt3DCore::QNodeId id;
QVector3D intersection;
+ QVector3D uvw;
};
bool compareHitsDistance(const Hit &a, const Hit &b)
@@ -78,7 +79,7 @@ bool compareHitsDistance(const Hit &a, const Hit &b)
Hit volumeRayIntersection(const QBoundingVolume *volume, const QRay3D &ray)
{
Hit hit;
- if ((hit.intersects = volume->intersects(ray, &hit.intersection))) {
+ if ((hit.intersects = volume->intersects(ray, &hit.intersection, &hit.uvw))) {
hit.distance = ray.projectedDistance(hit.intersection);
hit.id = volume->id();
}
@@ -134,12 +135,12 @@ QCollisionQueryResult QRayCastingServicePrivate::collides(const QRay3D &ray, QBo
if (mode == QAbstractCollisionQueryService::FirstHit) {
Hit firstHit = QtConcurrent::blockingMappedReduced<Hit>(volumes, gathererFunctor, reduceToFirstHit);
if (firstHit.intersects)
- q->addEntityHit(result, firstHit.id, firstHit.intersection, firstHit.distance);
+ q->addEntityHit(result, firstHit.id, firstHit.intersection, firstHit.distance, firstHit.uvw);
} else {
QVector<Hit> hits = QtConcurrent::blockingMappedReduced<QVector<Hit> >(volumes, gathererFunctor, reduceToAllHits);
std::sort(hits.begin(), hits.end(), compareHitsDistance);
for (const Hit &hit : qAsConst(hits))
- q->addEntityHit(result, hit.id, hit.intersection, hit.distance);
+ q->addEntityHit(result, hit.id, hit.intersection, hit.distance, hit.uvw);
}
return result;
@@ -154,6 +155,7 @@ QCollisionQueryResult::Hit QRayCastingServicePrivate::collides(const QRay3D &ray
result.m_distance = hit.distance;
result.m_entityId = hit.id;
result.m_intersection = hit.intersection;
+ result.m_uvw = hit.uvw;
}
return result;
}
diff --git a/src/render/render.pro b/src/render/render.pro
index 1b90af82f..c31db94b7 100644
--- a/src/render/render.pro
+++ b/src/render/render.pro
@@ -41,6 +41,7 @@ SOURCES += \
MODULE_PLUGIN_TYPES = \
sceneparsers \
- geometryloaders
+ geometryloaders \
+ renderplugins
load(qt_module)
diff --git a/src/render/texture/gltexture_p.h b/src/render/texture/gltexture_p.h
index 424e77854..d9ce32a9f 100644
--- a/src/render/texture/gltexture_p.h
+++ b/src/render/texture/gltexture_p.h
@@ -148,6 +148,16 @@ public:
m_dirty |= TextureData;
}
+ bool isDirty()
+ {
+ QMutexLocker locker(&m_dirtyFlagMutex);
+ return m_dirty == 0 ? false : true;
+ }
+
+ QMutex *textureLock()
+ {
+ return &m_dirtyFlagMutex;
+ }
protected:
template<class APITexture, class APITextureImage>
diff --git a/src/src.pro b/src/src.pro
index afccd4ff7..0055274e0 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -71,6 +71,11 @@ src_plugins_geometryloaders.file = $$PWD/plugins/geometryloaders/geometryloaders
src_plugins_geometryloaders.target = sub-plugins-geometryloaders
src_plugins_geometryloaders.depends = src_render src_extras
+# Qt3D Render plugins
+src_plugins_render.file = $$PWD/plugins/renderplugins/renderplugins.pro
+src_plugins_render.target = sub-plugins-render
+src_plugins_render.depends = src_render src_extras src_quick3d_render
+
SUBDIRS += \
src_core \
src_render \
@@ -89,6 +94,5 @@ SUBDIRS += \
src_quick3d_imports_extras \
src_plugins_sceneparsers \
src_plugins_geometryloaders \
+ src_plugins_render \
doc
-
-