From 4c7e6c699264bc37100f43c00e08027e9f06518f Mon Sep 17 00:00:00 2001 From: Amr Essam Date: Mon, 31 Mar 2025 14:31:04 +0300 Subject: [PATCH] QmlDesigner: Add preset layout options for 3D View Task-number: QDS-14907 Change-Id: I0937a64dc1820727178372663e2913f2c2239f10 Reviewed-by: Mahmoud Badri --- .../commands/puppettocreatorcommand.h | 2 +- .../interfaces/nodeinstanceglobal.h | 3 +- .../components/edit3d/edit3dcanvas.cpp | 10 +- .../components/edit3d/edit3dview.cpp | 132 +++++--- .../components/edit3d/edit3dview.h | 28 +- .../components/edit3d/edit3dwidget.cpp | 47 ++- .../components/edit3d/edit3dwidget.h | 4 + .../instances/nodeinstanceview.cpp | 10 +- .../qmldesigner/qmldesignerconstants.h | 8 + .../mockfiles/qt6/EditCameraController.qml | 26 +- .../qmlpuppet/mockfiles/qt6/EditView3D.qml | 302 ++++++++++-------- .../qmlpuppet/mockfiles/qt6/OverlayView3D.qml | 4 +- .../qt5informationnodeinstanceserver.cpp | 15 +- .../qt5informationnodeinstanceserver.h | 2 +- 14 files changed, 364 insertions(+), 229 deletions(-) diff --git a/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h index a8f37a81e53..44d68f9ed29 100644 --- a/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h +++ b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h @@ -16,7 +16,7 @@ public: Edit3DToolState, Render3DView, ActiveSceneChanged, - ActiveSplitChanged, + ActiveViewportChanged, RenderModelNodePreviewImage, Import3DPreviewIcon, Import3DPreviewImage, diff --git a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h index a05d9681f64..8b25001f83e 100644 --- a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h +++ b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h @@ -51,10 +51,11 @@ enum class View3DActionType { ParticlesRestart, ParticlesSeek, SyncEnvBackground, + ViewportPreset, GetNodeAtPos, GetNodeAtMainScenePos, SetBakeLightsView3D, - SplitViewToggle, + ViewportViewToggle, MaterialOverride, ShowWireframe, FlyModeToggle, diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp index a0ac71a9399..3545c218a54 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp @@ -98,11 +98,11 @@ void Edit3DCanvas::setFlyMode(bool enabled, const QPoint &pos) m_flyModeStartCursorPos = pos; m_flyModeFirstUpdate = true; - // Hide cursor on the middle of the active split to make the wheel work during flight mode. - // We can't rely on current activeSplit value, as mouse press to enter flight mode can change the - // active split, so hide the cursor based on its current location. + // Hide cursor on the middle of the active viewport to make the wheel work during flight mode. + // We can't rely on current activeViewport value, as mouse press to enter flight mode can change the + // active viewport, so hide the cursor based on its current location. QPoint center = mapToGlobal(QPoint(width() / 2, height() / 2)); - if (m_parent->view()->isSplitView()) { + if (m_parent->view()->isMultiViewportView()) { if (pos.x() <= center.x()) { if (pos.y() <= center.y()) m_hiddenCursorPos = mapToGlobal(QPoint(width() / 4, height() / 4)); @@ -192,7 +192,7 @@ void Edit3DCanvas::mouseMoveEvent(QMouseEvent *e) if (!m_flyModeFirstUpdate) { // We notify explicit camera rotation needs for QML Puppet rather than relying on mouse events, // as mouse isn't grabbed on QML Puppet side and can't handle fast movements that go out of - // edit camera mouse area. This also simplifies split view handling. + // edit camera mouse area. This also simplifies viewport view handling. QPointF diff = m_isQDSTrusted ? (m_hiddenCursorPos - globalPos) : (m_lastCursorPos - e->globalPosition().toPoint()); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 11edda9005e..37c9c66f542 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -73,7 +73,7 @@ Edit3DView::Edit3DView(ExternalDependenciesInterface &externalDependencies) connect(&m_compressionTimer, &QTimer::timeout, this, &Edit3DView::handleEntriesChanged); for (int i = 0; i < 4; ++i) - m_splitToolStates.append({0, false, i == 0}); + m_viewportToolStates.append({0, false, i == 0}); } void Edit3DView::createEdit3DWidget() @@ -120,15 +120,15 @@ void Edit3DView::renderImage3DChanged(const QImage &img) void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) { - const QString activeSplitKey = QStringLiteral("activeSplit"); - if (sceneState.contains(activeSplitKey)) { - setActiveSplit(sceneState[activeSplitKey].toInt()); - // If the sceneState contained just activeSplit key, then this is simply an active split + const QString activeViewportKey = QStringLiteral("activeViewport"); + if (sceneState.contains(activeViewportKey)) { + setActiveViewport(sceneState[activeViewportKey].toInt()); + // If the sceneState contained just activeViewport key, then this is simply an active Viewport // change rather than entire active scene change, and we don't need to process further. if (sceneState.size() == 1) return; } else { - setActiveSplit(0); + setActiveViewport(0); } const QString sceneKey = QStringLiteral("sceneInstanceId"); @@ -146,7 +146,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) const QString particleEmitterKey = QStringLiteral("showParticleEmitter"); const QString particlesPlayKey = QStringLiteral("particlePlay"); const QString syncEnvBgKey = QStringLiteral("syncEnvBackground"); - const QString splitViewKey = QStringLiteral("splitView"); + const QString activePresetKey = QStringLiteral("activePreset"); const QString matOverrideKey = QStringLiteral("matOverride"); const QString showWireframeKey = QStringLiteral("showWireframe"); @@ -177,10 +177,10 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) if (sceneState.contains(perspectiveKey)) { const QVariantList showList = sceneState[perspectiveKey].toList(); for (int i = 0; i < 4; ++i) - m_splitToolStates[i].isPerspective = i < showList.size() ? showList[i].toBool() : i == 0; + m_viewportToolStates[i].isPerspective = i < showList.size() ? showList[i].toBool() : i == 0; } else { for (int i = 0; i < 4; ++i) { - SplitToolState &state = m_splitToolStates[i]; + ViewportToolState &state = m_viewportToolStates[i]; state.isPerspective = i == 0; } } @@ -235,26 +235,21 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) else m_particlesPlayAction->action()->setChecked(true); - if (sceneState.contains(splitViewKey)) - m_splitViewAction->action()->setChecked(sceneState[splitViewKey].toBool()); - else - m_splitViewAction->action()->setChecked(false); - if (sceneState.contains(matOverrideKey)) { const QVariantList overrides = sceneState[matOverrideKey].toList(); for (int i = 0; i < 4; ++i) - m_splitToolStates[i].matOverride = i < overrides.size() ? overrides[i].toInt() : 0; + m_viewportToolStates[i].matOverride = i < overrides.size() ? overrides[i].toInt() : 0; } else { - for (SplitToolState &state : m_splitToolStates) + for (ViewportToolState &state : m_viewportToolStates) state.matOverride = 0; } if (sceneState.contains(showWireframeKey)) { const QVariantList showList = sceneState[showWireframeKey].toList(); for (int i = 0; i < 4; ++i) - m_splitToolStates[i].showWireframe = i < showList.size() ? showList[i].toBool() : false; + m_viewportToolStates[i].showWireframe = i < showList.size() ? showList[i].toBool() : false; } else { - for (SplitToolState &state : m_splitToolStates) + for (ViewportToolState &state : m_viewportToolStates) state.showWireframe = false; } @@ -274,10 +269,10 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) storeCurrentSceneEnvironment(); } -void Edit3DView::setActiveSplit(int split) +void Edit3DView::setActiveViewport(int viewport) { - m_activeSplit = split; - m_cameraModeAction->action()->setChecked(m_splitToolStates[m_activeSplit].isPerspective); + m_activeViewport = viewport; + m_cameraModeAction->action()->setChecked(m_viewportToolStates[m_activeViewport].isPerspective); } void Edit3DView::modelAttached(Model *model) @@ -709,6 +704,45 @@ void Edit3DView::createSyncEnvBackgroundAction() tooltip); } +void Edit3DView::createViewportPresetActions() +{ + auto createViewportPresetAction = [this](std::unique_ptr &targetAction, + const QByteArray &id, + const QString &label, + bool isChecked) { + auto operation = [this, &targetAction, label](const SelectionContext &) { + for (Edit3DAction *action : std::as_const(m_viewportPresetActions)) { + if (action->menuId() != targetAction->menuId()) + action->action()->setChecked(false); + } + emitView3DAction(View3DActionType::ViewportPreset, label); + }; + + targetAction = std::make_unique( + id, + View3DActionType::Empty, + label, + QKeySequence(), + true, + isChecked, + QIcon(), + this, + operation); + }; + + createViewportPresetAction(m_viewportPresetSingleAction, Constants::EDIT3D_PRESET_SINGLE, "Single", true); + createViewportPresetAction(m_viewportPresetQuadAction, Constants::EDIT3D_PRESET_QUAD, "Quad", false); + createViewportPresetAction(m_viewportPreset3Left1RightAction, Constants::EDIT3D_PRESET_3LEFT1RIGHT, "3Left1Right", false); + createViewportPresetAction(m_viewportPreset2HorizontalAction, Constants::EDIT3D_PRESET_2HORIZONTAL, "2Horizontal", false); + createViewportPresetAction(m_viewportPreset2VerticalAction, Constants::EDIT3D_PRESET_2VERTICAL, "2Vertical", false); + + m_viewportPresetActions << m_viewportPresetSingleAction.get(); + m_viewportPresetActions << m_viewportPresetQuadAction.get(); + m_viewportPresetActions << m_viewportPreset3Left1RightAction.get(); + m_viewportPresetActions << m_viewportPreset2HorizontalAction.get(); + m_viewportPresetActions << m_viewportPreset2VerticalAction.get(); +} + void Edit3DView::createSeekerSliderAction() { m_seekerAction = std::make_unique( @@ -930,27 +964,27 @@ void Edit3DView::storeCurrentSceneEnvironment() } } -const QList &Edit3DView::splitToolStates() const +const QList &Edit3DView::viewportToolStates() const { - return m_splitToolStates; + return m_viewportToolStates; } -void Edit3DView::setSplitToolState(int splitIndex, const SplitToolState &state) +void Edit3DView::setViewportToolState(int viewportIndex, const ViewportToolState &state) { - if (splitIndex >= m_splitToolStates.size()) + if (viewportIndex >= m_viewportToolStates.size()) return; - m_splitToolStates[splitIndex] = state; + m_viewportToolStates[viewportIndex] = state; } -int Edit3DView::activeSplit() const +int Edit3DView::activeViewport() const { - return m_activeSplit; + return m_activeViewport; } -bool Edit3DView::isSplitView() const +bool Edit3DView::isMultiViewportView() const { - return m_splitViewAction->action()->isChecked(); + return m_viewportPresetsMenuAction->action()->isChecked(); } void Edit3DView::createEdit3DActions() @@ -1022,12 +1056,12 @@ void Edit3DView::createEdit3DActions() SelectionContextOperation cameraModeTrigger = [this](const SelectionContext &) { QVariantList list; - for (int i = 0; i < m_splitToolStates.size(); ++i) { - Edit3DView::SplitToolState state = m_splitToolStates[i]; - if (i == m_activeSplit) { + for (int i = 0; i < m_viewportToolStates.size(); ++i) { + Edit3DView::ViewportToolState state = m_viewportToolStates[i]; + if (i == m_activeViewport) { bool isChecked = m_cameraModeAction->action()->isChecked(); state.isPerspective = isChecked; - setSplitToolState(i, state); + setViewportToolState(i, state); list.append(isChecked); } else { list.append(state.isPerspective); @@ -1315,14 +1349,24 @@ void Edit3DView::createEdit3DActions() this, snapConfigTrigger); - m_splitViewAction = std::make_unique(QmlDesigner::Constants::EDIT3D_SPLIT_VIEW, - View3DActionType::SplitViewToggle, - Tr::tr("Toggle Split View On/Off"), - QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Q), - true, + SelectionContextOperation viewportPresetsActionTrigger = [this](const SelectionContext &) { + if (!edit3DWidget()->viewportPresetsMenu()) + return; + + edit3DWidget()->showViewportPresetsMenu( + !edit3DWidget()->viewportPresetsMenu()->isVisible(), + resolveToolbarPopupPos(m_viewportPresetsMenuAction.get())); + }; + + m_viewportPresetsMenuAction = std::make_unique(QmlDesigner::Constants::EDIT3D_PRESETS, + View3DActionType::Empty, + Tr::tr("Show Viewport Modes"), + QKeySequence(), + false, false, toolbarIcon(DesignerIcons::SplitViewIcon), - this); + this, + viewportPresetsActionTrigger); SelectionContextOperation cameraSpeedConfigTrigger = [this](const SelectionContext &) { if (!m_cameraSpeedConfiguration) { @@ -1372,7 +1416,7 @@ void Edit3DView::createEdit3DActions() m_leftActions << nullptr; m_leftActions << m_visibilityTogglesAction.get(); m_leftActions << m_backgroundColorMenuAction.get(); - m_leftActions << m_splitViewAction.get(); + m_leftActions << m_viewportPresetsMenuAction.get(); m_rightActions << m_particleViewModeAction.get(); m_rightActions << m_particlesPlayAction.get(); @@ -1400,6 +1444,8 @@ void Edit3DView::createEdit3DActions() m_backgroundColorActions << m_selectGridColorAction.get(); m_backgroundColorActions << m_syncEnvBackgroundAction.get(); m_backgroundColorActions << m_resetColorAction.get(); + + createViewportPresetActions(); } QVector Edit3DView::leftActions() const @@ -1422,6 +1468,10 @@ QVector Edit3DView::backgroundColorActions() const return m_backgroundColorActions; } +QVector Edit3DView::viewportPresetActions() const +{ + return m_viewportPresetActions; +} Edit3DAction *Edit3DView::edit3DAction(View3DActionType type) const { diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index 0cc421c8566..1c5d478357d 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -39,7 +39,7 @@ class QMLDESIGNERCOMPONENTS_EXPORT Edit3DView : public AbstractView Q_OBJECT public: - struct SplitToolState + struct ViewportToolState { int matOverride = 0; bool showWireframe = false; @@ -92,6 +92,7 @@ public: QVector rightActions() const; QVector visibilityToggleActions() const; QVector backgroundColorActions() const; + QVector viewportPresetActions() const; Edit3DAction *edit3DAction(View3DActionType type) const; Edit3DBakeLightsAction *bakeLightsAction() const; @@ -110,11 +111,11 @@ public: void setCameraSpeedAuxData(double speed, double multiplier); void getCameraSpeedAuxData(double &speed, double &multiplier); - const QList &splitToolStates() const; - void setSplitToolState(int splitIndex, const SplitToolState &state); + const QList &viewportToolStates() const; + void setViewportToolState(int viewportIndex, const ViewportToolState &state); - int activeSplit() const; - bool isSplitView() const; + int activeViewport() const; + bool isMultiViewportView() const; void setFlyMode(bool enabled); void emitView3DAction(View3DActionType type, const QVariant &value); @@ -147,12 +148,13 @@ private: void createGridColorSelectionAction(); void createResetColorAction(QAction *syncEnvBackgroundAction); void createSyncEnvBackgroundAction(); + void createViewportPresetActions(); void createSeekerSliderAction(); void syncCameraSpeedToNewView(); QmlObjectNode currentSceneEnv(); void storeCurrentSceneEnvironment(); - void setActiveSplit(int split); + void setActiveViewport(int viewportIndex); QPoint resolveToolbarPopupPos(Edit3DAction *action) const; @@ -164,6 +166,7 @@ private: QVector m_rightActions; QVector m_visibilityToggleActions; QVector m_backgroundColorActions; + QVector m_viewportPresetActions; QMap m_edit3DActions; std::unique_ptr m_selectionModeAction; @@ -191,7 +194,14 @@ private: std::unique_ptr m_selectBackgroundColorAction; std::unique_ptr m_selectGridColorAction; std::unique_ptr m_resetColorAction; - std::unique_ptr m_splitViewAction; + + // Viewport presets actions + std::unique_ptr m_viewportPresetSingleAction; + std::unique_ptr m_viewportPresetQuadAction; + std::unique_ptr m_viewportPreset3Left1RightAction; + std::unique_ptr m_viewportPreset2HorizontalAction; + std::unique_ptr m_viewportPreset2VerticalAction; + std::unique_ptr m_viewportPresetsMenuAction; // View3DActionType::Empty actions std::unique_ptr m_resetAction; @@ -216,9 +226,9 @@ private: bool m_isBakingLightsSupported = false; QPointer m_snapConfiguration; QPointer m_cameraSpeedConfiguration; - int m_activeSplit = 0; + int m_activeViewport = 0; - QList m_splitToolStates; + QList m_viewportToolStates; ModelNode m_contextMenuPendingNode; ModelNode m_pickView3dNode; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 12e7588c093..8f8071171b4 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -179,6 +179,10 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) handleActions(view->backgroundColorActions(), m_backgroundColorMenu, false); + m_viewportPresetsMenu = new QMenu(this); + m_viewportPresetsMenu->setToolTipsVisible(true); + handleActions(view->viewportPresetActions(), m_viewportPresetsMenu, false); + createContextMenu(); // Onboarding label contains instructions for new users how to get 3D content into the project @@ -568,11 +572,11 @@ void Edit3DWidget::onMatOverrideAction(QAction *action) return; QVariantList list; - for (int i = 0; i < m_view->splitToolStates().size(); ++i) { - Edit3DView::SplitToolState state = m_view->splitToolStates()[i]; - if (i == m_view->activeSplit()) { + for (int i = 0; i < m_view->viewportToolStates().size(); ++i) { + Edit3DView::ViewportToolState state = m_view->viewportToolStates()[i]; + if (i == m_view->activeViewport()) { state.matOverride = action->data().toInt(); - m_view->setSplitToolState(i, state); + m_view->setViewportToolState(i, state); list.append(action->data()); } else { list.append(state.matOverride); @@ -588,11 +592,11 @@ void Edit3DWidget::onWireframeAction() return; QVariantList list; - for (int i = 0; i < m_view->splitToolStates().size(); ++i) { - Edit3DView::SplitToolState state = m_view->splitToolStates()[i]; - if (i == m_view->activeSplit()) { + for (int i = 0; i < m_view->viewportToolStates().size(); ++i) { + Edit3DView::ViewportToolState state = m_view->viewportToolStates()[i]; + if (i == m_view->activeViewport()) { state.showWireframe = m_wireFrameAction->isChecked(); - m_view->setSplitToolState(i, state); + m_view->setViewportToolState(i, state); list.append(m_wireFrameAction->isChecked()); } else { list.append(state.showWireframe); @@ -610,11 +614,11 @@ void Edit3DWidget::onResetAllOverridesAction() QVariantList wList; QVariantList mList; - for (int i = 0; i < m_view->splitToolStates().size(); ++i) { - Edit3DView::SplitToolState state; + for (int i = 0; i < m_view->viewportToolStates().size(); ++i) { + Edit3DView::ViewportToolState state; state.showWireframe = false; state.matOverride = 0; - m_view->setSplitToolState(i, state); + m_view->setViewportToolState(i, state); wList.append(state.showWireframe); mList.append(state.matOverride); } @@ -675,6 +679,21 @@ void Edit3DWidget::showBackgroundColorMenu(bool show, const QPoint &pos) m_backgroundColorMenu->close(); } +QMenu *Edit3DWidget::viewportPresetsMenu() const +{ + return m_viewportPresetsMenu.data(); +} + +void Edit3DWidget::showViewportPresetsMenu(bool show, const QPoint &pos) +{ + if (m_viewportPresetsMenu.isNull()) + return; + if (show) + m_viewportPresetsMenu->popup(pos); + else + m_viewportPresetsMenu->close(); +} + void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d) { auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); @@ -711,11 +730,11 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_materialsAction->updateMenu(view()->selectedModelNodes()); if (m_view) { - int idx = m_view->activeSplit(); - m_wireFrameAction->setChecked(m_view->splitToolStates()[idx].showWireframe); + int idx = m_view->activeViewport(); + m_wireFrameAction->setChecked(m_view->viewportToolStates()[idx].showWireframe); for (QAction *a : std::as_const(m_matOverrideActions)) a->setChecked(false); - int type = m_view->splitToolStates()[idx].matOverride; + int type = m_view->viewportToolStates()[idx].matOverride; m_matOverrideActions[type]->setChecked(true); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 9b286699977..bc5a1b20d60 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -58,6 +58,9 @@ public: QMenu *backgroundColorMenu() const; void showBackgroundColorMenu(bool show, const QPoint &pos); + QMenu *viewportPresetsMenu() const; + void showViewportPresetsMenu(bool show, const QPoint &pos); + void showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d); void updateCreateSubMenu(const QList &entriesList); @@ -91,6 +94,7 @@ private: Core::IContext *m_context = nullptr; QPointer m_visibilityTogglesMenu; QPointer m_backgroundColorMenu; + QPointer m_viewportPresetsMenu; QPointer m_contextMenu; QPointer m_bakeLightsAction; QPointer m_editComponentAction; diff --git a/src/plugins/qmldesigner/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/instances/nodeinstanceview.cpp index 6a16f65d83a..776541ec5ca 100644 --- a/src/plugins/qmldesigner/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/instances/nodeinstanceview.cpp @@ -1811,12 +1811,12 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand const auto sceneState = qvariant_cast(command.data()); if (isAttached()) model()->emitUpdateActiveScene3D(this, sceneState); - } else if (command.type() == PuppetToCreatorCommand::ActiveSplitChanged) { - // Active split change is a special case of active scene change - QVariantMap splitState; - splitState.insert("activeSplit", command.data()); + } else if (command.type() == PuppetToCreatorCommand::ActiveViewportChanged) { + // Active viewport change is a special case of active scene change + QVariantMap viewportState; + viewportState.insert("activeViewport", command.data()); if (isAttached()) - model()->emitUpdateActiveScene3D(this, splitState); + model()->emitUpdateActiveScene3D(this, viewportState); } else if (command.type() == PuppetToCreatorCommand::RenderModelNodePreviewImage) { ImageContainer container = qvariant_cast(command.data()); QImage image = container.image(); diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 7bde8178caa..8b1e89c4c78 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -44,6 +44,14 @@ inline constexpr char EDIT3D_EDIT_SHOW_CAMERA_FRUSTUM[] = "QmlDesigner.Editor3D.ToggleCameraFrustum"; inline constexpr char EDIT3D_EDIT_SHOW_PARTICLE_EMITTER[] = "QmlDesigner.Editor3D.ToggleParticleEmitter"; + +inline constexpr char EDIT3D_PRESETS[] = "QmlDesigner.Editor3D.Presets"; +inline constexpr char EDIT3D_PRESET_SINGLE[] = "QmlDesigner.Editor3D.Single"; +inline constexpr char EDIT3D_PRESET_QUAD[] = "QmlDesigner.Editor3D.Quad"; +inline constexpr char EDIT3D_PRESET_3LEFT1RIGHT[] = "QmlDesigner.Editor3D.3Left1Right"; +inline constexpr char EDIT3D_PRESET_2HORIZONTAL[] = "QmlDesigner.Editor3D.2Horizontal"; +inline constexpr char EDIT3D_PRESET_2VERTICAL[] = "QmlDesigner.Editor3D.2Vertical"; + inline constexpr char EDIT3D_RESET_VIEW[] = "QmlDesigner.Editor3D.ResetView"; inline constexpr char EDIT3D_PARTICLE_MODE[] = "QmlDesigner.Editor3D.ParticleViewModeToggle"; inline constexpr char EDIT3D_PARTICLES_PLAY[] = "QmlDesigner.Editor3D.ParticlesPlay"; diff --git a/src/tools/qmlpuppet/mockfiles/qt6/EditCameraController.qml b/src/tools/qmlpuppet/mockfiles/qt6/EditCameraController.qml index 27f1f717034..6ef65c9718c 100644 --- a/src/tools/qmlpuppet/mockfiles/qt6/EditCameraController.qml +++ b/src/tools/qmlpuppet/mockfiles/qt6/EditCameraController.qml @@ -8,9 +8,9 @@ Item { id: cameraCtrl property var viewRoot: null - property int splitId: -1 + property int viewportId: -1 property Camera camera: view3d ? view3d.camera : null - property View3D view3d: viewRoot.editViews[splitId] + property View3D view3d: viewRoot.editViews[viewportId] property string sceneId: viewRoot.sceneId property vector3d _lookAtPoint property vector3d _pressPoint @@ -55,11 +55,11 @@ Item { _lookAtPoint = Qt.vector3d(0, 0, 0); _zoomFactor = 1; - if (splitId === 1) { + if (viewportId === 1) { jumpToRotation(originGizmo.quaternionForAxis(OriginGizmo.PositiveZ)); - } else if (splitId === 2) { + } else if (viewportId === 2) { jumpToRotation(originGizmo.quaternionForAxis(OriginGizmo.NegativeY)); - } else if (splitId === 3) { + } else if (viewportId === 3) { jumpToRotation(originGizmo.quaternionForAxis(OriginGizmo.NegativeX)); } else { camera.position = _defaultCameraPosition; @@ -79,7 +79,7 @@ Item { cameraState[1] = _zoomFactor; cameraState[2] = camera.position; cameraState[3] = camera.rotation; - _generalHelper.storeToolState(sceneId, "editCamState" + splitId, cameraState, delay); + _generalHelper.storeToolState(sceneId, "editCamState" + viewportId, cameraState, delay); } function focusObject(targetNodes, rotation, updateZoom, closeUp) @@ -254,12 +254,12 @@ Item { } on_LookAtPointChanged: { - viewRoot.overlayViews[splitId].lookAtGizmo.position = _lookAtPoint; + viewRoot.overlayViews[viewportId].lookAtGizmo.position = _lookAtPoint; } Connections { target: _generalHelper - enabled: viewRoot.activeSplit === cameraCtrl.splitId + enabled: viewRoot.activeViewport === cameraCtrl.viewportId function onRequestCameraMove(camera, moveVec) { if (camera === cameraCtrl.camera) { @@ -272,7 +272,7 @@ Item { Image { anchors.centerIn: parent source: "qrc:///qtquickplugin/mockfiles/images/crosshair.png" - visible: cameraCtrl.showCrosshairs && viewRoot.activeSplit === cameraCtrl.splitId + visible: cameraCtrl.showCrosshairs && viewRoot.activeViewport === cameraCtrl.viewportId opacity: 0.7 } @@ -303,7 +303,7 @@ Item { onPressed: (mouse) => { if (cameraCtrl.flyMode) return; - viewRoot.activeSplit = cameraCtrl.splitId + viewRoot.activeViewport = cameraCtrl.viewportId if (cameraCtrl.camera && (mouse.modifiers & (Qt.AltModifier | Qt.ShiftModifier))) { cameraCtrl._dragging = true; cameraCtrl._startRotation = cameraCtrl.camera.eulerRotation; @@ -328,9 +328,9 @@ Item { onCanceled: handleRelease() onWheel: (wheel) => { - if (cameraCtrl.flyMode && cameraCtrl.splitId !== viewRoot.activeSplit) + if (cameraCtrl.flyMode && cameraCtrl.viewportId !== viewRoot.activeViewport) return; - viewRoot.activeSplit = cameraCtrl.splitId; + viewRoot.activeViewport = cameraCtrl.viewportId; if (cameraCtrl.camera) { // Empirically determined divisor for nice zoom cameraCtrl.zoomRelative(wheel.angleDelta.y / -40); @@ -373,7 +373,7 @@ Item { targetNode: cameraCtrl.camera onAxisClicked: (axis) => { - viewRoot.activeSplit = cameraCtrl.splitId + viewRoot.activeViewport = cameraCtrl.viewportId cameraCtrl.jumpToRotation(quaternionForAxis(axis)); } } diff --git a/src/tools/qmlpuppet/mockfiles/qt6/EditView3D.qml b/src/tools/qmlpuppet/mockfiles/qt6/EditView3D.qml index f3a60c53020..2d4edbe033c 100644 --- a/src/tools/qmlpuppet/mockfiles/qt6/EditView3D.qml +++ b/src/tools/qmlpuppet/mockfiles/qt6/EditView3D.qml @@ -12,7 +12,7 @@ Item { visible: true property Node activeScene: null - property int activeSplit: 0 + property int activeViewport: 0 property var editViews: [null, null, null, null] property var usePerspective: [true, false, false, false] property var overlayViews: [overlayView0, overlayView1, overlayView2, overlayView3] @@ -21,8 +21,8 @@ Item { property var materialOverrides: [DebugSettings.None, DebugSettings.None, DebugSettings.None, DebugSettings.None] property var showWireframes: [false, false, false, false] - property var activeEditView: editViews[activeSplit] - property var activeOverlayView: overlayViews[activeSplit] + property var activeEditView: editViews[activeViewport] + property var activeOverlayView: overlayViews[activeViewport] property string sceneId property bool showEditLight: false @@ -37,12 +37,56 @@ Item { property color backgroundGradientColorStart: "#222222" property color backgroundGradientColorEnd: "#999999" property color gridColor: "#cccccc" + property color viewportBorderColor: "#aaaaaaaa" property bool syncEnvBackground: true - property bool splitView: false + property string activePreset: "Single" property bool flyMode: false property bool showCameraSpeed: false property string cameraViewMode + // The presets used to customize the display of the viewports + property var viewportPresets: { + "Single": { + numViewports: 1, + viewRects: [ + { x: 0.0, y: 0.0, width: 1.0, height: 1.0 } + ] + }, + "Quad": { + numViewports: 4, + viewRects: [ + { x: 0.0, y: 0.0, width: 0.5, height: 0.5 }, + { x: 0.5, y: 0.0, width: 0.5, height: 0.5 }, + { x: 0.0, y: 0.5, width: 0.5, height: 0.5 }, + { x: 0.5, y: 0.5, width: 0.5, height: 0.5 } + ] + }, + "3Left1Right": { + numViewports: 4, + viewRects: [ + { x: 0.0, y: 0.0, width: 0.25, height: 0.33 }, + { x: 0.0, y: 0.33, width: 0.25, height: 0.34 }, + { x: 0.0, y: 0.67, width: 0.25, height: 0.33 }, + { x: 0.25, y: 0.0, width: 0.75, height: 1.0 } + ] + }, + "2Horizontal": { + numViewports: 2, + viewRects: [ + { x: 0.0, y: 0.0, width: 1.0, height: 0.5 }, + { x: 0.0, y: 0.5, width: 1.0, height: 0.5 } + ] + }, + "2Vertical": { + numViewports: 2, + viewRects: [ + { x: 0.0, y: 0.0, width: 0.5, height: 1.0 }, + { x: 0.5, y: 0.0, width: 0.5, height: 1.0 } + ] + } + //TODO: reset of presets + }; + enum SelectionMode { Item, Group } enum TransformMode { Move, Rotate, Scale } @@ -64,7 +108,7 @@ Item { signal commitObjectProperty(var objects, var propNames) signal changeObjectProperty(var objects, var propNames) signal notifyActiveSceneChange() - signal notifyActiveSplitChange(int index) + signal notifyActiveViewportChange(int index) onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) @@ -81,14 +125,14 @@ Item { onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode); onMaterialOverridesChanged: _generalHelper.storeToolState(sceneId, "matOverride", materialOverrides); onShowWireframesChanged: _generalHelper.storeToolState(sceneId, "showWireframe", showWireframes); - onSplitViewChanged: { - _generalHelper.storeToolState(sceneId, "splitView", splitView); + onActivePresetChanged: { + _generalHelper.storeToolState(sceneId, "activePreset", activePreset); _generalHelper.requestOverlayUpdate(); } - onActiveSplitChanged: { - _generalHelper.storeToolState(sceneId, "activeSplit", activeSplit); - cameraControls[activeSplit].forceActiveFocus(); - notifyActiveSplitChange(activeSplit); + onActiveViewportChanged: { + _generalHelper.storeToolState(sceneId, "activeViewport", activeViewport); + cameraControls[activeViewport].forceActiveFocus(); + notifyActiveViewportChange(activeViewport); } onActiveSceneChanged: updateActiveScene() @@ -141,7 +185,7 @@ Item { selectionBoxCount = 0; editViewsChanged(); - cameraControls[activeSplit].forceActiveFocus(); + cameraControls[activeViewport].forceActiveFocus(); return true; } return false; @@ -234,7 +278,7 @@ Item { } else if (selectedNodes.length > 0 && selectionBoxCount > 0) { boxModels.push(activeEditView.selectionBoxes[0].model); } - cameraControls[activeSplit].focusObject( + cameraControls[activeViewport].focusObject( boxModels, activeEditView.camera.eulerRotation, true, false); } } @@ -242,7 +286,7 @@ Item { function alignCamerasToView(cameraNodes) { if (activeEditView) { - cameraControls[activeSplit].alignCameras(cameraNodes); + cameraControls[activeViewport].alignCameras(cameraNodes); var propertyNames = ["position", "eulerRotation"]; viewRoot.changeObjectProperty(cameraNodes, propertyNames); viewRoot.commitObjectProperty(cameraNodes, propertyNames); @@ -252,7 +296,7 @@ Item { function alignViewToCamera(cameraNodes) { if (activeEditView) - cameraControls[activeSplit].alignView(cameraNodes); + cameraControls[activeViewport].alignView(cameraNodes); } function updateBackgroundColors(colors) @@ -388,15 +432,16 @@ Item { viewRoot.showCameraSpeed = false; } - if ("splitView" in toolStates) - splitView = toolStates.splitView; + if ("activePreset" in toolStates) + activePreset = toolStates.activePreset; else if (resetToDefault) - splitView = false; + activePreset = "Quad"; + applyViewportPreset(activePreset) - if ("activeSplit" in toolStates) - activeSplit = toolStates.activeSplit; + if ("activeViewport" in toolStates) + activeViewport = toolStates.activeViewport; else if (resetToDefault) - activeSplit = 0; + activeViewport = 0; if ("showWireframe" in toolStates) showWireframes = toolStates.showWireframe; @@ -424,8 +469,8 @@ Item { _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); _generalHelper.storeToolState(sceneId, "transformMode", transformMode); - _generalHelper.storeToolState(sceneId, "splitView", splitView) - _generalHelper.storeToolState(sceneId, "activeSplit", activeSplit) + _generalHelper.storeToolState(sceneId, "activePreset", activePreset) + _generalHelper.storeToolState(sceneId, "activeViewport", activeViewport) _generalHelper.storeToolState(sceneId, "showWireframe", showWireframes) _generalHelper.storeToolState(sceneId, "matOverride", materialOverrides) @@ -527,6 +572,7 @@ Item { selectionChanged(newSelection); } + //TODO: only update the active viewport views function addLightGizmo(scene, obj) { for (var i = 0; i < 4; ++i) @@ -617,64 +663,95 @@ Item { overlayViews[i].updateReflectionProbeGizmoScene(scene, obj); } - function resolveSplitPoint(x, y) + function resolveViewportPoint(x, y) { - if (!splitView || activeSplit === 0) + let rect = viewRects[activeViewport]; + // Check invisible or out or range, then fallback to original origin + if (!rect || !rect.visible) return Qt.point(x, y); - if (activeSplit === 1) - return Qt.point(x - viewContainer.width / 2, y); - else if (activeSplit === 2) - return Qt.point(x, y - viewContainer.height / 2); - else - return Qt.point(x - viewContainer.width / 2, y - viewContainer.height / 2); + // Transform topleft of the active viewport to be the origin + return Qt.point(x - rect.x, y - rect.y); } - function updateActiveSplit(x, y) + function updateActiveViewport(x, y) { - if (splitView) { - if (x <= viewContainer.width / 2) { - if (y <= viewContainer.height / 2) - activeSplit = 0; - else - activeSplit = 2; - } else { - if (y <= viewContainer.height / 2) - activeSplit = 1; - else - activeSplit = 3; + for (let i = 0; i < 4; ++i) { + let rect = viewRects[i]; + if (!rect.visible) + continue; + + if (x >= rect.x && x <= rect.x + rect.width + && y >= rect.y && y <= rect.y + rect.height) { + activeViewport = i; + return; } } + + // TODO: if click outside all visible viewRects, do nothing + // or reset to e.g. activeVireport = -1 or 0 } function gizmoAt(x, y) { - updateActiveSplit(x, y); - let splitPoint = resolveSplitPoint(x, y); + updateActiveViewport(x, y); + let viewportPoint = resolveViewportPoint(x, y); - return activeOverlayView.gizmoAt(splitPoint.x, splitPoint.y); + return activeOverlayView.gizmoAt(viewportPoint.x, viewportPoint.y); } function rotateEditCamera(angles) { - cameraControls[activeSplit].rotateCamera(angles); + cameraControls[activeViewport].rotateCamera(angles); } function moveEditCamera(amounts) { - cameraControls[activeSplit].moveCamera(amounts); + cameraControls[activeViewport].moveCamera(amounts); + } + + // Update viewports based on selected preset + function applyViewportPreset(presetName) + { + let preset = viewportPresets[presetName]; + if (!preset) + return; + + let count = preset.numViewports; + + for (let i = 0; i < 4; ++i) { + if (i < count) { + viewRects[i].visible = true; + viewRects[i].x = preset.viewRects[i].x * viewContainer.width; + viewRects[i].y = preset.viewRects[i].y * viewContainer.height; + viewRects[i].width = preset.viewRects[i].width * viewContainer.width; + viewRects[i].height = preset.viewRects[i].height * viewContainer.height; + } else { + viewRects[i].visible = false; + } + } + + //TODO: Do we need this here? + cameraView.updateSnapping(); } Component.onCompleted: { createEditViews(); selectObjects([]); + applyViewportPreset(activePreset) // Work-around the fact that the projection matrix for the camera is not calculated until // the first frame is rendered, so any initial calls to mapFrom3DScene() will fail. _generalHelper.requestOverlayUpdate(); } - onWidthChanged: _generalHelper.requestOverlayUpdate() - onHeightChanged: _generalHelper.requestOverlayUpdate() + onWidthChanged: { + applyViewportPreset(activePreset) + _generalHelper.requestOverlayUpdate() + } + onHeightChanged: { + applyViewportPreset(activePreset) + _generalHelper.requestOverlayUpdate() + } Connections { target: _generalHelper @@ -715,9 +792,9 @@ Item { } // Shared nodes of the overlay, set as importScene on all overlay views. - // Content here can be used as is on all splits. - // Nodes that utilize autoscaling or otherwise need to have different appearance on each split - // need to have separate copy on each split. + // Content here can be used as is on all viewports. + // Nodes that utilize autoscaling or otherwise need to have different appearance on each viewport + // need to have separate copy on each viewport. Node { id: overlayScene @@ -743,12 +820,9 @@ Item { Rectangle { id: viewRect0 - width: viewRoot.splitView ? parent.width / 2 : parent.width - height: viewRoot.splitView ? parent.height / 2 : parent.height - x: 0 - y: 0 - visible: viewRoot.splitView || viewRoot.activeSplit == 0 gradient: bgGradient + border.width: 1 + border.color: viewportBorderColor OverlayView3D { id: overlayView0 editView: viewRoot.editViews[0] @@ -765,18 +839,15 @@ Item { EditCameraController { id: cameraControl0 viewRoot: viewRoot - splitId: 0 + viewportId: 0 } } Rectangle { id: viewRect1 - width: viewRoot.splitView ? parent.width / 2 : parent.width - height: viewRoot.splitView ? parent.height / 2 : parent.height - x: viewRoot.splitView ? parent.width / 2 : 0 - y: 0 - visible: viewRoot.splitView || viewRoot.activeSplit == 1 gradient: bgGradient + border.width: 1 + border.color: viewportBorderColor OverlayView3D { id: overlayView1 editView: viewRoot.editViews[1] @@ -793,18 +864,15 @@ Item { EditCameraController { id: cameraControl1 viewRoot: viewRoot - splitId: 1 + viewportId: 1 } } Rectangle { id: viewRect2 - width: viewRoot.splitView ? parent.width / 2 : parent.width - height: viewRoot.splitView ? parent.height / 2 : parent.height - x: 0 - y: viewRoot.splitView ? parent.height / 2 : 0 - visible: viewRoot.splitView || viewRoot.activeSplit == 2 gradient: bgGradient + border.width: 1 + border.color: viewportBorderColor OverlayView3D { id: overlayView2 editView: viewRoot.editViews[2] @@ -821,18 +889,15 @@ Item { EditCameraController { id: cameraControl2 viewRoot: viewRoot - splitId: 2 + viewportId: 2 } } Rectangle { id: viewRect3 - width: viewRoot.splitView ? parent.width / 2 : parent.width - height: viewRoot.splitView ? parent.height / 2 : parent.height - x: viewRoot.splitView ? parent.width / 2 : 0 - y: viewRoot.splitView ? parent.height / 2 : 0 - visible: viewRoot.splitView || viewRoot.activeSplit == 3 gradient: bgGradient + border.width: 1 + border.color: viewportBorderColor OverlayView3D { id: overlayView3 editView: viewRoot.editViews[3] @@ -849,44 +914,21 @@ Item { EditCameraController { id: cameraControl3 viewRoot: viewRoot - splitId: 3 + viewportId: 3 } } + // Active viewport highlight Rectangle { - // Vertical border between splits - visible: viewRoot.splitView - x: parent.width / 2 - y: 0 - width: 1 - height: parent.height - border.width: 1 - border.color: "#aaaaaa" - } - - Rectangle { - // Horizontal border between splits - visible: viewRoot.splitView - x: 0 - y: parent.height / 2 - height: 1 - width: parent.width - border.width: 1 - border.color: "#aaaaaa" - } - - Rectangle { - // Active split highlight - visible: viewRoot.splitView - x: viewRects[viewRoot.activeSplit].x - y: viewRects[viewRoot.activeSplit].y - height: viewRects[viewRoot.activeSplit].height - + (viewRoot.activeSplit === 0 || viewRoot.activeSplit === 1 ? 1 : 0) - width: viewRects[viewRoot.activeSplit].width - + (viewRoot.activeSplit === 0 || viewRoot.activeSplit === 2 ? 1 : 0) + visible: activePreset !== "Single" && viewRects[viewRoot.activeViewport].visible + x: viewRects[viewRoot.activeViewport].x + y: viewRects[viewRoot.activeViewport].y + width: viewRects[viewRoot.activeViewport].width + height: viewRects[viewRoot.activeViewport].height border.width: 2 border.color: "#57B9FC" color: "transparent" + z: 1000 // Edge case to make sure selection rect drawn over everything } MouseArea { @@ -903,20 +945,20 @@ Item { if (viewRoot.flyMode) return; - viewRoot.updateActiveSplit(mouse.x, mouse.y); + viewRoot.updateActiveViewport(mouse.x, mouse.y); - let splitPoint = viewRoot.resolveSplitPoint(mouse.x, mouse.y); + let viewportPoint = viewRoot.resolveViewportPoint(mouse.x, mouse.y); if (viewRoot.activeEditView) { // First pick overlay to check for hits there var pickResult = _generalHelper.pickViewAt(activeOverlayView, - splitPoint.x, splitPoint.y); + viewportPoint.x, viewportPoint.y); var resolvedResult = _generalHelper.resolvePick(pickResult.objectHit); if (!resolvedResult) { // No hits from overlay view, pick the main scene pickResult = _generalHelper.pickViewAt(viewRoot.activeEditView, - splitPoint.x, splitPoint.y); + viewportPoint.x, viewportPoint.y); resolvedResult = _generalHelper.resolvePick(pickResult.objectHit); } @@ -940,17 +982,17 @@ Item { } onPositionChanged: (mouse) => { if (freeDraggerArea) { - let splitPoint = viewRoot.resolveSplitPoint(mouse.x, mouse.y); - let splitPress = viewRoot.resolveSplitPoint(pressPoint.x, pressPoint.y); - if (initialMoveBlock && Math.abs(splitPress.x - splitPoint.x) - + Math.abs(splitPress.y - splitPoint.y) > 10) { + let viewportPoint = viewRoot.resolveViewportPoint(mouse.x, mouse.y); + let viewportPress = viewRoot.resolveViewportPoint(pressPoint.x, pressPoint.y); + if (initialMoveBlock && Math.abs(viewportPress.x - viewportPoint.x) + + Math.abs(viewportPress.y - viewportPoint.y) > 10) { // Don't force press event at actual press, as that puts the gizmo // in free-dragging state, which is bad UX if drag is not actually done - freeDraggerArea.forcePressEvent(splitPress.x, splitPress.y); - freeDraggerArea.forceMoveEvent(splitPoint.x, splitPoint.y); + freeDraggerArea.forcePressEvent(viewportPress.x, viewportPress.y); + freeDraggerArea.forceMoveEvent(viewportPoint.x, viewportPoint.y); initialMoveBlock = false; } else { - freeDraggerArea.forceMoveEvent(splitPoint.x, splitPoint.y); + freeDraggerArea.forceMoveEvent(viewportPoint.x, viewportPoint.y); } } } @@ -959,11 +1001,11 @@ Item { { if (freeDraggerArea) { if (initialMoveBlock) { - let splitPress = viewRoot.resolveSplitPoint(pressPoint.x, pressPoint.y); - freeDraggerArea.forceReleaseEvent(splitPress.x, splitPress.y); + let viewportPress = viewRoot.resolveViewportPoint(pressPoint.x, pressPoint.y); + freeDraggerArea.forceReleaseEvent(viewportPress.x, viewportPress.y); } else { - let splitPoint = viewRoot.resolveSplitPoint(mouse.x, mouse.y); - freeDraggerArea.forceReleaseEvent(splitPoint.x, splitPoint.y); + let viewportPoint = viewRoot.resolveViewportPoint(mouse.x, mouse.y); + freeDraggerArea.forceReleaseEvent(viewportPoint.x, viewportPoint.y); } freeDraggerArea = null; } @@ -1107,19 +1149,17 @@ Item { 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 + const rect = viewRoot.viewRects[viewRoot.activeViewport]; + if (!rect || !rect.visible) + return; + + const centerX = rect.x + rect.width / 2; + cameraView.snapLeft = centerX < viewContainer.width / 2; } Connections { target: viewRoot - - onSplitViewChanged: cameraView.updateSnapping() - onActiveSplitChanged: cameraView.updateSnapping() + onActiveViewportChanged: cameraView.updateSnapping() } } } diff --git a/src/tools/qmlpuppet/mockfiles/qt6/OverlayView3D.qml b/src/tools/qmlpuppet/mockfiles/qt6/OverlayView3D.qml index 7d7f419e429..59dd33d6f3a 100644 --- a/src/tools/qmlpuppet/mockfiles/qt6/OverlayView3D.qml +++ b/src/tools/qmlpuppet/mockfiles/qt6/OverlayView3D.qml @@ -16,7 +16,7 @@ View3D { property var viewRoot: null property View3D editView: null - property bool isActive: viewRoot.overlayViews[viewRoot.activeSplit] === overlayView + property bool isActive: viewRoot.overlayViews[viewRoot.activeViewport] === overlayView property var lightIconGizmos: [] property var cameraGizmos: [] @@ -629,7 +629,7 @@ View3D { scale: lookAtAutoScale.getScale(Qt.vector3d(10, 10, 10)) visible: overlayView.viewRoot.showLookAt && overlayView.isActive - && !overlayView.viewRoot.cameraControls[viewRoot.activeSplit].showCrosshairs + && !overlayView.viewRoot.cameraControls[viewRoot.activeViewport].showCrosshairs } } } diff --git a/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.cpp index 2eb4d7f1cc7..99928dfe681 100644 --- a/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.cpp +++ b/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.cpp @@ -956,9 +956,9 @@ void Qt5InformationNodeInstanceServer::handleActiveSceneChange() #endif } -void Qt5InformationNodeInstanceServer::handleActiveSplitChange(int index) +void Qt5InformationNodeInstanceServer::handleActiveViewportChange(int index) { - nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ActiveSplitChanged, + nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ActiveViewportChanged, index}); } @@ -1966,8 +1966,8 @@ void Qt5InformationNodeInstanceServer::setup3DEditView( this, SLOT(handleObjectPropertyChange(QVariant, QVariant))); QObject::connect(m_editView3DData.rootItem, SIGNAL(notifyActiveSceneChange()), this, SLOT(handleActiveSceneChange())); - QObject::connect(m_editView3DData.rootItem, SIGNAL(notifyActiveSplitChange(int)), - this, SLOT(handleActiveSplitChange(int))); + QObject::connect(m_editView3DData.rootItem, SIGNAL(notifyActiveViewportChange(int)), + this, SLOT(handleActiveViewportChange(int))); QObject::connect(&m_propertyChangeTimer, &QTimer::timeout, this, &Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout); QObject::connect(&m_selectionChangeTimer, &QTimer::timeout, @@ -2599,6 +2599,9 @@ void Qt5InformationNodeInstanceServer::view3DAction([[maybe_unused]] const View3 case View3DActionType::SyncEnvBackground: updatedToolState.insert("syncEnvBackground", command.isEnabled()); break; + case View3DActionType::ViewportPreset: + updatedToolState.insert("activePreset", command.value()); + break; #ifdef QUICK3D_PARTICLES_MODULE case View3DActionType::ShowParticleEmitter: updatedToolState.insert("showParticleEmitter", command.isEnabled()); @@ -2637,8 +2640,8 @@ void Qt5InformationNodeInstanceServer::view3DAction([[maybe_unused]] const View3 getNodeAtMainScenePos(data[0].toPointF(), qint32(data[1].toInt())); return; } - case View3DActionType::SplitViewToggle: - updatedToolState.insert("splitView", command.isEnabled()); + case View3DActionType::ViewportViewToggle: + updatedToolState.insert("viewportView", command.isEnabled()); break; case View3DActionType::FlyModeToggle: updatedToolState.insert("flyMode", command.isEnabled()); diff --git a/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.h b/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.h index 4bd3c157533..3f93ca5aebc 100644 --- a/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.h +++ b/src/tools/qmlpuppet/qmlpuppet/instances/qt5informationnodeinstanceserver.h @@ -66,7 +66,7 @@ private slots: void handleObjectPropertyCommit(const QVariant &objects, const QVariant &propNames); void handleObjectPropertyChange(const QVariant &objects, const QVariant &propNames); void handleActiveSceneChange(); - void handleActiveSplitChange(int index); + void handleActiveViewportChange(int index); void handleToolStateChanged(const QString &sceneId, const QString &tool, const QVariant &toolState); void handleView3DSizeChange();