aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAli Kianian <[email protected]>2024-08-02 18:19:21 +0300
committerAli Kianian <[email protected]>2024-08-23 14:47:53 +0000
commitee78ccc7dc8fe4b8c7577f21d3232347f9c35b16 (patch)
tree917199be5de1f06b09823ac663bd7dd599f87f10
parent133554186e4888f623588131bc77bea9cc640a3e (diff)
QmlDesigner: Add a camera view to 3d editor view
Task-number: QDS-13275 Fixes: QDS-13352 Change-Id: I9b583a273a0aa7fc0d2c72b274fca243cc65546e Reviewed-by: Miikka Heikkinen <[email protected]>
-rw-r--r--src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h1
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt1
-rw-r--r--src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.cpp105
-rw-r--r--src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.h46
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp25
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.h8
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp50
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h1
-rw-r--r--src/tools/qml2puppet/editor3d_qt6.qrc1
-rw-r--r--src/tools/qml2puppet/mockfiles/qt6/CameraView.qml164
-rw-r--r--src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml37
-rw-r--r--src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp32
-rw-r--r--src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h14
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp34
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h1
15 files changed, 503 insertions, 17 deletions
diff --git a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h
index d5647a0740b..a05d9681f64 100644
--- a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h
+++ b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h
@@ -44,6 +44,7 @@ enum class View3DActionType {
ShowSelectionBox,
ShowIconGizmo,
ShowCameraFrustum,
+ CameraViewMode,
ShowParticleEmitter,
Edit3DParticleModeToggle,
ParticlesPlay,
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index a2e9fc943a7..7c2f81c10ab 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -652,6 +652,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/edit3d
SOURCES
+ cameraviewwidgetaction.cpp cameraviewwidgetaction.h
edit3dview.cpp edit3dview.h
edit3dviewconfig.h
edit3dwidget.cpp edit3dwidget.h
diff --git a/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.cpp b/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.cpp
new file mode 100644
index 00000000000..8f9e025dc0a
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.cpp
@@ -0,0 +1,105 @@
+// Copyright (C) 2024 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 "cameraviewwidgetaction.h"
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QComboBox>
+
+namespace QmlDesigner {
+
+struct CameraActionsModel::DataItem
+{
+ QString name;
+ QString tooltip;
+ QString mode;
+};
+
+const QList<CameraActionsModel::DataItem> CameraActionsModel::m_data{
+ {tr("Hide Camera View"), tr("Never show the camera view."), "CameraOff"},
+ {tr("Show Selected Camera View"),
+ tr("Show the selected camera in the camera view."),
+ "ShowSelectedCamera"},
+ {tr("Always Show Camera View"),
+ tr("Show the last selected camera in the camera view."),
+ "AlwaysShowCamera"},
+};
+
+CameraViewWidgetAction::CameraViewWidgetAction(QObject *parent)
+ : QWidgetAction(parent)
+{
+ QComboBox *defaultComboBox = new QComboBox();
+ CameraActionsModel *comboBoxModel = new CameraActionsModel(defaultComboBox);
+
+ defaultComboBox->setModel(comboBoxModel);
+ setDefaultWidget(defaultComboBox);
+ connect(defaultComboBox, &QComboBox::currentIndexChanged, this, [this] {
+ emit currentModeChanged(currentMode());
+ });
+}
+
+QString CameraViewWidgetAction::currentMode() const
+{
+ QComboBox *defaultComboBox = qobject_cast<QComboBox *>(defaultWidget());
+ QTC_ASSERT(defaultComboBox, return "CameraOff");
+
+ return defaultComboBox->currentData(CameraActionsModel::ModeRole).toString();
+}
+
+void CameraViewWidgetAction::setMode(const QString &mode)
+{
+ QComboBox *defaultComboBox = qobject_cast<QComboBox *>(defaultWidget());
+ QTC_ASSERT(defaultComboBox, return);
+ defaultComboBox->setCurrentIndex(CameraActionsModel::modeIndex(mode));
+}
+
+QWidget *CameraViewWidgetAction::createWidget(QWidget *parent)
+{
+ QComboBox *defaultComboBox = qobject_cast<QComboBox *>(defaultWidget());
+ QTC_ASSERT(defaultComboBox, return nullptr);
+
+ QComboBox *newComboBox = new QComboBox(parent);
+ newComboBox->setModel(defaultComboBox->model());
+ connect(defaultComboBox, &QComboBox::currentIndexChanged, newComboBox, &QComboBox::setCurrentIndex);
+ connect(newComboBox, &QComboBox::currentIndexChanged, defaultComboBox, &QComboBox::setCurrentIndex);
+ newComboBox->setCurrentIndex(defaultComboBox->currentIndex());
+ return newComboBox;
+}
+
+CameraActionsModel::CameraActionsModel(QObject *parent)
+ : QAbstractListModel(parent)
+{}
+
+CameraActionsModel::~CameraActionsModel() = default;
+
+int CameraActionsModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
+{
+ return m_data.size();
+}
+
+QVariant CameraActionsModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return {};
+
+ const DataItem &data = m_data.at(index.row());
+ switch (role) {
+ case Qt::DisplayRole:
+ return data.name;
+ case Qt::ToolTipRole:
+ return data.tooltip;
+ case ExtendedDataRoles::ModeRole:
+ return data.mode;
+ default:
+ return {};
+ }
+}
+
+int CameraActionsModel::modeIndex(const QString &mode)
+{
+ int idx = Utils::indexOf(m_data, Utils::equal(&DataItem::mode, mode));
+ return std::max(0, idx);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.h b/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.h
new file mode 100644
index 00000000000..e368a41b032
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/cameraviewwidgetaction.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2024 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 <QAbstractListModel>
+#include <QCoreApplication>
+#include <QWidgetAction>
+
+namespace QmlDesigner {
+
+class CameraViewWidgetAction : public QWidgetAction
+{
+ Q_OBJECT
+
+public:
+ explicit CameraViewWidgetAction(QObject *parent = nullptr);
+ QString currentMode() const;
+ void setMode(const QString &mode);
+
+protected:
+ QWidget *createWidget(QWidget *parent) override;
+
+signals:
+ void currentModeChanged(QString);
+};
+
+class CameraActionsModel : public QAbstractListModel
+{
+ Q_DECLARE_TR_FUNCTIONS(CameraActionsModel)
+
+public:
+ enum ExtendedDataRoles { ModeRole = Qt::UserRole + 1 };
+
+ explicit CameraActionsModel(QObject *parent);
+ virtual ~CameraActionsModel();
+
+ int rowCount(const QModelIndex &parent = {}) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ static int modeIndex(const QString &mode);
+
+private:
+ struct DataItem;
+ static const QList<DataItem> m_data;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
index 83299a485d5..272b5994193 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
@@ -3,6 +3,7 @@
#include "edit3dactions.h"
+#include "cameraviewwidgetaction.h"
#include "edit3dview.h"
#include "indicatoractionwidget.h"
#include "qmldesignerconstants.h"
@@ -11,6 +12,7 @@
#include <utils3d.h>
#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
namespace QmlDesigner {
@@ -198,4 +200,27 @@ bool Edit3DIndicatorButtonAction::isEnabled(const SelectionContext &) const
return m_buttonAction->isEnabled();
}
+Edit3DCameraViewAction::Edit3DCameraViewAction(const QByteArray &menuId,
+ View3DActionType type,
+ Edit3DView *view)
+ : Edit3DAction(menuId, type, view, new Edit3DWidgetActionTemplate(new CameraViewWidgetAction(view)))
+{
+ CameraViewWidgetAction *widgetAction = qobject_cast<CameraViewWidgetAction *>(action());
+ Q_ASSERT(widgetAction);
+
+ QObject::connect(widgetAction,
+ &CameraViewWidgetAction::currentModeChanged,
+ view,
+ [this, edit3dview = std::move(view)](const QString &newState) {
+ edit3dview->emitView3DAction(actionType(), newState);
+ });
+}
+
+void Edit3DCameraViewAction::setMode(const QString &mode)
+{
+ CameraViewWidgetAction *widgetAction = qobject_cast<CameraViewWidgetAction *>(action());
+ QTC_ASSERT(widgetAction, return);
+ widgetAction->setMode(mode);
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
index 03aeb22902a..63c9d3b41e8 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
@@ -150,4 +150,12 @@ private:
Edit3DView *m_view = nullptr;
};
+class Edit3DCameraViewAction : public Edit3DAction
+{
+public:
+ Edit3DCameraViewAction(const QByteArray &menuId, View3DActionType type, Edit3DView *view);
+
+ void setMode(const QString &mode);
+};
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index b971d828c50..9d9e9848ff0 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -45,6 +45,11 @@
#include <utils/utilsicons.h>
#include <QToolButton>
+static const QByteArray operator""_actionId(const char *text, size_t size)
+{
+ return QString("QmlDesigner.Edit3D.%1").arg(QLatin1String(text, size)).toLatin1();
+}
+
namespace QmlDesigner {
inline static QIcon contextIcon(const DesignerIcons::IconId &iconId)
@@ -127,23 +132,24 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
m_activeSplit = 0;
}
- const QString sceneKey = QStringLiteral("sceneInstanceId");
- const QString selectKey = QStringLiteral("selectionMode");
- const QString transformKey = QStringLiteral("transformMode");
- const QString perspectiveKey = QStringLiteral("usePerspective");
- const QString orientationKey = QStringLiteral("globalOrientation");
- const QString editLightKey = QStringLiteral("showEditLight");
- const QString gridKey = QStringLiteral("showGrid");
- const QString showLookAtKey = QStringLiteral("showLookAt");
- const QString selectionBoxKey = QStringLiteral("showSelectionBox");
- const QString iconGizmoKey = QStringLiteral("showIconGizmo");
- const QString cameraFrustumKey = QStringLiteral("showCameraFrustum");
- const QString particleEmitterKey = QStringLiteral("showParticleEmitter");
- const QString particlesPlayKey = QStringLiteral("particlePlay");
- const QString syncEnvBgKey = QStringLiteral("syncEnvBackground");
- const QString splitViewKey = QStringLiteral("splitView");
- const QString matOverrideKey = QStringLiteral("matOverride");
- const QString showWireframeKey = QStringLiteral("showWireframe");
+ const QString sceneKey = QStringLiteral("sceneInstanceId");
+ const QString selectKey = QStringLiteral("selectionMode");
+ const QString transformKey = QStringLiteral("transformMode");
+ const QString perspectiveKey = QStringLiteral("usePerspective");
+ const QString orientationKey = QStringLiteral("globalOrientation");
+ const QString editLightKey = QStringLiteral("showEditLight");
+ const QString gridKey = QStringLiteral("showGrid");
+ const QString showLookAtKey = QStringLiteral("showLookAt");
+ const QString selectionBoxKey = QStringLiteral("showSelectionBox");
+ const QString iconGizmoKey = QStringLiteral("showIconGizmo");
+ const QString cameraFrustumKey = QStringLiteral("showCameraFrustum");
+ const QString cameraViewModeKey = QStringLiteral("cameraViewMode");
+ const QString particleEmitterKey = QStringLiteral("showParticleEmitter");
+ const QString particlesPlayKey = QStringLiteral("particlePlay");
+ const QString syncEnvBgKey = QStringLiteral("syncEnvBackground");
+ const QString splitViewKey = QStringLiteral("splitView");
+ const QString matOverrideKey = QStringLiteral("matOverride");
+ const QString showWireframeKey = QStringLiteral("showWireframe");
if (sceneState.contains(sceneKey)) {
qint32 newActiveScene = sceneState[sceneKey].value<qint32>();
@@ -209,6 +215,11 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
else
m_showCameraFrustumAction->action()->setChecked(false);
+ if (sceneState.contains(cameraViewModeKey))
+ m_cameraViewAction->setMode(sceneState[cameraViewModeKey].toString());
+ else
+ m_cameraViewAction->setMode("");
+
if (sceneState.contains(particleEmitterKey))
m_showParticleEmitterAction->action()->setChecked(sceneState[particleEmitterKey].toBool());
else
@@ -1100,6 +1111,10 @@ void Edit3DView::createEdit3DActions()
"Toggle between always showing the camera frustum visualization and only showing it "
"when the camera is selected."));
+ m_cameraViewAction = std::make_unique<Edit3DCameraViewAction>("CamerView"_actionId,
+ View3DActionType::CameraViewMode,
+ this);
+
m_showParticleEmitterAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_PARTICLE_EMITTER,
View3DActionType::ShowParticleEmitter,
@@ -1368,6 +1383,7 @@ void Edit3DView::createEdit3DActions()
m_visibilityToggleActions << m_showSelectionBoxAction.get();
m_visibilityToggleActions << m_showIconGizmoAction.get();
m_visibilityToggleActions << m_showCameraFrustumAction.get();
+ m_visibilityToggleActions << m_cameraViewAction.get();
m_visibilityToggleActions << m_showParticleEmitterAction.get();
createSyncEnvBackgroundAction();
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index f0ebc69dddb..8560fd6b45a 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -177,6 +177,7 @@ private:
std::unique_ptr<Edit3DAction> m_showSelectionBoxAction;
std::unique_ptr<Edit3DAction> m_showIconGizmoAction;
std::unique_ptr<Edit3DAction> m_showCameraFrustumAction;
+ std::unique_ptr<Edit3DCameraViewAction> m_cameraViewAction;
std::unique_ptr<Edit3DAction> m_showParticleEmitterAction;
std::unique_ptr<Edit3DAction> m_particleViewModeAction;
std::unique_ptr<Edit3DAction> m_particlesPlayAction;
diff --git a/src/tools/qml2puppet/editor3d_qt6.qrc b/src/tools/qml2puppet/editor3d_qt6.qrc
index 85df241f162..e1de7a0903d 100644
--- a/src/tools/qml2puppet/editor3d_qt6.qrc
+++ b/src/tools/qml2puppet/editor3d_qt6.qrc
@@ -26,6 +26,7 @@
<file>mockfiles/qt6/AutoScaleHelper.qml</file>
<file>mockfiles/qt6/CameraFrustum.qml</file>
<file>mockfiles/qt6/CameraGizmo.qml</file>
+ <file>mockfiles/qt6/CameraView.qml</file>
<file>mockfiles/qt6/DirectionalDraggable.qml</file>
<file>mockfiles/qt6/EditCameraController.qml</file>
<file>mockfiles/qt6/EditView3D.qml</file>
diff --git a/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml b/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml
new file mode 100644
index 00000000000..3bc67468099
--- /dev/null
+++ b/src/tools/qml2puppet/mockfiles/qt6/CameraView.qml
@@ -0,0 +1,164 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+import QtQuick
+import QtQuick3D
+
+Item {
+ id: cameraView
+
+ required property bool showCameraView
+ required property bool alwaysOn
+ property bool snapLeft: true
+ property Node targetNode
+ property size preferredSize
+ property size viewPortSize
+ property var activeScene
+ property var activeSceneEnvironment
+ property var preferredCamera
+
+ width: loader.width
+ height: loader.height
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ visible: loader.active
+
+ onTargetNodeChanged: loader.updateCamera()
+ onAlwaysOnChanged: loader.updateCamera()
+ onPreferredCameraChanged: loader.updateCamera()
+ onActiveSceneChanged: forceReload()
+ Component.onCompleted: loader.updateCamera()
+
+ function forceReload() {
+ loader.forceDeactive = true
+ loader.oldCamera = null
+ loader.updateCamera()
+ loader.forceDeactive = false
+ }
+
+ Loader {
+ id: loader
+
+ property Camera camera
+ property Camera oldCamera
+ property bool forceDeactive: false
+
+ active: !forceDeactive && (cameraView.alwaysOn || cameraView.showCameraView) && loader.camera
+
+ function updateCamera() {
+ loader.camera = activeCamera()
+ }
+
+ function activeCamera() {
+ if (cameraView.alwaysOn) {
+ if (_generalHelper.isCamera(cameraView.targetNode))
+ return cameraView.targetNode
+ else if (loader.oldCamera)
+ return loader.oldCamera
+ else
+ return cameraView.preferredCamera
+ } else if (_generalHelper.isCamera(cameraView.targetNode)) {
+ return cameraView.targetNode
+ }
+ return null
+ }
+
+ onCameraChanged: {
+ if (loader.camera)
+ loader.oldCamera = loader.camera
+ }
+
+ sourceComponent: Rectangle {
+ id: cameraRect
+
+ implicitWidth: view3D.dispSize.width + 2
+ implicitHeight: view3D.dispSize.height + 2
+ border.width: 1
+ border.color: "lightslategray"
+ color: "black"
+
+ View3D {
+ id: view3D
+
+ readonly property bool isOrthographicCamera: _generalHelper.isOrthographicCamera(view3D.camera)
+ property size dispSize: calculateSize(cameraView.viewPortSize, cameraView.preferredSize)
+ readonly property real magnificationFactor: cameraView.viewPortSize.width === 0
+ ? 1.0
+ : (view3D.dispSize.width / cameraView.viewPortSize.width)
+
+ transformOrigin: Item.Center
+ anchors.centerIn: parent
+
+ camera: loader.camera
+ importScene: cameraView.activeScene
+ environment: cameraView.activeSceneEnvironment ?? defaultSceneEnvironment
+
+ function calculateSize(viewPortSize: size, preferredSize : size){
+ if (_generalHelper.fuzzyCompare(viewPortSize.width, 0)
+ || _generalHelper.fuzzyCompare(viewPortSize.height, 0))
+ return Qt.size(0, 0)
+
+ let aspectRatio = viewPortSize.height / viewPortSize.width
+ var calculatedHeight = preferredSize.width * aspectRatio
+ if (calculatedHeight <= preferredSize.height)
+ return Qt.size(preferredSize.width, calculatedHeight)
+
+ var calculatedWidth = preferredSize.height / aspectRatio;
+ return Qt.size(calculatedWidth, preferredSize.height);
+ }
+
+ states: [
+ State {
+ name: "orthoCamera"
+ when: view3D.isOrthographicCamera
+ PropertyChanges {
+ target: view3D
+
+ width: cameraView.viewPortSize.width
+ height: cameraView.viewPortSize.height
+ scale: view3D.magnificationFactor
+ }
+ },
+ State {
+ name: "nonOrthoCamera"
+ when: !view3D.isOrthographicCamera
+ PropertyChanges {
+ target: view3D
+
+ width: view3D.dispSize.width
+ height: view3D.dispSize.height
+ scale: 1.0
+ }
+ }
+ ]
+ }
+ }
+ }
+
+ SceneEnvironment {
+ id: defaultSceneEnvironment
+
+ antialiasingMode: SceneEnvironment.MSAA
+ antialiasingQuality: SceneEnvironment.High
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: cameraView.snapLeft
+ AnchorChanges {
+ target: cameraView
+ anchors.left: parent.left
+ anchors.right: undefined
+ }
+ },
+ State {
+ name: "snapRight"
+ when: !cameraView.snapLeft
+ AnchorChanges {
+ target: cameraView
+ anchors.left: undefined
+ anchors.right: parent.right
+ }
+ }
+ ]
+}
diff --git a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
index 751d21c0e8a..e159b532c34 100644
--- a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
+++ b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
@@ -40,6 +40,7 @@ Item {
property bool splitView: false
property bool flyMode: false
property bool showCameraSpeed: false
+ property string cameraViewMode
enum SelectionMode { Item, Group }
enum TransformMode { Move, Rotate, Scale }
@@ -72,6 +73,7 @@ Item {
onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox);
onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo);
onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum);
+ onCameraViewModeChanged: _generalHelper.storeToolState(sceneId, "cameraViewMode", cameraViewMode)
onShowParticleEmitterChanged: _generalHelper.storeToolState(sceneId, "showParticleEmitter", showParticleEmitter);
onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
@@ -334,6 +336,11 @@ Item {
else if (resetToDefault)
showCameraFrustum = false;
+ if ("cameraViewMode" in toolStates)
+ cameraViewMode = toolStates.cameraViewMode
+ else if (resetToDefault)
+ cameraViewMode = "CameraOff"
+
if ("showParticleEmitter" in toolStates)
showParticleEmitter = toolStates.showParticleEmitter;
else if (resetToDefault)
@@ -405,6 +412,7 @@ Item {
_generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox)
_generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo)
_generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum)
+ _generalHelper.storeToolState(sceneId, "cameraViewMode", cameraViewMode)
_generalHelper.storeToolState(sceneId, "showParticleEmitter", showParticleEmitter)
_generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
_generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
@@ -1083,6 +1091,35 @@ Item {
anchors.centerIn: parent
}
}
+
+ CameraView {
+ id: cameraView
+
+ showCameraView: viewRoot.cameraViewMode === "ShowSelectedCamera"
+ alwaysOn: viewRoot.cameraViewMode === "AlwaysShowCamera"
+ targetNode: viewRoot.selectedNode
+ activeScene: viewRoot.activeScene
+ activeSceneEnvironment: viewRoot.activeEditView.sceneEnv
+ preferredCamera: _generalHelper.activeScenePreferredCamera
+ preferredSize: Qt.size(viewRoot.width * 0.3, viewRoot.height * 0.3)
+ viewPortSize: Qt.size(viewRoot.viewPortRect.width, viewRoot.viewPortRect.height)
+
+ function updateSnapping() {
+ if (!viewRoot.splitView)
+ cameraView.snapLeft = true
+ else if (viewRoot.activeSplit === 2)
+ cameraView.snapLeft = false
+ else if (viewRoot.activeSplit === 3)
+ cameraView.snapLeft = true
+ }
+
+ Connections {
+ target: viewRoot
+
+ onSplitViewChanged: cameraView.updateSnapping()
+ onActiveSplitChanged: cameraView.updateSnapping()
+ }
+ }
}
Text {
diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
index 3baf91c1464..e58192e54f8 100644
--- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
@@ -682,6 +682,16 @@ bool GeneralHelper::isPickable(QQuick3DNode *node) const
return true;
}
+bool GeneralHelper::isCamera(QQuick3DNode *node) const
+{
+ return node && qobject_cast<QQuick3DCamera *>(node);
+}
+
+bool GeneralHelper::isOrthographicCamera(QQuick3DNode *node) const
+{
+ return node && qobject_cast<QQuick3DOrthographicCamera *>(node);
+}
+
// Emitter gizmo model creation is done in C++ as creating dynamic properties and
// assigning materials to dynamically created models is lot simpler in C++
QQuick3DNode *GeneralHelper::createParticleEmitterGizmoModel(QQuick3DNode *emitter,
@@ -1546,6 +1556,28 @@ void GeneralHelper::requestTimerEvent(const QString &timerId, qint64 delay)
}
}
+QQuick3DCamera *GeneralHelper::activeScenePreferredCamera() const
+{
+ return m_activeScenePreferredCamera.get();
+}
+
+void GeneralHelper::setActiveScenePreferredCamera(QQuick3DCamera *camera)
+{
+ if (m_activeScenePreferredCamera.get() != camera) {
+ if (m_activeScenePreferredCamera)
+ disconnect(m_activeScenePreferredCamera.get(), &QObject::destroyed, this, 0);
+
+ m_activeScenePreferredCamera = camera;
+
+ connect(
+ m_activeScenePreferredCamera.get(),
+ &QObject::destroyed,
+ this,
+ &GeneralHelper::requestActiveScenePreferredCamera);
+
+ emit activeScenePreferredCameraChanged();
+ }
+}
}
}
diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
index f1b57f4122f..4aa66bd7419 100644
--- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
+++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
@@ -40,6 +40,11 @@ class GeneralHelper : public QObject
Q_PROPERTY(double minGridStep READ minGridStep NOTIFY minGridStepChanged FINAL)
Q_PROPERTY(double cameraSpeed READ cameraSpeed NOTIFY cameraSpeedChanged FINAL)
+ Q_PROPERTY(
+ QQuick3DCamera *activeScenePreferredCamera
+ READ activeScenePreferredCamera
+ NOTIFY activeScenePreferredCameraChanged FINAL)
+
public:
GeneralHelper();
@@ -90,6 +95,8 @@ public:
Q_INVOKABLE bool isLocked(QQuick3DNode *node) const;
Q_INVOKABLE bool isHidden(QQuick3DNode *node) const;
Q_INVOKABLE bool isPickable(QQuick3DNode *node) const;
+ Q_INVOKABLE bool isCamera(QQuick3DNode *node) const;
+ Q_INVOKABLE bool isOrthographicCamera(QQuick3DNode *node) const;
Q_INVOKABLE QQuick3DNode *createParticleEmitterGizmoModel(QQuick3DNode *emitter,
QQuick3DMaterial *material) const;
@@ -168,6 +175,9 @@ public:
Q_INVOKABLE void requestTimerEvent(const QString &timerId, qint64 delay);
+ QQuick3DCamera *activeScenePreferredCamera() const;
+ void setActiveScenePreferredCamera(QQuick3DCamera *camera);
+
signals:
void overlayUpdateNeeded();
void toolStateChanged(const QString &sceneId, const QString &tool, const QVariant &toolState);
@@ -180,8 +190,10 @@ signals:
void sceneEnvDataChanged();
void requestCameraMove(QQuick3DCamera *camera, const QVector3D &moveVector);
void requestRender();
+ void requestActiveScenePreferredCamera();
void cameraSpeedChanged();
void requestedTimerEvent(const QString &timerId);
+ void activeScenePreferredCameraChanged();
private:
void handlePendingToolStateUpdate();
@@ -229,6 +241,8 @@ private:
QList<QMetaObject::Connection> m_multiSelectConnections;
bool m_blockMultiSelectionNodePositioning = false;
+ QPointer<QQuick3DCamera> m_activeScenePreferredCamera;
+
bool m_snapAbsolute = true;
bool m_snapPosition = false;
bool m_snapRotation = false;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index d81a0aa5644..39f29d5a9f5 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -300,6 +300,30 @@ void Qt5InformationNodeInstanceServer::resolveImportSupport()
#endif
}
+void Qt5InformationNodeInstanceServer::updateActiveScenePreferredCamera()
+{
+#ifdef QUICK3D_MODULE
+ auto preferredCamera = [&]() -> QQuick3DCamera * {
+ if (auto activeView = qobject_cast<QQuick3DViewport *>(m_active3DView)) {
+ if (auto camera = activeView->camera()) {
+ if (hasInstanceForObject(camera) && find3DSceneRoot(camera) == m_active3DScene)
+ return camera;
+ }
+ }
+
+ const QList<ServerNodeInstance> allCameras = allCameraInstances();
+ for (const auto &camera : allCameras) {
+ if (find3DSceneRoot(camera) == m_active3DScene)
+ return qobject_cast<QQuick3DCamera *>(camera.internalObject());
+ }
+ return nullptr;
+ };
+
+ auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
+ helper->setActiveScenePreferredCamera(preferredCamera());
+#endif
+}
+
void Qt5InformationNodeInstanceServer::updateMaterialPreviewData(
const QVector<PropertyValueContainer> &valueChanges)
{
@@ -535,6 +559,11 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::requestRender, this, [this]() {
render3DEditView(1);
});
+ QObject::connect(
+ helper,
+ &QmlDesigner::Internal::GeneralHelper::requestActiveScenePreferredCamera,
+ this,
+ &Qt5InformationNodeInstanceServer::updateActiveScenePreferredCamera);
engine()->rootContext()->setContextProperty("_generalHelper", helper);
engine()->addImageProvider(QLatin1String("IconGizmoImageProvider"),
new QmlDesigner::Internal::IconGizmoImageProvider);
@@ -1035,6 +1064,8 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D([[maybe_unu
activeSceneVar = objectToVariant(sceneRoot);
}
+ updateActiveScenePreferredCamera();
+
QMetaObject::invokeMethod(m_editView3DData.rootItem, "setActiveScene", Qt::QueuedConnection,
Q_ARG(QVariant, activeSceneVar),
Q_ARG(QVariant, QVariant::fromValue(sceneId)));
@@ -2549,6 +2580,9 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
case View3DActionType::ShowCameraFrustum:
updatedToolState.insert("showCameraFrustum", command.isEnabled());
break;
+ case View3DActionType::CameraViewMode:
+ updatedToolState.insert("cameraViewMode", command.value());
+ break;
case View3DActionType::SyncEnvBackground:
updatedToolState.insert("syncEnvBackground", command.isEnabled());
break;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index 321751cf238..60eebe488ae 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -122,6 +122,7 @@ private:
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
void handleInputEvents();
void resolveImportSupport();
+ void updateActiveScenePreferredCamera();
void updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges);
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
void updateSnapAndCameraSettings(const QVector<PropertyValueContainer> &valueChanges);