From e82898a184944e697313d1bd7c58750c2021d3cf Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 16 Mar 2023 14:31:41 +0200 Subject: [PATCH] QmlDesigner: Implement basic lights baking support It is expected that user manually specifies all necessary light baking related properties, including exposing them from subcomponents if needed. qlmdenoiser that is used to denoise generated light maps is a third party application. It can be found here: https://git.qt.io/laagocs/qlmdenoiser Fixes: QDS-9403 Change-Id: Ida6fc142440b9ffa8cc97d578f85d8b76cb4b43f Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri --- .../edit3dQmlSource/BakeLightsDialog.qml | 90 +++++++ .../commands/puppettocreatorcommand.h | 6 +- .../interfaces/nodeinstanceglobal.h | 3 +- src/plugins/qmldesigner/CMakeLists.txt | 2 + .../components/edit3d/bakelights.cpp | 250 ++++++++++++++++++ .../components/edit3d/bakelights.h | 54 ++++ .../edit3d/bakelightsconnectionmanager.cpp | 48 ++++ .../edit3d/bakelightsconnectionmanager.h | 28 ++ .../components/edit3d/edit3dactions.cpp | 40 ++- .../components/edit3d/edit3dactions.h | 15 ++ .../components/edit3d/edit3dview.cpp | 53 +++- .../components/edit3d/edit3dview.h | 8 + .../components/edit3d/edit3dwidget.cpp | 8 + .../components/edit3d/edit3dwidget.h | 1 + .../qmldesigner/designercore/include/model.h | 1 + .../designercore/include/nodeinstanceview.h | 1 + .../instances/nodeinstanceview.cpp | 5 + .../qmldesigner/designercore/model/model.cpp | 10 + .../qmldesigner/qmldesignerconstants.h | 2 +- src/plugins/qmldesigner/settingspage.cpp | 2 +- src/tools/qml2puppet/CMakeLists.txt | 1 + .../qml2puppet/instances/instances.pri | 2 + .../nodeinstanceserverdispatcher.cpp | 3 + .../qt5bakelightsnodeinstanceserver.cpp | 233 ++++++++++++++++ .../qt5bakelightsnodeinstanceserver.h | 57 ++++ .../instances/qt5nodeinstanceclientproxy.cpp | 4 + .../qml2puppet/instances/servernodeinstance.h | 1 + 27 files changed, 916 insertions(+), 12 deletions(-) create mode 100644 share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsDialog.qml create mode 100644 src/plugins/qmldesigner/components/edit3d/bakelights.cpp create mode 100644 src/plugins/qmldesigner/components/edit3d/bakelights.h create mode 100644 src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp create mode 100644 src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h create mode 100644 src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp create mode 100644 src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.h diff --git a/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsDialog.qml b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsDialog.qml new file mode 100644 index 00000000000..9632c0b4a11 --- /dev/null +++ b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsDialog.qml @@ -0,0 +1,90 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuickDesignerTheme +import HelperWidgets +import StudioControls as StudioControls +import StudioTheme as StudioTheme + +Rectangle { + id: root + + color: StudioTheme.Values.themePanelBackground + + Column { + id: col + padding: 5 + leftPadding: 10 + spacing: 5 + + Text { + id: title + text: qsTr("Baking lights for 3D view: %1").arg(sceneId) + font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize + color: StudioTheme.Values.themeTextColor + } + + Rectangle { + width: root.width - 16 + height: root.height - title.height - button.height - 20 + + color: StudioTheme.Values.themePanelBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + ScrollView { + id: scrollView + + anchors.fill: parent + anchors.margins: 4 + + clip: true + + Behavior on contentY { + PropertyAnimation { + easing.type: Easing.InOutQuad + } + } + + Text { + id: progressText + width: scrollView.width + font.pixelSize: StudioTheme.Values.myFontSize + color: StudioTheme.Values.themeTextColor + } + + function ensureVisible() + { + let newPos = scrollView.contentHeight - scrollView.height + scrollView.contentY = newPos < 0 ? 0 : newPos + } + } + + } + + Connections { + target: rootView + function onProgress(msg) { + progressText.text += progressText.text === "" ? msg : "\n" + msg + scrollView.ensureVisible() + } + + function onFinished() { + button.text = qsTr("Close") + } + } + + Button { + id: button + text: qsTr("Cancel") + anchors.right: parent.right + anchors.margins: StudioTheme.Values.dialogButtonPadding + + onClicked: rootView.cancel() + } + } +} diff --git a/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h index 5c8cd3af063..30b0cce9981 100644 --- a/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h +++ b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h @@ -19,7 +19,11 @@ public: RenderModelNodePreviewImage, Import3DSupport, NodeAtPos, - None }; + BakeLightsProgress, + BakeLightsFinished, + BakeLightsAborted, + None + }; PuppetToCreatorCommand(Type type, const QVariant &data); PuppetToCreatorCommand() = default; diff --git a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h index 57abf115e17..67f0fa4c5c2 100644 --- a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h +++ b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h @@ -48,7 +48,8 @@ enum class View3DActionType { SelectGridColor, ResetBackgroundColor, SyncBackgroundColor, - GetNodeAtPos + GetNodeAtPos, + SetBakeLightsView3D }; constexpr bool isNanotraceEnabled() diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 00714ca6cc6..9280965ce0d 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -653,6 +653,8 @@ extend_qtc_plugin(QmlDesigner edit3dactions.cpp edit3dactions.h edit3dvisibilitytogglesmenu.cpp edit3dvisibilitytogglesmenu.h backgroundcolorselection.cpp backgroundcolorselection.h + bakelights.cpp bakelights.h + bakelightsconnectionmanager.cpp bakelightsconnectionmanager.h edit3d.qrc ) diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp new file mode 100644 index 00000000000..c44b49bb5c4 --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp @@ -0,0 +1,250 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "bakelights.h" + +#include "abstractview.h" +#include "bakelightsconnectionmanager.h" +#include "documentmanager.h" +#include "modelnode.h" +#include "nodeabstractproperty.h" +#include "nodeinstanceview.h" +#include "nodemetainfo.h" +#include "plaintexteditmodifier.h" +#include "rewriterview.h" +#include "variantproperty.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +static QString propertyEditorResourcesPath() +{ +#ifdef SHARE_QML_PATH + if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) + return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources"; +#endif + return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString(); +} + +static QString qmlSourcesPath() +{ +#ifdef SHARE_QML_PATH + if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) + return QLatin1String(SHARE_QML_PATH) + "/edit3dQmlSource"; +#endif + return Core::ICore::resourcePath("qmldesigner/edit3dQmlSource").toString(); +} + +BakeLights::BakeLights(AbstractView *view) + : QObject(view) + , m_view(view) +{ + m_view3dId = resolveView3dId(view); + + if (m_view3dId.isEmpty()) { + // It should never get here, baking controls should be disabled in this case + qWarning() << __FUNCTION__ << "Active scene is not View3D"; + deleteLater(); + return; + } + + // Create folders for lightmaps if they do not exist + PropertyName loadPrefixPropName{"loadPrefix"}; + const QList bakedLightmapNodes = m_view->allModelNodesOfType( + m_view->model()->qtQuick3DBakedLightmapMetaInfo()); + Utils::FilePath currentPath = DocumentManager::currentFilePath().absolutePath(); + QSet pathSet; + for (const ModelNode &node : bakedLightmapNodes) { + if (node.hasVariantProperty(loadPrefixPropName)) { + QString prefix = node.variantProperty(loadPrefixPropName).value().toString(); + Utils::FilePath fp = Utils::FilePath::fromString(prefix); + if (fp.isRelativePath()) { + fp = currentPath.pathAppended(prefix); + if (!fp.exists()) + pathSet.insert(fp); + } + } + } + for (const Utils::FilePath &fp : std::as_const(pathSet)) + fp.createDir(); + + // Show non-modal progress dialog with cancel button + QString path = qmlSourcesPath() + "/BakeLightsDialog.qml"; + + m_dialog = new QQuickView; + m_dialog->setTitle(tr("Bake Lights")); + m_dialog->setResizeMode(QQuickView::SizeRootObjectToView); + m_dialog->setMinimumSize({150, 100}); + m_dialog->setWidth(800); + m_dialog->setHeight(400); + m_dialog->setFlags(Qt::Dialog); + m_dialog->setModality(Qt::NonModal); + m_dialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); + + m_dialog->rootContext()->setContextProperties({ + {"rootView", QVariant::fromValue(this)}, + {"sceneId", QVariant::fromValue(m_view3dId)} + }); + m_dialog->setSource(QUrl::fromLocalFile(path)); + m_dialog->installEventFilter(this); + m_dialog->show(); + + QTimer::singleShot(0, this, &BakeLights::bakeLights); +} + +BakeLights::~BakeLights() +{ + if (m_connectionManager) { + m_connectionManager->setProgressCallback({}); + m_connectionManager->setFinishedCallback({}); + m_connectionManager->setCrashCallback({}); + } + + if (m_model) { + m_model->setNodeInstanceView({}); + m_model->setRewriterView({}); + m_model.reset(); + } + + delete m_dialog; + delete m_rewriterView; + delete m_nodeInstanceView; + delete m_connectionManager; +} + +QString BakeLights::resolveView3dId(AbstractView *view) +{ + if (!view || !view->model()) + return {}; + + QString view3dId; + ModelNode activeView3D; + ModelNode activeScene = view->active3DSceneNode(); + + if (activeScene.isValid()) { + if (activeScene.metaInfo().isQtQuick3DView3D()) { + activeView3D = activeScene; + } else { + ModelNode sceneParent = activeScene.parentProperty().parentModelNode(); + if (sceneParent.metaInfo().isQtQuick3DView3D()) + activeView3D = sceneParent; + } + view3dId = activeView3D.id(); + } + + return view3dId; +} + +void BakeLights::raiseDialog() +{ + if (m_dialog) + m_dialog->raise(); +} + +void BakeLights::bakeLights() +{ + if (!m_view || !m_view->model()) + return; + + // Start baking process + m_connectionManager = new BakeLightsConnectionManager; + m_rewriterView = new RewriterView{m_view->externalDependencies(), RewriterView::Amend}; + m_nodeInstanceView = new NodeInstanceView{*m_connectionManager, m_view->externalDependencies()}; + + m_model = QmlDesigner::Model::create("QtQuick/Item", 2, 1); + m_model->setFileUrl(m_view->model()->fileUrl()); + + // Take the current unsaved state of the main model and apply it to our copy + auto textDocument = std::make_unique( + m_view->model()->rewriterView()->textModifier()->textDocument()->toRawText()); + + auto modifier = std::make_unique(textDocument.get(), + QTextCursor{textDocument.get()}); + + m_rewriterView->setTextModifier(modifier.get()); + m_model->setRewriterView(m_rewriterView); + + auto rootModelNodeMetaInfo = m_rewriterView->rootModelNode().metaInfo(); + bool is3DRoot = m_rewriterView->errors().isEmpty() + && (rootModelNodeMetaInfo.isQtQuick3DNode() + || rootModelNodeMetaInfo.isQtQuick3DMaterial()); + + if (!m_rewriterView->errors().isEmpty() + || (!m_rewriterView->rootModelNode().metaInfo().isGraphicalItem() && !is3DRoot)) { + emit progress(tr("Invalid root node, baking aborted.")); + emit finished(); + m_dialog->raise(); + return; + } + + m_nodeInstanceView->setTarget(m_view->nodeInstanceView()->target()); + + auto progressCallback = [this](const QString &msg) { + emit progress(msg); + }; + + auto finishedCallback = [this](const QString &msg) { + m_dialog->raise(); + emit progress(msg); + emit finished(); + + // Puppet reset is needed to update baking results to current views + m_view->resetPuppet(); + }; + + auto crashCallback = [this]() { + m_dialog->raise(); + emit progress(tr("Baking process crashed, baking aborted.")); + emit finished(); + }; + + m_connectionManager->setProgressCallback(std::move(progressCallback)); + m_connectionManager->setFinishedCallback(std::move(finishedCallback)); + m_connectionManager->setCrashCallback(std::move(crashCallback)); + + m_model->setNodeInstanceView(m_nodeInstanceView); + + // InternalIds are not guaranteed to match between normal model and our copy of it, so + // we identify the View3D by its qml id. + m_nodeInstanceView->view3DAction(View3DActionType::SetBakeLightsView3D, m_view3dId); +} + +void BakeLights::cancel() +{ + if (!m_dialog.isNull() && m_dialog->isVisible()) + m_dialog->close(); + + deleteLater(); +} + +bool BakeLights::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_dialog) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Escape) + cancel(); + } else if (event->type() == QEvent::Close) { + cancel(); + } + } + + return QObject::eventFilter(obj, event); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.h b/src/plugins/qmldesigner/components/edit3d/bakelights.h new file mode 100644 index 00000000000..d63ca0b3b82 --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/bakelights.h @@ -0,0 +1,54 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +#pragma once + +#include "qmldesignercorelib_global.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QQuickView; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class AbstractView; +class BakeLightsConnectionManager; +class NodeInstanceView; +class RewriterView; + +class BakeLights : public QObject +{ + Q_OBJECT + +public: + BakeLights(AbstractView *view); + ~BakeLights(); + + Q_INVOKABLE void cancel(); + + void raiseDialog(); + + static QString resolveView3dId(AbstractView *view); + +signals: + void finished(); + void progress(const QString &msg); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private: + void bakeLights(); + + QPointer m_dialog; + QPointer m_connectionManager; + QPointer m_nodeInstanceView; + QPointer m_rewriterView; + QPointer m_view; + ModelPointer m_model; + QString m_view3dId; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp new file mode 100644 index 00000000000..201ca1d2e9b --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "bakelightsconnectionmanager.h" + +#include + +namespace QmlDesigner { + +BakeLightsConnectionManager::BakeLightsConnectionManager() +{ + connections().emplace_back("Bake lights", "bakelightsmode"); +} + +void BakeLightsConnectionManager::setProgressCallback(Callback callback) +{ + m_progressCallback = std::move(callback); +} + +void BakeLightsConnectionManager::setFinishedCallback(Callback callback) +{ + m_finishedCallback = std::move(callback); +} + +void BakeLightsConnectionManager::dispatchCommand(const QVariant &command, + ConnectionManagerInterface::Connection &) +{ + static const int commandType = QMetaType::type("PuppetToCreatorCommand"); + + if (command.userType() == commandType) { + auto cmd = command.value(); + switch (cmd.type()) { + case PuppetToCreatorCommand::BakeLightsProgress: + m_progressCallback(cmd.data().toString()); + break; + case PuppetToCreatorCommand::BakeLightsAborted: + m_finishedCallback(tr("Baking aborted!")); + break; + case PuppetToCreatorCommand::BakeLightsFinished: + m_finishedCallback(tr("Baking finished!")); + break; + default: + break; + } + } +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h new file mode 100644 index 00000000000..2af5e56c114 --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h @@ -0,0 +1,28 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "connectionmanager.h" + +namespace QmlDesigner { + +class BakeLightsConnectionManager : public ConnectionManager +{ +public: + using Callback = std::function; + + BakeLightsConnectionManager(); + + void setProgressCallback(Callback callback); + void setFinishedCallback(Callback callback); + +protected: + void dispatchCommand(const QVariant &command, Connection &connection) override; + +private: + Callback m_progressCallback; + Callback m_finishedCallback; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp index 61731c578f8..12d2dd05528 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp @@ -2,18 +2,15 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "edit3dactions.h" -#include "edit3dview.h" -#include -#include -#include -#include +#include "bakelights.h" +#include "edit3dview.h" +#include "nodemetainfo.h" +#include "qmldesignerconstants.h" #include "seekerslider.h" #include -#include - namespace QmlDesigner { Edit3DActionTemplate::Edit3DActionTemplate(const QString &description, @@ -147,4 +144,33 @@ bool Edit3DParticleSeekerAction::isEnabled(const SelectionContext &) const return m_seeker->isEnabled(); } +Edit3DBakeLightsAction::Edit3DBakeLightsAction(const QIcon &icon, + Edit3DView *view, + SelectionContextOperation selectionAction) + : Edit3DAction(QmlDesigner::Constants::EDIT3D_BAKE_LIGHTS, + View3DActionType::Empty, + QCoreApplication::translate("BakeLights", "Bake Lights"), + QKeySequence(), + false, + false, + icon, + view, + selectionAction, + QCoreApplication::translate("BakeLights", "Bake lights for the current 3D scene.")) + , m_view(view) +{ + +} + +bool Edit3DBakeLightsAction::isVisible(const SelectionContext &) const +{ + return m_view->isBakingLightsSupported(); +} + +bool Edit3DBakeLightsAction::isEnabled(const SelectionContext &) const +{ + return m_view->isBakingLightsSupported() + && !BakeLights::resolveView3dId(m_view).isEmpty(); +} + } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h index bad427a25be..4e8be202b9f 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h @@ -122,4 +122,19 @@ private: SeekerSliderAction *m_seeker = nullptr; }; +class Edit3DBakeLightsAction : public Edit3DAction +{ +public: + Edit3DBakeLightsAction(const QIcon &icon, + Edit3DView *view, + SelectionContextOperation selectionAction); + +protected: + bool isVisible(const SelectionContext &) const override; + bool isEnabled(const SelectionContext &) const override; + +private: + Edit3DView *m_view = nullptr; +}; + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index d92e76362b9..d346e2bf164 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -4,6 +4,7 @@ #include "edit3dview.h" #include "backgroundcolorselection.h" +#include "bakelights.h" #include "designeractionmanager.h" #include "designericons.h" #include "designersettings.h" @@ -20,11 +21,16 @@ #include "qmldesignerplugin.h" #include "qmlvisualnode.h" #include "seekerslider.h" +#include "theme.h" #include #include -#include +#include +#include + +#include + #include #include #include @@ -204,6 +210,12 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) m_particlesPlayAction->action()->setChecked(sceneState[particlesPlayKey].toBool()); else m_particlesPlayAction->action()->setChecked(true); + + // Selection context change updates visible and enabled states + SelectionContext selectionContext(this); + selectionContext.setUpdateMode(SelectionContext::UpdateMode::Fast); + if (m_bakeLightsAction) + m_bakeLightsAction->currentContextChanged(selectionContext); } void Edit3DView::modelAttached(Model *model) @@ -219,6 +231,13 @@ void Edit3DView::modelAttached(Model *model) edit3DWidget()->canvas()->busyIndicator()->show(); + m_isBakingLightsSupported = false; + ProjectExplorer::Target *target = QmlDesignerPlugin::instance()->currentDesignDocument()->currentTarget(); + if (target && target->kit()) { + if (QtSupport::QtVersion *qtVer = QtSupport::QtKitAspect::qtVersion(target->kit())) + m_isBakingLightsSupported = qtVer->qtVersion() >= QVersionNumber(6, 5, 0); + } + connect(model->metaInfo().itemLibraryInfo(), &ItemLibraryInfo::entriesChanged, this, &Edit3DView::onEntriesChanged, Qt::UniqueConnection); } @@ -279,6 +298,11 @@ void Edit3DView::handleEntriesChanged() void Edit3DView::modelAboutToBeDetached(Model *model) { + m_isBakingLightsSupported = false; + + if (m_bakeLights) + m_bakeLights->cancel(); + // Hide the canvas when model is detached (i.e. changing documents) if (edit3DWidget() && edit3DWidget()->canvas()) { m_canvasCache.insert(model, edit3DWidget()->canvas()->renderImage()); @@ -702,6 +726,17 @@ void Edit3DView::createEdit3DActions() m_seekerAction->action()->setEnabled(!m_particlesPlayAction->action()->isChecked()); }; + SelectionContextOperation bakeLightsTrigger = [this](const SelectionContext &) { + if (!m_isBakingLightsSupported) + return; + + // BakeLights cleans itself up when its dialog is closed + if (!m_bakeLights) + m_bakeLights = new BakeLights(this); + else + m_bakeLights->raiseDialog(); + }; + m_particleViewModeAction = new Edit3DAction( QmlDesigner::Constants::EDIT3D_PARTICLE_MODE, View3DActionType::Edit3DParticleModeToggle, @@ -804,6 +839,11 @@ void Edit3DView::createEdit3DActions() m_seekerAction = createSeekerSliderAction(); + m_bakeLightsAction = new Edit3DBakeLightsAction( + toolbarIcon(Theme::editLightOn_medium), //: TODO placeholder icon + this, + bakeLightsTrigger); + m_leftActions << m_selectionModeAction; m_leftActions << nullptr; // Null indicates separator m_leftActions << nullptr; // Second null after separator indicates an exclusive group @@ -830,6 +870,7 @@ void Edit3DView::createEdit3DActions() m_rightActions << nullptr; m_rightActions << m_seekerAction; m_rightActions << nullptr; + m_rightActions << m_bakeLightsAction; m_rightActions << m_resetAction; m_visibilityToggleActions << m_showGridAction; @@ -870,6 +911,11 @@ Edit3DAction *Edit3DView::edit3DAction(View3DActionType type) const return m_edit3DActions.value(type, nullptr).data(); } +Edit3DBakeLightsAction *Edit3DView::bakeLightsAction() const +{ + return m_bakeLightsAction; +} + void Edit3DView::addQuick3DImport() { DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); @@ -939,4 +985,9 @@ void Edit3DView::dropAsset(const QString &file, const QPointF &pos) emitView3DAction(View3DActionType::GetNodeAtPos, pos); } +bool Edit3DView::isBakingLightsSupported() const +{ + return m_isBakingLightsSupported; +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 2b746cf1af7..109555f586b 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -22,8 +22,10 @@ QT_END_NAMESPACE namespace QmlDesigner { +class BakeLights; class Edit3DWidget; class Edit3DAction; +class Edit3DBakeLightsAction; class Edit3DCameraAction; class QMLDESIGNERCOMPONENTS_EXPORT Edit3DView : public AbstractView @@ -57,6 +59,7 @@ public: QVector visibilityToggleActions() const; QVector backgroundColorActions() const; Edit3DAction *edit3DAction(View3DActionType type) const; + Edit3DBakeLightsAction *bakeLightsAction() const; void addQuick3DImport(); void startContextMenu(const QPoint &pos); @@ -66,6 +69,8 @@ public: void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos); void dropAsset(const QString &file, const QPointF &pos); + bool isBakingLightsSupported() const; + private slots: void onEntriesChanged(); @@ -122,6 +127,7 @@ private: Edit3DAction *m_visibilityTogglesAction = nullptr; Edit3DAction *m_backgrondColorMenuAction = nullptr; Edit3DAction *m_seekerAction = nullptr; + Edit3DBakeLightsAction *m_bakeLightsAction = nullptr; int particlemode; ModelCache m_canvasCache; ModelNode m_droppedModelNode; @@ -130,6 +136,8 @@ private: NodeAtPosReqType m_nodeAtPosReqType; QPoint m_contextMenuPos; QTimer m_compressionTimer; + QPointer m_bakeLights; + bool m_isBakingLightsSupported = false; friend class Edit3DAction; }; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 408584e166b..a217e396d9c 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -261,6 +261,12 @@ void Edit3DWidget::createContextMenu() view()->emitView3DAction(View3DActionType::AlignViewToCamera, true); }); + m_bakeLightsAction = m_contextMenu->addAction( + contextIcon(DesignerIcons::LightIcon), // TODO: placeholder icon + tr("Bake Lights"), [&] { + view()->bakeLightsAction()->action()->trigger(); + }); + m_contextMenu->addSeparator(); m_selectParentAction = m_contextMenu->addAction( @@ -466,6 +472,8 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_alignViewAction->setEnabled(isCamera); m_selectParentAction->setEnabled(selectionExcludingRoot); m_toggleGroupAction->setEnabled(true); + m_bakeLightsAction->setVisible(view()->bakeLightsAction()->action()->isVisible()); + m_bakeLightsAction->setEnabled(view()->bakeLightsAction()->action()->isEnabled()); m_contextMenu->popup(mapToGlobal(pos)); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 092abd313a5..eecd52345fa 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -75,6 +75,7 @@ private: QPointer m_visibilityTogglesMenu; QPointer m_backgroundColorMenu; QPointer m_contextMenu; + QPointer m_bakeLightsAction; QPointer m_editComponentAction; QPointer m_editMaterialAction; QPointer m_duplicateAction; diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 9e6c7ca36ad..f3227361e68 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -87,6 +87,7 @@ public: NodeMetaInfo flowViewFlowTransitionMetaInfo() const; NodeMetaInfo flowViewFlowWildcardMetaInfo() const; NodeMetaInfo fontMetaInfo() const; + NodeMetaInfo qtQuick3DBakedLightmapMetaInfo() const; NodeMetaInfo qtQuick3DDefaultMaterialMetaInfo() const; NodeMetaInfo qtQuick3DMaterialMetaInfo() const; NodeMetaInfo qtQuick3DModelMetaInfo() const; diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index 467cef0ed3d..11017a27b1c 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -122,6 +122,7 @@ public: QImage statePreviewImage(const ModelNode &stateNode) const; void setTarget(ProjectExplorer::Target *newTarget); + ProjectExplorer::Target *target() const; void sendToken(const QString &token, int number, const QVector &nodeVector); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 7aaed70c9dd..ebe5acd9d28 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1572,6 +1572,11 @@ void NodeInstanceView::setTarget(ProjectExplorer::Target *newTarget) } } +ProjectExplorer::Target *NodeInstanceView::target() const +{ + return m_currentTarget; +} + void NodeInstanceView::statePreviewImagesChanged(const StatePreviewImageChangedCommand &command) { if (!model()) diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index a234c11e1fe..13197666fc4 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1939,6 +1939,16 @@ NodeMetaInfo Model::qtQuick3DTextureMetaInfo() const } } +NodeMetaInfo Model::qtQuick3DBakedLightmapMetaInfo() const +{ + if constexpr (useProjectStorage()) { + using namespace Storage::Info; + return createNodeMetaInfo(); + } else { + return metaInfo("QtQuick3D.BakedLightmap"); + } +} + NodeMetaInfo Model::qtQuick3DMaterialMetaInfo() const { if constexpr (useProjectStorage()) { diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 743d70bcbc9..d38dad74c7e 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -62,7 +62,7 @@ const char EDIT3D_PARTICLES_SEEKER[] = "QmlDesigner.Editor3D.ParticlesSeeker" const char EDIT3D_PARTICLES_RESTART[] = "QmlDesigner.Editor3D.ParticlesRestart"; const char EDIT3D_VISIBILITY_TOGGLES[] = "QmlDesigner.Editor3D.VisibilityToggles"; const char EDIT3D_BACKGROUND_COLOR_ACTIONS[] = "QmlDesigner.Editor3D.BackgroundColorActions"; - +const char EDIT3D_BAKE_LIGHTS[] = "QmlDesigner.Editor3D.BakeLights"; const char QML_DESIGNER_SUBFOLDER[] = "/designer/"; const char COMPONENT_BUNDLES_FOLDER[] = "/ComponentBundles"; diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp index 6acb2284217..52a58e01a5e 100644 --- a/src/plugins/qmldesigner/settingspage.cpp +++ b/src/plugins/qmldesigner/settingspage.cpp @@ -41,7 +41,7 @@ namespace Internal { static QStringList puppetModes() { - static QStringList puppetModeList{"", "all", "editormode", "rendermode", "previewmode"}; + static QStringList puppetModeList{"", "all", "editormode", "rendermode", "previewmode", "bakelightsmode"}; return puppetModeList; } diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 62325819a58..1d8dc8691b4 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -175,6 +175,7 @@ extend_qtc_executable(qml2puppet qmlstatenodeinstance.cpp qmlstatenodeinstance.h qmltransitionnodeinstance.cpp qmltransitionnodeinstance.h qt3dpresentationnodeinstance.cpp qt3dpresentationnodeinstance.h + qt5bakelightsnodeinstanceserver.cpp qt5bakelightsnodeinstanceserver.h qt5informationnodeinstanceserver.cpp qt5informationnodeinstanceserver.h qt5nodeinstanceclientproxy.cpp qt5nodeinstanceclientproxy.h qt5nodeinstanceserver.cpp qt5nodeinstanceserver.h diff --git a/src/tools/qml2puppet/qml2puppet/instances/instances.pri b/src/tools/qml2puppet/qml2puppet/instances/instances.pri index 2d3b4ceedfe..505dd748e49 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/instances.pri +++ b/src/tools/qml2puppet/qml2puppet/instances/instances.pri @@ -25,6 +25,7 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \ $$PWD/qt5captureimagenodeinstanceserver.h \ $$PWD/qt5capturepreviewnodeinstanceserver.h \ $$PWD/qt5testnodeinstanceserver.h \ + $$PWD/qt5bakelightsnodeinstanceserver.h \ $$PWD/qt5informationnodeinstanceserver.h \ $$PWD/qt5rendernodeinstanceserver.h \ $$PWD/qt5previewnodeinstanceserver.h \ @@ -60,6 +61,7 @@ SOURCES += $$PWD/qt5nodeinstanceserver.cpp \ $$PWD/qt5captureimagenodeinstanceserver.cpp \ $$PWD/qt5capturepreviewnodeinstanceserver.cpp \ $$PWD/qt5testnodeinstanceserver.cpp \ + $$PWD/qt5bakelightsnodeinstanceserver.cpp \ $$PWD/qt5informationnodeinstanceserver.cpp \ $$PWD/qt5rendernodeinstanceserver.cpp \ $$PWD/qt5previewnodeinstanceserver.cpp \ diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp index 09910847a94..9815d21ac47 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp @@ -3,6 +3,7 @@ #include "nodeinstanceserverdispatcher.h" +#include "qt5bakelightsnodeinstanceserver.h" #include "qt5captureimagenodeinstanceserver.h" #include "qt5capturepreviewnodeinstanceserver.h" #include "qt5informationnodeinstanceserver.h" @@ -170,6 +171,8 @@ std::unique_ptr createNodeInstanceServer( return std::make_unique(nodeInstanceClient); else if (serverName == "previewmode") return std::make_unique(nodeInstanceClient); + else if (serverName == "bakelightsmode") + return std::make_unique(nodeInstanceClient); return {}; } diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp new file mode 100644 index 00000000000..87b125480d8 --- /dev/null +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp @@ -0,0 +1,233 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "qt5bakelightsnodeinstanceserver.h" + +#if BAKE_LIGHTS_SUPPORTED +#include "createscenecommand.h" +#include "view3dactioncommand.h" + +#include "nodeinstanceclientinterface.h" +#include "puppettocreatorcommand.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#endif + +namespace QmlDesigner { + +Qt5BakeLightsNodeInstanceServer::Qt5BakeLightsNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : + Qt5NodeInstanceServer(nodeInstanceClient) +{ + setSlowRenderTimerInterval(100000000); + setRenderTimerInterval(100); +} + +#if BAKE_LIGHTS_SUPPORTED + +Qt5BakeLightsNodeInstanceServer::~Qt5BakeLightsNodeInstanceServer() +{ + cleanup(); +} + +void Qt5BakeLightsNodeInstanceServer::createScene(const CreateSceneCommand &command) +{ + initializeView(); + registerFonts(command.resourceUrl); + setTranslationLanguage(command.language); + setupScene(command); + startRenderTimer(); + + // Set working directory to a temporary directory, as baking process creates a file there + if (m_workingDir.isValid()) + QDir::setCurrent(m_workingDir.path()); +} + +void Qt5BakeLightsNodeInstanceServer::view3DAction(const View3DActionCommand &command) +{ + switch (command.type()) { + case View3DActionType::SetBakeLightsView3D: { + QString id = command.value().toString(); + const QList allViews = allView3DInstances(); + for (const auto &view : allViews) { + if (view.id() == id) { + m_view3D = qobject_cast(view.internalObject()); + break; + } + } + + if (!m_view3D) + abort(tr("View3D not found: '%1'").arg(id)); + else + startRenderTimer(); + break; + } + default: + break; + } +} + +void Qt5BakeLightsNodeInstanceServer::startRenderTimer() +{ + if (timerId() != 0) + killTimer(timerId()); + + int timerId = startTimer(renderTimerInterval()); + + setTimerId(timerId); +} + +void Qt5BakeLightsNodeInstanceServer::bakeLights() +{ + if (!m_view3D) { + abort(tr("Invalid View3D object set.")); + return; + } + + QQuick3DLightmapBaker::Callback callback = [this](QQuick3DLightmapBaker::BakingStatus status, + std::optional msg, QQuick3DLightmapBaker::BakingControl *) { + switch (status) { + case QQuick3DLightmapBaker::BakingStatus::Progress: + case QQuick3DLightmapBaker::BakingStatus::Warning: + case QQuick3DLightmapBaker::BakingStatus::Error: + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, msg.value_or("")}); + break; + case QQuick3DLightmapBaker::BakingStatus::Cancelled: + abort(tr("Baking cancelled.")); + break; + case QQuick3DLightmapBaker::BakingStatus::Complete: + runDenoiser(); + break; + default: + qWarning() << __FUNCTION__ << "Unexpected light baking status received:" + << int(status) << msg.value_or(""); + break; + } + }; + + QQuick3DLightmapBaker *baker = m_view3D->lightmapBaker(); + baker->bake(callback); + + m_bakingStarted = true; +} + +void Qt5BakeLightsNodeInstanceServer::cleanup() +{ + m_workingDir.remove(); + if (m_denoiser) { + if (m_denoiser->state() == QProcess::Running) + m_denoiser->terminate(); + m_denoiser->deleteLater(); + } +} + +void Qt5BakeLightsNodeInstanceServer::abort(const QString &msg) +{ + cleanup(); + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsAborted, msg}); +} + +void Qt5BakeLightsNodeInstanceServer::finish() +{ + cleanup(); + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsFinished, {}}); +} + +void Qt5BakeLightsNodeInstanceServer::runDenoiser() +{ + // Check if denoiser exists (as it is third party app) + QString binPath = QLibraryInfo::path(QLibraryInfo::BinariesPath); +#if defined(Q_OS_WIN) + binPath += "/qlmdenoiser.exe"; +#elif defined(Q_OS_MACOS) + // TODO: What is the path in mac? +#else + binPath += "/qlmdenoiser"; +#endif + + QFileInfo fi(binPath); + if (!fi.exists()) { + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, + tr("Warning: Denoiser executable not found, cannot denoise baked lightmaps (%1).") + .arg(binPath)}); + finish(); + return; + } + + m_denoiser = new QProcess(); + + QObject::connect(m_denoiser, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) { + m_workingDir.remove(); + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, + tr("Warning: An error occurred while running denoiser process!")}); + finish(); + }); + + QObject::connect(m_denoiser, &QProcess::finished, this, [this](int exitCode, + QProcess::ExitStatus exitStatus) { + if (exitCode == 0 && exitStatus == QProcess::NormalExit) { + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, + tr("Denoising finished.")}); + } else { + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, + tr("Warning: Denoiser process failed with exit code '%1'!").arg(exitCode)}); + } + finish(); + }); + + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::BakeLightsProgress, + tr("Denoising baked lightmaps...")}); + + m_denoiser->setWorkingDirectory(m_workingDir.path()); + m_denoiser->start(binPath, {"qlm_list.txt"}); + +} + +void Qt5BakeLightsNodeInstanceServer::collectItemChangesAndSendChangeCommands() +{ + static bool inFunction = false; + + if (!rootNodeInstance().holdsGraphical()) + return; + + if (!inFunction) { + inFunction = true; + + QQuickDesignerSupport::polishItems(quickWindow()); + + render(); + + inFunction = false; + } +} + +void Qt5BakeLightsNodeInstanceServer::render() +{ + // Render multiple times to make sure everything gets rendered correctly before baking + if (++m_renderCount == 4) { + bakeLights(); + } else { + rootNodeInstance().updateDirtyNodeRecursive(); + renderWindow(); + if (m_bakingStarted) + slowDownRenderTimer(); // No more renders needed + } +} +#endif + +} // namespace QmlDesigner diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.h new file mode 100644 index 00000000000..fc99adc9021 --- /dev/null +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.h @@ -0,0 +1,57 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "qt5nodeinstanceserver.h" + +#if QUICK3D_MODULE && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) +#include +#define BAKE_LIGHTS_SUPPORTED 1 +#endif + +QT_BEGIN_NAMESPACE +class QProcess; +class QQuick3DViewport; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class Qt5BakeLightsNodeInstanceServer : public Qt5NodeInstanceServer +{ + Q_OBJECT +public: + explicit Qt5BakeLightsNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient); + +#if BAKE_LIGHTS_SUPPORTED +public: + virtual ~Qt5BakeLightsNodeInstanceServer(); + + void createScene(const CreateSceneCommand &command) override; + void view3DAction(const View3DActionCommand &command) override; + + void render(); + +protected: + void collectItemChangesAndSendChangeCommands() override; + void startRenderTimer() override; + void bakeLights(); + +private: + void abort(const QString &msg); + void runDenoiser(); + void finish(); + void cleanup(); + + QQuick3DViewport *m_view3D = nullptr; + bool m_bakingStarted = false; + int m_renderCount = 0; + QProcess *m_denoiser = nullptr; + QTemporaryDir m_workingDir; +#else +protected: + void collectItemChangesAndSendChangeCommands() override {}; +#endif +}; + +} // namespace QmlDesigner diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp index c5c6f6dc965..b0726b152a0 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp @@ -6,6 +6,7 @@ #include #include "capturenodeinstanceserverdispatcher.h" +#include "qt5bakelightsnodeinstanceserver.h" #include "qt5captureimagenodeinstanceserver.h" #include "qt5capturepreviewnodeinstanceserver.h" #include "qt5informationnodeinstanceserver.h" @@ -74,6 +75,9 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) : } else if (QCoreApplication::arguments().at(2) == QLatin1String("captureiconmode")) { setNodeInstanceServer(std::make_unique(this)); initializeSocket(); + } else if (QCoreApplication::arguments().at(2) == QLatin1String("bakelightsmode")) { + setNodeInstanceServer(std::make_unique(this)); + initializeSocket(); } } diff --git a/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h index b8e45491a8a..abb16d74bdf 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h +++ b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h @@ -57,6 +57,7 @@ using QHashValueType = size_t; friend class Qt4PreviewNodeInstanceServer; friend class Qt5InformationNodeInstanceServer; friend class Qt5NodeInstanceServer; + friend class Qt5BakeLightsNodeInstanceServer; friend class Qt5PreviewNodeInstanceServer; friend class Qt5CapturePreviewNodeInstanceServer; friend class Qt5TestNodeInstanceServer;