diff options
23 files changed, 710 insertions, 231 deletions
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp index 6e0d3bd02..f7248f180 100644 --- a/src/core/aspects/qabstractaspect.cpp +++ b/src/core/aspects/qabstractaspect.cpp @@ -247,6 +247,8 @@ void QAbstractAspectPrivate::syncDirtyFrontEndSubNodes(const QVector<NodeRelatio for (const auto &nodeChange: qAsConst(nodes)) { auto getBackend = [this](QNode *node) -> std::tuple<QBackendNode *, bool> { const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo; + if (!metaObj) + return {}; const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj); const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first; diff --git a/src/extras/shaders/es2/phong.inc.frag100 b/src/extras/shaders/es2/phong.inc.frag100 index 0c326d0b6..c68c8e41a 100644 --- a/src/extras/shaders/es2/phong.inc.frag100 +++ b/src/extras/shaders/es2/phong.inc.frag100 @@ -66,8 +66,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 if ( lights[0].type != TYPE_DIRECTIONAL ) { s = lights[0].position - vpos; if (lights[0].constantAttenuation != 0.0 - || light[0].linearAttenuation != 0.0 - || light[0].quadraticAttenuation != 0.0) { + || lights[0].linearAttenuation != 0.0 + || lights[0].quadraticAttenuation != 0.0) { FP float dist = length(s); att = 1.0 / (lights[0].constantAttenuation + lights[0].linearAttenuation * dist + lights[0].quadraticAttenuation * dist * dist); } @@ -99,8 +99,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 if ( lights[1].type != TYPE_DIRECTIONAL ) { s = lights[1].position - vpos; if (lights[1].constantAttenuation != 0.0 - || light[1].linearAttenuation != 0.0 - || light[1].quadraticAttenuation != 0.0) { + || lights[1].linearAttenuation != 0.0 + || lights[1].quadraticAttenuation != 0.0) { FP float dist = length(s); att = 1.0 / (lights[1].constantAttenuation + lights[1].linearAttenuation * dist + lights[1].quadraticAttenuation * dist * dist); } diff --git a/src/input/backend/mouseeventfilter.cpp b/src/input/backend/mouseeventfilter.cpp index 48b30725a..baa78ac25 100644 --- a/src/input/backend/mouseeventfilter.cpp +++ b/src/input/backend/mouseeventfilter.cpp @@ -77,6 +77,7 @@ bool MouseEventFilter::eventFilter(QObject *obj, QEvent *e) } case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: case QEvent::MouseMove: // Creates copy and store event to be processed later on in an InputAspect job m_inputHandler->appendMouseEvent(QMouseEvent(*static_cast<QMouseEvent *>(e))); diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp index 89d76a057..068fe1964 100644 --- a/src/input/frontend/qmousehandler.cpp +++ b/src/input/frontend/qmousehandler.cpp @@ -58,7 +58,7 @@ QMouseHandlerPrivate::QMouseHandlerPrivate() { m_shareable = false; m_pressAndHoldTimer->setSingleShot(true); - m_pressAndHoldTimer->setInterval(500); + m_pressAndHoldTimer->setInterval(800); QObject::connect(m_pressAndHoldTimer, &QTimer::timeout, [this] { emit q_func()->pressAndHold(m_lastPressedEvent.data()); }); @@ -77,15 +77,15 @@ void QMouseHandlerPrivate::mouseEvent(const QMouseEventPtr &event) { Q_Q(QMouseHandler); switch (event->type()) { - case QEvent::MouseButtonPress: { + case QEvent::MouseButtonPress: m_lastPressedEvent = event; m_pressAndHoldTimer->start(); emit q->pressed(event.data()); break; - } case QEvent::MouseButtonRelease: m_pressAndHoldTimer->stop(); emit q->released(event.data()); + emit q->clicked(event.data()); break; #if QT_CONFIG(gestures) case QEvent::Gesture: @@ -96,6 +96,7 @@ void QMouseHandlerPrivate::mouseEvent(const QMouseEventPtr &event) emit q->doubleClicked(event.data()); break; case QEvent::MouseMove: + m_pressAndHoldTimer->stop(); emit q->positionChanged(event.data()); break; default: diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro index e29f7b831..c4c1b7cc8 100644 --- a/src/quick3d/imports/scene3d/importsscene3d.pro +++ b/src/quick3d/imports/scene3d/importsscene3d.pro @@ -13,7 +13,6 @@ HEADERS += \ qtquickscene3dplugin.h \ scene3dlogging_p.h \ scene3ditem_p.h \ - scene3dcleaner_p.h \ scene3drenderer_p.h \ scene3dsgnode_p.h \ scene3dsgmaterialshader_p.h \ @@ -24,7 +23,6 @@ SOURCES += \ qtquickscene3dplugin.cpp \ scene3ditem.cpp \ scene3dlogging.cpp \ - scene3dcleaner.cpp \ scene3drenderer.cpp \ scene3dsgnode.cpp \ scene3dsgmaterialshader.cpp \ diff --git a/src/quick3d/imports/scene3d/scene3dcleaner.cpp b/src/quick3d/imports/scene3d/scene3dcleaner.cpp deleted file mode 100644 index ec371410d..000000000 --- a/src/quick3d/imports/scene3d/scene3dcleaner.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "scene3dcleaner_p.h" - -#include <Qt3DCore/qaspectengine.h> -#include <QtCore/qthread.h> - -#include <scene3dlogging_p.h> -#include <scene3drenderer_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -Scene3DCleaner::Scene3DCleaner(QObject *parent) - : QObject(parent) - , m_renderer(nullptr) -{ -} - -Scene3DCleaner::~Scene3DCleaner() -{ - qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread(); -} - -void Scene3DCleaner::cleanup() -{ - Q_ASSERT(m_renderer); - delete m_renderer->m_aspectEngine; // also deletes m_renderer->m_renderAspect - m_renderer->m_aspectEngine = nullptr; - m_renderer->m_renderAspect = nullptr; - m_renderer->deleteLater(); - deleteLater(); -} - -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/quick3d/imports/scene3d/scene3dcleaner_p.h b/src/quick3d/imports/scene3d/scene3dcleaner_p.h deleted file mode 100644 index a246cbde7..000000000 --- a/src/quick3d/imports/scene3d/scene3dcleaner_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_SCENE3DCLEANER_P_H -#define QT3DRENDER_SCENE3DCLEANER_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 <QtCore/QObject> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class Scene3DRenderer; - -class Scene3DCleaner : public QObject -{ - Q_OBJECT -public: - explicit Scene3DCleaner(QObject *parent = 0); - ~Scene3DCleaner(); - - void setRenderer(Scene3DRenderer *renderer) { m_renderer = renderer; } - -public Q_SLOTS: - void cleanup(); - -private: - Scene3DRenderer *m_renderer; -}; - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_SCENE3DCLEANER_H diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index f824d2c4e..6a1085a85 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -68,7 +68,6 @@ #include <Qt3DRender/private/qrendersurfaceselector_p.h> #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/rendersettings_p.h> -#include <scene3dcleaner_p.h> #include <scene3dlogging_p.h> #include <scene3drenderer_p.h> #include <scene3dsgnode_p.h> @@ -150,8 +149,8 @@ Scene3DItem::Scene3DItem(QQuickItem *parent) , m_viewHolderFG(nullptr) , m_aspectEngine(new Qt3DCore::QAspectEngine()) , m_renderAspect(nullptr) + , m_aspectToDelete(nullptr) , m_renderer(nullptr) - , m_rendererCleaner(new Scene3DCleaner()) , m_multisample(true) , m_dirty(true) , m_dirtyViews(false) @@ -179,6 +178,8 @@ Scene3DItem::~Scene3DItem() // When the window is closed, it first destroys all of its children. At // this point, Scene3DItem is destroyed but the Renderer, AspectEngine and // Scene3DSGNode still exist and will perform their cleanup on their own. + m_aspectEngine->deleteLater(); + m_renderer->deleteLater(); } /*! @@ -204,18 +205,11 @@ QStringList Scene3DItem::aspects() const */ Qt3DCore::QEntity *Scene3DItem::entity() const { - return m_entity; + return m_entity.data(); } -void Scene3DItem::setAspects(const QStringList &aspects) +void Scene3DItem::applyAspects() { - if (!m_aspects.isEmpty()) { - qCWarning(Scene3D) << "Aspects already set on the Scene3D, ignoring"; - return; - } - - m_aspects = aspects; - // Aspects are owned by the aspect engine for (const QString &aspect : qAsConst(m_aspects)) { if (aspect == QLatin1String("render")) // This one is hardwired anyway @@ -246,16 +240,27 @@ void Scene3DItem::setAspects(const QStringList &aspects) } m_aspectEngine->registerAspect(aspect); } +} + +void Scene3DItem::setAspects(const QStringList &aspects) +{ + if (!m_aspects.isEmpty()) { + qWarning() << "Aspects already set on the Scene3D, ignoring"; + return; + } + + m_aspects = aspects; + applyAspects(); emit aspectsChanged(); } void Scene3DItem::setEntity(Qt3DCore::QEntity *entity) { - if (entity == m_entity) + if (entity == m_entity.data()) return; - m_entity = entity; + m_entity.reset(entity); emit entityChanged(); } @@ -398,14 +403,21 @@ void Scene3DItem::removeView(Scene3DView *view) void Scene3DItem::applyRootEntityChange() { - if (m_aspectEngine->rootEntity() != m_entity) { - m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr(m_entity)); + if (m_aspectEngine->rootEntity() != m_entity.data()) { + m_aspectEngine->setRootEntity(m_entity); + + /* If we changed window, the old aspect engine must be deleted only after we have set + the root entity for the new one so that it doesn't delete the root node. */ + if (m_aspectToDelete) { + delete m_aspectToDelete; + m_aspectToDelete = nullptr; + } // Set the render surface if (!m_entity) return; - setWindowSurface(m_entity); + setWindowSurface(entity()); if (m_cameraAspectRatioMode == AutomaticAspectRatio) { // Set aspect ratio of first camera to match the window @@ -481,6 +493,8 @@ void Scene3DItem::onBeforeSync() // if the Scene3D item is not visible if (!isVisible() && dontRenderWhenHidden) return; + if (m_renderer->m_resetRequested) + return; Q_ASSERT(QThread::currentThread() == thread()); @@ -496,7 +510,7 @@ void Scene3DItem::onBeforeSync() // Make renderer aware of any Scene3DView we are dealing with if (m_dirtyViews) { // Scene3DViews checks - if (m_entity != m_viewHolderEntity) { + if (entity() != m_viewHolderEntity) { qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set"; } if (!usesFBO) { @@ -544,6 +558,20 @@ void Scene3DItem::requestUpdate() } } +void Scene3DItem::updateWindowSurface() +{ + if (!m_entity || !m_dummySurface) + return; + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = + Qt3DRender::QRenderSurfaceSelectorPrivate::find(entity()); + if (surfaceSelector) { + if (QWindow *rw = QQuickRenderControl::renderWindowFor(this->window())) { + m_dummySurface->deleteLater(); + createDummySurface(rw, surfaceSelector); + } + } +} + void Scene3DItem::setWindowSurface(QObject *rootObject) { Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject); @@ -554,20 +582,25 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) // We may not have a real, exposed QQuickWindow when the Quick rendering // is redirected via QQuickRenderControl (f.ex. QQuickWidget). if (QWindow *rw = QQuickRenderControl::renderWindowFor(this->window())) { - // rw is the top-level window that is backed by a native window. Do - // not use that though since we must not clash with e.g. the widget - // backingstore compositor in the gui thread. - m_dummySurface = new QOffscreenSurface; - m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living - m_dummySurface->setFormat(rw->format()); - m_dummySurface->setScreen(rw->screen()); - m_dummySurface->create(); - surfaceSelector->setSurface(m_dummySurface); + createDummySurface(rw, surfaceSelector); } else { surfaceSelector->setSurface(this->window()); } } } + +void Scene3DItem::createDummySurface(QWindow *rw, Qt3DRender::QRenderSurfaceSelector *surfaceSelector) +{ + // rw is the top-level window that is backed by a native window. Do + // not use that though since we must not clash with e.g. the widget + // backingstore compositor in the gui thread. + m_dummySurface = new QOffscreenSurface; + m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living + m_dummySurface->setFormat(rw->format()); + m_dummySurface->setScreen(rw->screen()); + m_dummySurface->create(); + surfaceSelector->setSurface(m_dummySurface); +} /*! \qmlmethod void Scene3D::setItemAreaAndDevicePixelRatio(size area, real devicePixelRatio) @@ -575,7 +608,8 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) */ void Scene3DItem::setItemAreaAndDevicePixelRatio(QSize area, qreal devicePixelRatio) { - Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(m_entity); + Qt3DRender::QRenderSurfaceSelector *surfaceSelector + = Qt3DRender::QRenderSurfaceSelectorPrivate::find(entity()); if (surfaceSelector) { surfaceSelector->setExternalRenderTargetSize(area); surfaceSelector->setSurfacePixelRatio(devicePixelRatio); @@ -665,6 +699,22 @@ void Scene3DItem::setMultisample(bool enable) QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) { + // m_resetRequested is set to true by Scene3DRenderer::shutdown() + if (m_renderer && m_renderer->m_resetRequested) { + qCWarning(Scene3D) << "Renderer for Scene3DItem has requested a reset due to the item " + "moving to another window"; + QObject::disconnect(m_windowConnection); + m_aspectEngine->unregisterAspect(m_renderAspect); // Deletes the renderAspect + m_renderAspect = nullptr; + m_aspectToDelete = m_aspectEngine; + m_aspectEngine = new Qt3DCore::QAspectEngine(); + m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual); + applyAspects(); + // Needs to belong in the same thread as the item which is the same as the original + // QAspectEngine + m_aspectEngine->moveToThread(thread()); + m_renderer->m_resetRequested = false; + } // If the render aspect wasn't created yet, do so now if (m_renderAspect == nullptr) { m_renderAspect = new QRenderAspect(QRenderAspect::Synchronous); @@ -675,16 +725,24 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode // Before Synchronizing is in the SG Thread, we want beforeSync to be triggered // in the context of the main thread - QObject::connect(window(), &QQuickWindow::afterAnimating, - this, &Scene3DItem::onBeforeSync, Qt::DirectConnection); + m_windowConnection = QObject::connect(window(), &QQuickWindow::afterAnimating, + this, &Scene3DItem::onBeforeSync, Qt::DirectConnection); auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect)); QObject::connect(renderAspectPriv->m_aspectManager->changeArbiter(), &Qt3DCore::QChangeArbiter::receivedChange, this, [this] { m_dirty = true; }, Qt::DirectConnection); } if (m_renderer == nullptr) { - m_renderer = new Scene3DRenderer(this, m_aspectEngine, m_renderAspect); - m_renderer->setCleanerHelper(m_rendererCleaner); + m_renderer = new Scene3DRenderer(); + m_renderer->init(this, m_aspectEngine, m_renderAspect); + } else if (m_renderer->renderAspect() != m_renderAspect) { + // If the renderer's renderAspect is not equal to the aspect used + // by the item, then it means that we have created a new one due to + // the fact that shutdown() was called on the renderer previously. + // This is a typical situation when the window the item is in has + // moved from one screen to another. + updateWindowSurface(); + m_renderer->init(this, m_aspectEngine, m_renderAspect); } const bool usesFBO = m_compositingMode == FBO; const bool hasScene3DViews = !m_views.empty(); diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h index e46bb20af..0beaf94c0 100644 --- a/src/quick3d/imports/scene3d/scene3ditem_p.h +++ b/src/quick3d/imports/scene3d/scene3ditem_p.h @@ -71,6 +71,7 @@ class Scene3DRenderer; class Scene3DCleaner; class Scene3DView; class QFrameGraphNode; +class QRenderSurfaceSelector; class Scene3DItem : public QQuickItem { @@ -138,16 +139,20 @@ private: void updateCameraAspectRatio(); void mousePressEvent(QMouseEvent *event) override; bool needsRender(); + void updateWindowSurface(); + void createDummySurface(QWindow *window, QRenderSurfaceSelector *surfaceSelector); + void applyAspects(); QStringList m_aspects; - Qt3DCore::QEntity *m_entity; + // Store as shared pointer so that aspect engine doesn't delete it. + QSharedPointer<Qt3DCore::QEntity> m_entity; Qt3DCore::QEntity *m_viewHolderEntity; Qt3DRender::QFrameGraphNode *m_viewHolderFG; Qt3DCore::QAspectEngine *m_aspectEngine; + Qt3DCore::QAspectEngine *m_aspectToDelete; QRenderAspect *m_renderAspect; Scene3DRenderer *m_renderer; - Scene3DCleaner *m_rendererCleaner; bool m_multisample; bool m_dirty; @@ -160,6 +165,7 @@ private: CompositingMode m_compositingMode; QOffscreenSurface *m_dummySurface; QVector<Scene3DView *> m_views; + QMetaObject::Connection m_windowConnection; }; } // Qt3DRender diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 312dc41cb..f28633c88 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -53,7 +53,6 @@ #include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/private/qservicelocator_p.h> -#include <scene3dcleaner_p.h> #include <scene3ditem_p.h> #include <scene3dlogging_p.h> #include <scene3dsgnode_p.h> @@ -144,16 +143,15 @@ private: signal of the window is not called. Therefore the cleanup method is invoked to properly destroy the aspect engine. */ -Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, QRenderAspect *renderAspect) +Scene3DRenderer::Scene3DRenderer() : QObject() - , m_item(item) - , m_aspectEngine(aspectEngine) - , m_renderAspect(renderAspect) + , m_item(nullptr) + , m_aspectEngine(nullptr) + , m_renderAspect(nullptr) , m_multisampledFBO(nullptr) , m_finalFBO(nullptr) , m_texture(nullptr) , m_node(nullptr) - , m_cleaner(nullptr) , m_window(nullptr) , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead , m_lastMultisample(false) @@ -165,6 +163,17 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_allowRendering(0) , m_compositingMode(Scene3DItem::FBO) { +} + +void Scene3DRenderer::init(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, + QRenderAspect *renderAspect) +{ + m_item = item; + m_window = m_item->window(); + m_aspectEngine = aspectEngine; + m_renderAspect = renderAspect; + m_needsShutdown = true; + Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -215,21 +224,14 @@ void Scene3DRenderer::scheduleRootEntityChange() QMetaObject::invokeMethod(m_item, "applyRootEntityChange", Qt::QueuedConnection); } -void Scene3DRenderer::setCleanerHelper(Scene3DCleaner *cleaner) -{ - m_cleaner = cleaner; - if (m_cleaner) { - // Window closed case - QObject::connect(m_item->window(), &QQuickWindow::destroyed, m_cleaner, &Scene3DCleaner::cleanup); - m_cleaner->setRenderer(this); - } -} - // Executed in the QtQuick render thread (which may even be the gui/main with QQuickWidget / RenderControl). void Scene3DRenderer::shutdown() { qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread(); + // In case the same item is rendered on another window reset it + m_resetRequested = true; + // Set to null so that subsequent calls to render // would return early m_item = nullptr; @@ -243,8 +245,13 @@ void Scene3DRenderer::shutdown() // Shutdown the Renderer Aspect while the OpenGL context // is still valid - if (m_renderAspect) + if (m_renderAspect) { static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderShutdown(); + m_renderAspect = nullptr; + } + m_aspectEngine = nullptr; + m_finalFBO.reset(); + m_multisampledFBO.reset(); } // QtQuick render thread (which may also be the gui/main thread with QQuickWidget / RenderControl) @@ -254,7 +261,6 @@ void Scene3DRenderer::onSceneGraphInvalidated() if (m_needsShutdown) { m_needsShutdown = false; shutdown(); - QMetaObject::invokeMethod(m_cleaner, "cleanup"); } } @@ -265,7 +271,6 @@ void Scene3DRenderer::onWindowChanged(QQuickWindow *w) if (m_needsShutdown) { m_needsShutdown = false; shutdown(); - QMetaObject::invokeMethod(m_cleaner, "cleanup"); } } } diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index 08a2c60a3..5674f21c2 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -78,9 +78,7 @@ class Scene3DRenderer : public QObject { Q_OBJECT public: - Scene3DRenderer(Scene3DItem *item, - Qt3DCore::QAspectEngine *aspectEngine, - QRenderAspect *renderAspect); + Scene3DRenderer(); ~Scene3DRenderer(); void setSGNode(Scene3DSGNode *node); @@ -89,7 +87,12 @@ public: void setCompositingMode(Scene3DItem::CompositingMode mode); void setSkipFrame(bool skip); void setScene3DViews(const QVector<Scene3DView *> views); + void init(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, QRenderAspect *renderAspect); + QRenderAspect *renderAspect() const + { + return m_renderAspect; + } public Q_SLOTS: void render(); void shutdown(); @@ -103,13 +106,12 @@ private: void scheduleRootEntityChange(); Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine - Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DRendererCleaner + Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DItem QRenderAspect *m_renderAspect; // Will be released by the aspectEngine QScopedPointer<QOpenGLFramebufferObject> m_multisampledFBO; QScopedPointer<QOpenGLFramebufferObject> m_finalFBO; QScopedPointer<QSGTexture> m_texture; Scene3DSGNode *m_node; // Will be released by the QtQuick SceneGraph - Scene3DCleaner *m_cleaner; QQuickWindow *m_window; QMutex m_windowMutex; QSize m_lastSize; @@ -123,8 +125,9 @@ private: QSemaphore m_allowRendering; Scene3DItem::CompositingMode m_compositingMode; QVector<Scene3DView *> m_views; + bool m_resetRequested = false; - friend class Scene3DCleaner; + friend class Scene3DItem; }; } // namespace Qt3DRender diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index 7434cd901..8efd8db8f 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -278,7 +278,7 @@ void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::ShadersDirty); } - static const QVector<std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const>> shaderTypesToGetters = { + static const QVarLengthArray<std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const>, 6> shaderTypesToGetters { {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph}, {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph}, {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph}, diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index aced13fc5..cbb4751f9 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -308,13 +308,13 @@ Renderer::Renderer(QRenderAspect::RenderType type) // Create jobs to update transforms and bounding volumes // We can only update bounding volumes once all world transforms are known + m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); m_updateWorldBoundingVolumeJob->addDependency(m_calculateBoundingVolumeJob); m_expandBoundingVolumeJob->addDependency(m_updateWorldBoundingVolumeJob); m_updateShaderDataTransformJob->addDependency(m_worldTransformJob); m_pickBoundingVolumeJob->addDependency(m_expandBoundingVolumeJob); m_rayCastingJob->addDependency(m_expandBoundingVolumeJob); - // m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs // Ensures all skeletons are loaded before we try to update them m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs); @@ -1840,12 +1840,8 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Add jobs const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - if (entitiesEnabledDirty) { + if (entitiesEnabledDirty) renderBinJobs.push_back(m_updateTreeEnabledJob); - // This dependency is added here because we clear all dependencies - // at the start of this function. - m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); - } if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { renderBinJobs.push_back(m_worldTransformJob); diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index ef15d7fcd..65e65da3d 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -431,6 +431,7 @@ struct SubRangeSorter<QSortPolicy::Texture> { static void sortSubRange(CommandIt begin, const CommandIt end) { +#ifndef Q_OS_WIN std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) { QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures(); QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures(); @@ -449,6 +450,7 @@ struct SubRangeSorter<QSortPolicy::Texture> return identicalTextureCount < originalTextureASize; }); +#endif } }; diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 2f630e0d9..de9dd861b 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -88,3 +88,5 @@ qtHaveModule(widgets): { rendercapture-cpp \ texture-updates-cpp } + +qtHaveModule(quickwidgets): SUBDIRS += quickwidget-switch diff --git a/tests/manual/quickwidget-switch/main.cpp b/tests/manual/quickwidget-switch/main.cpp new file mode 100644 index 000000000..ebadc458d --- /dev/null +++ b/tests/manual/quickwidget-switch/main.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDesktopWidget> +#include <QScreen> +#include <QApplication> +#include <QMainWindow> +#include <QMdiArea> +#include <QMdiSubWindow> +#include <QQuickWidget> +#include <QVBoxLayout> +#include <QPushButton> + +void configureMainWindow(QMainWindow *w, QMdiArea *mdiArea, QPushButton *button) +{ + auto widget = new QWidget; + auto layout = new QVBoxLayout; + layout->addWidget(mdiArea); + layout->addWidget(button); + widget->setLayout(layout); + w->setCentralWidget(widget); +} + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + + QMainWindow w1; + w1.winId(); + w1.windowHandle()->setScreen(QGuiApplication::screens().at(0)); + auto mdiArea1 = new QMdiArea; + auto button1 = new QPushButton("Switch to this window"); + configureMainWindow(&w1, mdiArea1, button1); + w1.setGeometry(0, 0, 800, 800); + w1.show(); + + QMainWindow w2; + w2.winId(); + w2.windowHandle()->setScreen(QGuiApplication::screens().at(1)); + auto mdiArea2 = new QMdiArea; + auto button2 = new QPushButton("Switch to this window"); + configureMainWindow(&w2, mdiArea2, button2); + w2.setGeometry(0, 0, 800, 800); + w2.show(); + + QMdiSubWindow* subWindow = new QMdiSubWindow(); + + QQuickWidget *quickWidget = new QQuickWidget(); + quickWidget->resize(QSize(400, 400)); + quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); + quickWidget->setSource(QUrl("qrc:/main.qml")); + + subWindow->setWidget(quickWidget); + + QObject::connect(button1, &QPushButton::clicked, + [mdiArea1, mdiArea2, subWindow, button1, button2]() { + mdiArea2->removeSubWindow(subWindow); + mdiArea1->addSubWindow(subWindow); + subWindow->show(); + button1->setEnabled(false); + button2->setEnabled(true); + }); + + QObject::connect(button2, &QPushButton::clicked, + [mdiArea1, mdiArea2, subWindow, button1, button2]() { + mdiArea1->removeSubWindow(subWindow); + mdiArea2->addSubWindow(subWindow); + subWindow->show(); + button1->setEnabled(true); + button2->setEnabled(false); + }); + + mdiArea2->addSubWindow(subWindow); + button2->setEnabled(false); + subWindow->show(); + + return app.exec(); +} diff --git a/tests/manual/quickwidget-switch/main.qml b/tests/manual/quickwidget-switch/main.qml new file mode 100644 index 000000000..d4bce020c --- /dev/null +++ b/tests/manual/quickwidget-switch/main.qml @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +import QtQuick.Scene3D 2.0 + +QQ2.Item { + id: mioitem + width: 300 + height: 300 + Scene3D { + id: scene3d + anchors.fill: parent + Entity { + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -40.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + OrbitCameraController { + camera: camera + } + + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + clearColor: Qt.rgba(0, 0.5, 1, 1) + camera: camera + } + }, + // Event Source will be set by the Qt3DQuickWindow + InputSettings { } + ] + + PhongMaterial { + id: material + } + + TorusMesh { + id: torusMesh + radius: 5 + minorRadius: 1 + rings: 100 + slices: 20 + } + + Transform { + id: torusTransform + scale3D: Qt.vector3d(1.5, 1, 0.5) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + } + + Entity { + id: torusEntity + components: [ torusMesh, material, torusTransform ] + } + + SphereMesh { + id: sphereMesh + radius: 3 + } + + Transform { + id: sphereTransform + property real userAngle: 0.0 + matrix: { + var m = Qt.matrix4x4(); + m.rotate(userAngle, Qt.vector3d(0, 1, 0)); + m.translate(Qt.vector3d(20, 0, 0)); + return m; + } + } + + QQ2.NumberAnimation { + target: sphereTransform + property: "userAngle" + duration: 10000 + from: 0 + to: 360 + + loops: QQ2.Animation.Infinite + running: true + } + + Entity { + id: sphereEntity + components: [ sphereMesh, material, sphereTransform ] + } + } + } +} diff --git a/tests/manual/quickwidget-switch/quickwidget-switch.pro b/tests/manual/quickwidget-switch/quickwidget-switch.pro new file mode 100644 index 000000000..2f1cb98f5 --- /dev/null +++ b/tests/manual/quickwidget-switch/quickwidget-switch.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +QT += 3dextras +CONFIG += resources_big + +QT += 3dcore 3drender 3dinput 3dquick 3dlogic qml quick 3dquickextras widgets quickwidgets + +SOURCES += \ + main.cpp + +RESOURCES += \ + quickwidget-switch.qrc + diff --git a/tests/manual/quickwidget-switch/quickwidget-switch.qrc b/tests/manual/quickwidget-switch/quickwidget-switch.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/quickwidget-switch/quickwidget-switch.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/quickwindow-switch/main.cpp b/tests/manual/quickwindow-switch/main.cpp new file mode 100644 index 000000000..7bebe0c75 --- /dev/null +++ b/tests/manual/quickwindow-switch/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + const QUrl url(QStringLiteral("qrc:/main.qml")); + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/tests/manual/quickwindow-switch/main.qml b/tests/manual/quickwindow-switch/main.qml new file mode 100644 index 000000000..4b474bd11 --- /dev/null +++ b/tests/manual/quickwindow-switch/main.qml @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Window 2.12 as Win +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +import QtQuick.Scene3D 2.0 + +Win.Window { + id: win + width: 300 + height: 350 + visible: true + x: Win.Screen.width / 2 - width / 2 + y: Win.Screen.height / 2 - height / 2 + Item { + id: mioitem + width: 300 + height: 300 + Scene3D { + id: scene3d + anchors.fill: parent + Entity { + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -40.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + OrbitCameraController { + camera: camera + } + + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + clearColor: Qt.rgba(0, 0.5, 1, 1) + camera: camera + } + }, + // Event Source will be set by the Qt3DQuickWindow + InputSettings { } + ] + + PhongMaterial { + id: material + } + + TorusMesh { + id: torusMesh + radius: 5 + minorRadius: 1 + rings: 100 + slices: 20 + } + + Transform { + id: torusTransform + scale3D: Qt.vector3d(1.5, 1, 0.5) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + } + + Entity { + id: torusEntity + components: [ torusMesh, material, torusTransform ] + } + + SphereMesh { + id: sphereMesh + radius: 3 + } + + Transform { + id: sphereTransform + property real userAngle: 0.0 + matrix: { + var m = Qt.matrix4x4(); + m.rotate(userAngle, Qt.vector3d(0, 1, 0)); + m.translate(Qt.vector3d(20, 0, 0)); + return m; + } + } + + NumberAnimation { + target: sphereTransform + property: "userAngle" + duration: 10000 + from: 0 + to: 360 + + loops: Animation.Infinite + running: true + } + + Entity { + id: sphereEntity + components: [ sphereMesh, material, sphereTransform ] + } + } + } + } + Rectangle { + height: 50 + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + color: "yellow" + MouseArea { + anchors.fill: parent + z: 5 + onClicked: { + win.screen = (win.screen === Qt.application.screens[0] ? Qt.application.screens[1] : Qt.application.screens[0]) + } + } + Text { + anchors.centerIn: parent + minimumPointSize: 12 + fontSizeMode: Text.Fit + text: "Move to the other screen" + } + } +} diff --git a/tests/manual/quickwindow-switch/quickwindow-switch.pro b/tests/manual/quickwindow-switch/quickwindow-switch.pro new file mode 100644 index 000000000..2f338d36d --- /dev/null +++ b/tests/manual/quickwindow-switch/quickwindow-switch.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +QT += 3dextras +CONFIG += resources_big + +QT += 3dcore 3drender 3dinput 3dquick 3dlogic qml quick 3dquickextras + +SOURCES += \ + main.cpp + +RESOURCES += \ + quickwindow-switch.qrc + diff --git a/tests/manual/quickwindow-switch/quickwindow-switch.qrc b/tests/manual/quickwindow-switch/quickwindow-switch.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/quickwindow-switch/quickwindow-switch.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> |