QmlDesigner: Overhaul 3D snapping UI

Fixes: QDS-10532
Change-Id: I00dc78831aed62e0a93000938f514a04c2ab3a50
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2023-08-28 15:33:32 +03:00
parent 96e675cd26
commit 757c1734df
11 changed files with 406 additions and 376 deletions

View File

@@ -3,6 +3,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
@@ -13,175 +14,229 @@ Rectangle {
property int toolTipDelay: 1000
width: 230
height: 270
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
Column {
id: col
padding: 8
spacing: 4
Connections {
target: rootView
Rectangle {
id: ctrlRect
width: root.width - 16
height: posIntValue.height + rotIntValue.height + scaleIntValue.height + 32
// Spinboxes lose the initial binding if the value changes so we need these connections
onPosIntChanged: posIntSpin.realValue = rootView.posInt
onRotIntChanged: rotIntSpin.realValue = rootView.rotInt
onScaleIntChanged: scaleIntSpin.realValue = rootView.scaleInt
}
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
ColumnLayout {
anchors.fill: parent
spacing: 0
Column {
padding: 8
spacing: 8
Row {
height: posIntValue.height
width: parent.width - 16
spacing: StudioTheme.Values.sectionRowSpacing
RowLayout {
height: 32
Layout.topMargin: 8
Layout.rightMargin: 8
Layout.leftMargin: 8
Layout.fillWidth: true
spacing: 16
Text {
id: posIntLabel
text: qsTr("Position Snap Interval:")
color: enabled ? StudioTheme.Values.themeTextColor
: StudioTheme.Values.themeTextColorDisabled
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignRight
height: posIntValue.height
}
Rectangle {
width: 40
height: 40
radius: 5
Layout.fillHeight: false
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
Item { // Spacer
width: Math.max(ctrlRect.width - posIntLabel.width - posIntValue.width - 32, 1)
height: 1
}
StudioControls.RealSpinBox {
id: posIntValue
realFrom: 1
realTo: 100000
realValue: rootView.posInt
realStepSize: 1
width: 80
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for move gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.posInt = realValue
}
}
Row {
height: rotIntValue.height
width: parent.width - 16
spacing: StudioTheme.Values.sectionRowSpacing
Text {
id: rotIntLabel
text: qsTr("Rotation Snap Interval:")
color: enabled ? StudioTheme.Values.themeTextColor
: StudioTheme.Values.themeTextColorDisabled
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignRight
height: rotIntValue.height
}
Item { // Spacer
width: Math.max(ctrlRect.width - rotIntLabel.width - rotIntValue.width - 32, 1)
height: 1
}
StudioControls.RealSpinBox {
id: rotIntValue
realFrom: 1
realTo: 360
realValue: rootView.rotInt
realStepSize: 1
width: 80
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval in degrees for rotation gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.rotInt = realValue
}
}
Row {
height: scaleIntValue.height
width: parent.width - 16
spacing: StudioTheme.Values.sectionRowSpacing
Text {
id: scaleIntLabel
text: qsTr("Scale Snap Interval (%):")
color: enabled ? StudioTheme.Values.themeTextColor
: StudioTheme.Values.themeTextColorDisabled
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignRight
height: scaleIntValue.height
}
Item { // Spacer
width: Math.max(ctrlRect.width - scaleIntLabel.width - scaleIntValue.width - 32, 1)
height: 1
}
StudioControls.RealSpinBox {
id: scaleIntValue
realFrom: 1
realTo: 100000
realValue: rootView.scaleInt
realStepSize: 1
width: 80
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for scale gizmo in percentage of original scale.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.scaleInt = realValue
}
HelperWidgets.IconIndicator {
anchors.fill: parent
icon: StudioTheme.Constants.snapping_conf_medium
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
iconColor: StudioTheme.Values.themeLinkIndicatorColorHover
enabled: false
states: [] // Disable normal state based coloring
}
}
Text {
text: qsTr("Snap Configuration")
font.pixelSize: 12
horizontalAlignment: Text.AlignLeft
Layout.fillWidth: true
font.bold: true
color: StudioTheme.Values.themeTextColor
}
}
Item { // Spacer
width: 1
height: Math.max(root.height - buttons.height - ctrlRect.height - 16, 2)
GridLayout {
Layout.margins:10
Layout.fillWidth: true
Layout.fillHeight: true
rowSpacing: 5
columnSpacing: 5
rows: 5
columns: 3
Text {
text: qsTr("Interval")
Layout.column: 1
Layout.row: 0
Layout.leftMargin: 10
font.pixelSize: 12
font.bold: true
color: StudioTheme.Values.themeTextColor
}
StudioControls.CheckBox {
text: qsTr("Position")
Layout.column: 0
Layout.row: 1
Layout.minimumWidth: 100
checked: rootView.posEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap position.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.posEnabled = checked
}
StudioControls.RealSpinBox {
id: posIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 1
Layout.leftMargin: 10
realFrom: 1
realTo: 10000
realValue: rootView.posInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for move gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.posInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Rotation")
Layout.column: 0
Layout.row: 2
Layout.minimumWidth: 100
checked: rootView.rotEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap rotation.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.rotEnabled = checked
}
StudioControls.RealSpinBox {
id: rotIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 2
Layout.leftMargin: 10
realFrom: 1
realTo: 90
realValue: rootView.rotInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval in degrees for rotation gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.rotInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Scale")
Layout.column: 0
Layout.row: 3
Layout.minimumWidth: 100
checked: rootView.scaleEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap scale.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.scaleEnabled = checked
}
StudioControls.RealSpinBox {
id: scaleIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 3
Layout.leftMargin: 10
realFrom: 1
realTo: 100
realValue: rootView.scaleInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for scale gizmo in percentage of original scale.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.scaleInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Absolute Position")
Layout.fillWidth: false
Layout.leftMargin: 0
Layout.column: 0
Layout.row: 4
Layout.columnSpan: 3
checked: rootView.absolute
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Toggles if the position snaps to absolute values or relative to object position.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.absolute = checked
}
Text {
text: qsTr("deg")
font.pixelSize: 12
Layout.column: 2
Layout.row: 2
color: StudioTheme.Values.themeTextColor
}
Text {
text: qsTr("%")
font.pixelSize: 12
Layout.column: 2
Layout.row: 3
color: StudioTheme.Values.themeTextColor
}
}
Item {
id: buttons
height: cancelButton.height + 8
width: ctrlRect.width
Row {
spacing: StudioTheme.Values.dialogButtonSpacing
height: cancelButton.height
anchors.right: parent.right
HelperWidgets.Button {
id: cancelButton
text: qsTr("Cancel")
leftPadding: StudioTheme.Values.dialogButtonPadding
rightPadding: StudioTheme.Values.dialogButtonPadding
onClicked: rootView.cancel()
}
HelperWidgets.Button {
id: applyButton
text: qsTr("Ok")
leftPadding: StudioTheme.Values.dialogButtonPadding
rightPadding: StudioTheme.Values.dialogButtonPadding
onClicked: {
rootView.apply()
rootView.cancel()
}
}
}
HelperWidgets.Button {
text: qsTr("Reset All")
Layout.bottomMargin: 8
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
onClicked: rootView.resetDefaults()
}
}
}

View File

@@ -200,16 +200,7 @@ void Edit3DView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
rootModelNode().setAuxiliaryData(edit3dSnapPosProperty, m_snapPositionAction->action()->isChecked());
rootModelNode().setAuxiliaryData(edit3dSnapRotProperty, m_snapRotationAction->action()->isChecked());
rootModelNode().setAuxiliaryData(edit3dSnapScaleProperty, m_snapScaleAction->action()->isChecked());
rootModelNode().setAuxiliaryData(edit3dSnapAbsProperty, m_snapAbsoluteAction->action()->isChecked());
rootModelNode().setAuxiliaryData(edit3dSnapPosIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL));
rootModelNode().setAuxiliaryData(edit3dSnapRotIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL));
rootModelNode().setAuxiliaryData(edit3dSnapScaleIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL));
syncSnapAuxPropsToSettings();
checkImports();
auto cachedImage = m_canvasCache.take(model);
@@ -551,7 +542,32 @@ void Edit3DView::createSeekerSliderAction()
&SeekerSliderAction::valueChanged,
this, [=] (int value) {
this->emitView3DAction(View3DActionType::ParticlesSeek, value);
});
});
}
void Edit3DView::syncSnapAuxPropsToSettings()
{
if (!model())
return;
bool snapToggle = m_snapToggleAction->action()->isChecked();
rootModelNode().setAuxiliaryData(edit3dSnapPosProperty,
snapToggle ? Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION)
: false);
rootModelNode().setAuxiliaryData(edit3dSnapRotProperty,
snapToggle ? Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION)
: false);
rootModelNode().setAuxiliaryData(edit3dSnapScaleProperty,
snapToggle ? Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE)
: false);
rootModelNode().setAuxiliaryData(edit3dSnapAbsProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE));
rootModelNode().setAuxiliaryData(edit3dSnapPosIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL));
rootModelNode().setAuxiliaryData(edit3dSnapRotIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL));
rootModelNode().setAuxiliaryData(edit3dSnapScaleIntProperty,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL));
}
void Edit3DView::createEdit3DActions()
@@ -887,37 +903,32 @@ void Edit3DView::createEdit3DActions()
this,
bakeLightsTrigger);
SelectionContextOperation snapMenuTrigger = [this](const SelectionContext &) {
if (!edit3DWidget()->snapMenu())
return;
SelectionContextOperation snapToggleTrigger = [this](const SelectionContext &) {
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_ENABLED,
m_snapToggleAction->action()->isChecked());
syncSnapAuxPropsToSettings();
};
m_snapToggleAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_TOGGLE,
View3DActionType::Empty,
QCoreApplication::translate("SnapToggleAction", "Toggle snapping during node drag"),
QKeySequence(Qt::SHIFT | Qt::Key_Tab),
true,
Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ENABLED, false).toBool(),
toolbarIcon(DesignerIcons::SnappingIcon),
this,
snapToggleTrigger);
SelectionContextOperation snapConfigTrigger = [this](const SelectionContext &) {
QPoint pos;
const auto &actionWidgets = m_snapMenuAction->action()->associatedWidgets();
const auto &actionWidgets = m_snapConfigAction->action()->associatedWidgets();
for (auto actionWidget : actionWidgets) {
if (auto button = qobject_cast<QToolButton *>(actionWidget)) {
pos = button->mapToGlobal(QPoint(0, 0));
break;
}
}
edit3DWidget()->showSnapMenu(!edit3DWidget()->snapMenu()->isVisible(), pos);
};
m_snapMenuAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_MENU,
View3DActionType::Empty,
QCoreApplication::translate("Snapping", "Snapping"),
QKeySequence(),
false,
false,
toolbarIcon(DesignerIcons::SnappingIcon),
this,
snapMenuTrigger);
SelectionContextOperation snapConfigTrigger = [this](const SelectionContext &) {
QPoint pos;
pos = m_edit3DWidget->mapToGlobal(QPoint(m_edit3DWidget->width() / 2,
m_edit3DWidget->height() / 2));
if (!m_snapConfiguration)
m_snapConfiguration = new SnapConfiguration(this);
m_snapConfiguration->showConfigDialog(pos);
@@ -926,82 +937,13 @@ void Edit3DView::createEdit3DActions()
m_snapConfigAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_CONFIG,
View3DActionType::Empty,
QCoreApplication::translate("SnapConfigAction", "Snap Configuration"),
QCoreApplication::translate("SnapConfigAction", "Open snap configuration dialog"),
QKeySequence(),
false,
false,
toolbarIcon(DesignerIcons::SnappingIcon),
toolbarIcon(DesignerIcons::SnappingConfIcon),
this,
snapConfigTrigger,
QCoreApplication::translate("SnapConfigAction", "Open snap configuration dialog."));
SelectionContextOperation snapPositionTrigger = [this](const SelectionContext &) {
if (model())
rootModelNode().setAuxiliaryData(edit3dSnapPosProperty, m_snapPositionAction->action()->isChecked());
};
m_snapPositionAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_POSITION,
View3DActionType::Empty,
QCoreApplication::translate("SnapPositionAction", "Snap Position"),
QKeySequence(Qt::SHIFT | Qt::Key_W),
true,
Edit3DViewConfig::load(settingKeyForAction(QmlDesigner::Constants::EDIT3D_SNAP_POSITION), false).toBool(),
QIcon(),
this,
snapPositionTrigger,
QCoreApplication::translate("SnapPositionAction", "Toggle position snapping during node drag."));
SelectionContextOperation snapRotationTrigger = [this](const SelectionContext &) {
if (model())
rootModelNode().setAuxiliaryData(edit3dSnapRotProperty, m_snapRotationAction->action()->isChecked());
};
m_snapRotationAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_ROTATION,
View3DActionType::Empty,
QCoreApplication::translate("SnapRotationAction", "Snap Rotation"),
QKeySequence(Qt::SHIFT | Qt::Key_E),
true,
Edit3DViewConfig::load(settingKeyForAction(QmlDesigner::Constants::EDIT3D_SNAP_ROTATION), false).toBool(),
QIcon(),
this,
snapRotationTrigger,
QCoreApplication::translate("SnapRotationAction", "Toggle rotation snapping during node drag."));
SelectionContextOperation snapScaleTrigger = [this](const SelectionContext &) {
if (model())
rootModelNode().setAuxiliaryData(edit3dSnapScaleProperty, m_snapScaleAction->action()->isChecked());
};
m_snapScaleAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_SCALE,
View3DActionType::Empty,
QCoreApplication::translate("SnapScaleAction", "Snap Scale"),
QKeySequence(Qt::SHIFT | Qt::Key_R),
true,
Edit3DViewConfig::load(settingKeyForAction(QmlDesigner::Constants::EDIT3D_SNAP_SCALE), false).toBool(),
QIcon(),
this,
snapScaleTrigger,
QCoreApplication::translate("SnapScaleAction", "Toggle scale snapping during node drag."));
SelectionContextOperation snapAbsoluteTrigger = [this](const SelectionContext &) {
if (model())
rootModelNode().setAuxiliaryData(edit3dSnapAbsProperty, m_snapAbsoluteAction->action()->isChecked());
};
m_snapAbsoluteAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_SNAP_ABSOLUTE,
View3DActionType::Empty,
QCoreApplication::translate("SnapAbsoluteAction", "Absolute Position Snap"),
QKeySequence(Qt::SHIFT | Qt::Key_A),
true,
Edit3DViewConfig::load(settingKeyForAction(QmlDesigner::Constants::EDIT3D_SNAP_ABSOLUTE), true).toBool(),
QIcon(),
this,
snapAbsoluteTrigger,
QCoreApplication::translate("SnapAbsoluteAction", "If enabled, position snapping uses scene origin as origin point.\nOtherwise snapping uses drag start point as origin point."));
snapConfigTrigger);
m_leftActions << m_selectionModeAction.get();
m_leftActions << nullptr; // Null indicates separator
@@ -1016,12 +958,14 @@ void Edit3DView::createEdit3DActions()
m_leftActions << m_orientationModeAction.get();
m_leftActions << m_editLightAction.get();
m_leftActions << nullptr;
m_leftActions << m_snapToggleAction.get();
m_leftActions << m_snapConfigAction.get();
m_leftActions << nullptr;
m_leftActions << m_alignCamerasAction.get();
m_leftActions << m_alignViewAction.get();
m_leftActions << nullptr;
m_leftActions << m_visibilityTogglesAction.get();
m_leftActions << m_backgrondColorMenuAction.get();
m_leftActions << m_snapMenuAction.get();
m_rightActions << m_particleViewModeAction.get();
m_rightActions << m_particlesPlayAction.get();
@@ -1047,12 +991,6 @@ void Edit3DView::createEdit3DActions()
m_backgroundColorActions << m_selectGridColorAction.get();
m_backgroundColorActions << m_syncBackgroundColorAction.get();
m_backgroundColorActions << m_resetColorAction.get();
m_snapActions << m_snapConfigAction.get();
m_snapActions << m_snapPositionAction.get();
m_snapActions << m_snapRotationAction.get();
m_snapActions << m_snapScaleAction.get();
m_snapActions << m_snapAbsoluteAction.get();
}
QVector<Edit3DAction *> Edit3DView::leftActions() const
@@ -1075,10 +1013,6 @@ QVector<Edit3DAction *> Edit3DView::backgroundColorActions() const
return m_backgroundColorActions;
}
QVector<Edit3DAction *> Edit3DView::snapActions() const
{
return m_snapActions;
}
Edit3DAction *Edit3DView::edit3DAction(View3DActionType type) const
{
@@ -1161,17 +1095,4 @@ bool Edit3DView::isBakingLightsSupported() const
return m_isBakingLightsSupported;
}
const char *Edit3DView::settingKeyForAction(const QByteArray &actionId)
{
if (actionId == Constants::EDIT3D_SNAP_POSITION)
return DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION;
if (actionId == Constants::EDIT3D_SNAP_ROTATION)
return DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION;
if (actionId == Constants::EDIT3D_SNAP_SCALE)
return DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE;
if (actionId == Constants::EDIT3D_SNAP_ABSOLUTE)
return DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE;
return "";
}
} // namespace QmlDesigner

View File

@@ -62,7 +62,6 @@ public:
QVector<Edit3DAction *> rightActions() const;
QVector<Edit3DAction *> visibilityToggleActions() const;
QVector<Edit3DAction *> backgroundColorActions() const;
QVector<Edit3DAction *> snapActions() const;
Edit3DAction *edit3DAction(View3DActionType type) const;
Edit3DBakeLightsAction *bakeLightsAction() const;
@@ -77,7 +76,7 @@ public:
bool isBakingLightsSupported() const;
const char *settingKeyForAction(const QByteArray &actionId);
void syncSnapAuxPropsToSettings();
private slots:
void onEntriesChanged();
@@ -113,7 +112,6 @@ private:
QVector<Edit3DAction *> m_rightActions;
QVector<Edit3DAction *> m_visibilityToggleActions;
QVector<Edit3DAction *> m_backgroundColorActions;
QVector<Edit3DAction *> m_snapActions;
QMap<View3DActionType, Edit3DAction *> m_edit3DActions;
std::unique_ptr<Edit3DAction> m_selectionModeAction;
@@ -144,12 +142,8 @@ private:
std::unique_ptr<Edit3DAction> m_resetAction;
std::unique_ptr<Edit3DAction> m_visibilityTogglesAction;
std::unique_ptr<Edit3DAction> m_backgrondColorMenuAction;
std::unique_ptr<Edit3DAction> m_snapMenuAction;
std::unique_ptr<Edit3DAction> m_snapToggleAction;
std::unique_ptr<Edit3DAction> m_snapConfigAction;
std::unique_ptr<Edit3DAction> m_snapPositionAction;
std::unique_ptr<Edit3DAction> m_snapRotationAction;
std::unique_ptr<Edit3DAction> m_snapScaleAction;
std::unique_ptr<Edit3DAction> m_snapAbsoluteAction;
std::unique_ptr<Edit3DBakeLightsAction> m_bakeLightsAction;
int particlemode;

View File

@@ -166,19 +166,6 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view)
handleActions(view->backgroundColorActions(), m_backgroundColorMenu, false);
m_snapMenu = new Edit3DToolbarMenu(this);
handleActions(view->snapActions(), m_snapMenu, false);
connect(m_snapMenu, &QMenu::aboutToHide, this, [view]() {
// Persist the checkable settings of the menu
const auto actions = view->snapActions();
for (auto &action : actions) {
if (action->action()->isCheckable()) {
Edit3DViewConfig::save(view->settingKeyForAction(action->menuId()),
action->action()->isChecked());
}
}
});
createContextMenu();
m_mcuLabel = new QLabel(this);
@@ -467,21 +454,6 @@ void Edit3DWidget::showVisibilityTogglesMenu(bool show, const QPoint &pos)
m_visibilityTogglesMenu->close();
}
QMenu *Edit3DWidget::snapMenu() const
{
return m_snapMenu.data();
}
void Edit3DWidget::showSnapMenu(bool show, const QPoint &pos)
{
if (m_snapMenu.isNull())
return;
if (show)
m_snapMenu->popup(pos);
else
m_snapMenu->close();
}
QMenu *Edit3DWidget::backgroundColorMenu() const
{
return m_backgroundColorMenu.data();

View File

@@ -45,8 +45,6 @@ public:
void showCanvas(bool show);
QMenu *visibilityTogglesMenu() const;
void showVisibilityTogglesMenu(bool show, const QPoint &pos);
QMenu *snapMenu() const;
void showSnapMenu(bool show, const QPoint &pos);
QMenu *backgroundColorMenu() const;
void showBackgroundColorMenu(bool show, const QPoint &pos);
@@ -78,7 +76,6 @@ private:
QPointer<QMenu> m_visibilityTogglesMenu;
QPointer<QMenu> m_backgroundColorMenu;
QPointer<QMenu> m_contextMenu;
QPointer<QMenu> m_snapMenu;
QPointer<QAction> m_bakeLightsAction;
QPointer<QAction> m_editComponentAction;
QPointer<QAction> m_editMaterialAction;

View File

@@ -3,10 +3,9 @@
#include "snapconfiguration.h"
#include "abstractview.h"
#include "designersettings.h"
#include "edit3dview.h"
#include "edit3dviewconfig.h"
#include "modelnode.h"
#include <coreplugin/icore.h>
@@ -39,7 +38,7 @@ static QString qmlSourcesPath()
return Core::ICore::resourcePath("qmldesigner/edit3dQmlSource").toString();
}
SnapConfiguration::SnapConfiguration(AbstractView *view)
SnapConfiguration::SnapConfiguration(Edit3DView *view)
: QObject(view)
, m_view(view)
{
@@ -52,40 +51,70 @@ SnapConfiguration::~SnapConfiguration()
void SnapConfiguration::apply()
{
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL,
m_positionInterval);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL,
m_rotationInterval);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL,
m_scaleInterval);
m_view->rootModelNode().setAuxiliaryData(edit3dSnapPosIntProperty, m_positionInterval);
m_view->rootModelNode().setAuxiliaryData(edit3dSnapRotIntProperty, m_rotationInterval);
m_view->rootModelNode().setAuxiliaryData(edit3dSnapScaleIntProperty, m_scaleInterval);
if (m_changes) {
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION,
m_positionEnabled);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION,
m_rotationEnabled);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE,
m_scaleEnabled);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE,
m_absolute);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL,
m_positionInterval);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL,
m_rotationInterval);
Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL,
m_scaleInterval);
m_view->syncSnapAuxPropsToSettings();
}
cancel();
}
void SnapConfiguration::resetDefaults()
{
setPosEnabled(true);
setRotEnabled(true);
setScaleEnabled(true);
setAbsolute(true);
setPosInt(defaultPosInt);
setRotInt(defaultRotInt);
setScaleInt(defaultScaleInt);
}
void SnapConfiguration::showConfigDialog(const QPoint &pos)
{
bool posEnabled = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true).toBool();
bool rotEnabled = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION, true).toBool();
bool scaleEnabled = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE, true).toBool();
bool absolute = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE, true).toBool();
double posInt = Edit3DViewConfig::load(
DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL, 10.).toDouble();
DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL, defaultPosInt).toDouble();
double rotInt = Edit3DViewConfig::load(
DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL, 15.).toDouble();
DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL, defaultRotInt).toDouble();
double scaleInt = Edit3DViewConfig::load(
DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL, 10.).toDouble();
DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL, defaultScaleInt).toDouble();
setPosEnabled(posEnabled);
setRotEnabled(rotEnabled);
setScaleEnabled(scaleEnabled);
setAbsolute(absolute);
setPosInt(posInt);
setRotInt(rotInt);
setScaleInt(scaleInt);
m_changes = false;
if (!m_configDialog) {
// Show non-modal progress dialog with cancel button
QString path = qmlSourcesPath() + "/SnapConfigurationDialog.qml";
m_configDialog = new QQuickView;
m_configDialog->setTitle(tr("3D Snap Configuration"));
m_configDialog->setResizeMode(QQuickView::SizeRootObjectToView);
m_configDialog->setFlags(Qt::Dialog);
m_configDialog->setModality(Qt::ApplicationModal);
m_configDialog->setResizeMode(QQuickView::SizeViewToRootObject);
m_configDialog->setFlags(Qt::Dialog | Qt::FramelessWindowHint);
m_configDialog->setModality(Qt::NonModal);
m_configDialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_configDialog->setMinimumSize({280, 170});
m_configDialog->rootContext()->setContextProperties({
{"rootView", QVariant::fromValue(this)}
@@ -95,17 +124,54 @@ void SnapConfiguration::showConfigDialog(const QPoint &pos)
QPoint finalPos = pos;
finalPos.setX(pos.x() - m_configDialog->size().width() / 2);
finalPos.setY(pos.y() - m_configDialog->size().height() / 2);
finalPos.setY(pos.y());
m_configDialog->setPosition(finalPos);
}
m_configDialog->show();
}
void SnapConfiguration::setPosEnabled(bool enabled)
{
if (enabled != m_positionEnabled) {
m_positionEnabled = enabled;
m_changes = true;
emit posEnabledChanged();
}
}
void SnapConfiguration::setRotEnabled(bool enabled)
{
if (enabled != m_rotationEnabled) {
m_rotationEnabled = enabled;
m_changes = true;
emit rotEnabledChanged();
}
}
void SnapConfiguration::setScaleEnabled(bool enabled)
{
if (enabled != m_scaleEnabled) {
m_scaleEnabled = enabled;
m_changes = true;
emit scaleEnabledChanged();
}
}
void SnapConfiguration::setAbsolute(bool enabled)
{
if (enabled != m_absolute) {
m_absolute = enabled;
m_changes = true;
emit absoluteChanged();
}
}
void SnapConfiguration::setPosInt(double value)
{
if (value != m_positionInterval) {
m_positionInterval = value;
m_changes = true;
emit posIntChanged();
}
}
@@ -114,6 +180,7 @@ void SnapConfiguration::setRotInt(double value)
{
if (value != m_rotationInterval) {
m_rotationInterval = value;
m_changes = true;
emit rotIntChanged();
}
}
@@ -122,6 +189,7 @@ void SnapConfiguration::setScaleInt(double value)
{
if (value != m_scaleInterval) {
m_scaleInterval = value;
m_changes = true;
emit scaleIntChanged();
}
}
@@ -141,20 +209,17 @@ void SnapConfiguration::cancel()
bool SnapConfiguration::eventFilter(QObject *obj, QEvent *event)
{
// Closing dialog always applies the changes
if (obj == m_configDialog) {
if (event->type() == QEvent::KeyPress) {
if (event->type() == QEvent::FocusOut) {
apply();
} else if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Escape)
cancel();
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
// Apply asynchronously to allow the final value to be set by dialog before apply
QTimer::singleShot(0, this, [this]() {
apply();
cancel();
});
}
apply();
} else if (event->type() == QEvent::Close) {
cancel();
apply();
}
}

View File

@@ -14,7 +14,7 @@ QT_END_NAMESPACE
namespace QmlDesigner {
class AbstractView;
class Edit3DView;
inline constexpr AuxiliaryDataKeyView edit3dSnapPosProperty{AuxiliaryDataType::NodeInstanceAuxiliary,
"snapPos3d"};
@@ -34,19 +34,34 @@ inline constexpr AuxiliaryDataKeyView edit3dSnapScaleIntProperty{AuxiliaryDataTy
class SnapConfiguration : public QObject
{
Q_OBJECT
Q_PROPERTY(bool posEnabled READ posEnabled WRITE setPosEnabled NOTIFY posEnabledChanged)
Q_PROPERTY(bool rotEnabled READ rotEnabled WRITE setRotEnabled NOTIFY rotEnabledChanged)
Q_PROPERTY(bool scaleEnabled READ scaleEnabled WRITE setScaleEnabled NOTIFY scaleEnabledChanged)
Q_PROPERTY(bool absolute READ absolute WRITE setAbsolute NOTIFY absoluteChanged)
Q_PROPERTY(double posInt READ posInt WRITE setPosInt NOTIFY posIntChanged)
Q_PROPERTY(double rotInt READ rotInt WRITE setRotInt NOTIFY rotIntChanged)
Q_PROPERTY(double scaleInt READ scaleInt WRITE setScaleInt NOTIFY scaleIntChanged)
public:
SnapConfiguration(AbstractView *view);
SnapConfiguration(Edit3DView *view);
~SnapConfiguration();
Q_INVOKABLE void cancel();
Q_INVOKABLE void apply();
Q_INVOKABLE void resetDefaults();
void cancel();
void apply();
void showConfigDialog(const QPoint &pos);
void setPosEnabled(bool enabled);
bool posEnabled() const { return m_positionEnabled; }
void setRotEnabled(bool enabled);
bool rotEnabled() const { return m_rotationEnabled; }
void setScaleEnabled(bool enabled);
bool scaleEnabled() const { return m_scaleEnabled; }
void setAbsolute(bool enabled);
bool absolute() const { return m_absolute; }
void setPosInt(double value);
double posInt() const { return m_positionInterval; }
void setRotInt(double value);
@@ -54,7 +69,15 @@ public:
void setScaleInt(double value);
double scaleInt() const { return m_scaleInterval; }
constexpr static double defaultPosInt = 50.;
constexpr static double defaultRotInt = 5.;
constexpr static double defaultScaleInt = 10.;
signals:
void posEnabledChanged();
void rotEnabledChanged();
void scaleEnabledChanged();
void absoluteChanged();
void posIntChanged();
void rotIntChanged();
void scaleIntChanged();
@@ -66,10 +89,15 @@ private:
void cleanup();
QPointer<QQuickView> m_configDialog;
QPointer<AbstractView> m_view;
double m_positionInterval = 10.;
double m_rotationInterval = 15.;
double m_scaleInterval = 10.;
QPointer<Edit3DView> m_view;
bool m_positionEnabled = true;
bool m_rotationEnabled = true;
bool m_scaleEnabled = true;
bool m_absolute = true;
double m_positionInterval = 0.;
double m_rotationInterval = 0.;
double m_scaleInterval = 0.;
bool m_changes = false;
};
} // namespace QmlDesigner

View File

@@ -64,12 +64,8 @@ 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 EDIT3D_SNAP_MENU[] = "QmlDesigner.Editor3D.SnapMenu";
const char EDIT3D_SNAP_POSITION[] = "QmlDesigner.Editor3D.SnapPosition";
const char EDIT3D_SNAP_ROTATION[] = "QmlDesigner.Editor3D.SnapRotation";
const char EDIT3D_SNAP_SCALE[] = "QmlDesigner.Editor3D.SnapScale";
const char EDIT3D_SNAP_TOGGLE[] = "QmlDesigner.Editor3D.SnapToggle";
const char EDIT3D_SNAP_CONFIG[] = "QmlDesigner.Editor3D.SnapConfig";
const char EDIT3D_SNAP_ABSOLUTE[] = "QmlDesigner.Editor3D.SnapToGrid";
const char QML_DESIGNER_SUBFOLDER[] = "/designer/";
const char COMPONENT_BUNDLES_FOLDER[] = "/ComponentBundles";

View File

@@ -84,11 +84,12 @@ void DesignerSettings::fromSettings(QSettings *settings)
QStringList{"#222222", "#999999"});
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, "#aaaaaa");
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, false);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL, 10.);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION, false);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL, 15.);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE, false);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ENABLED, false);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION_INTERVAL, 50.);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ROTATION_INTERVAL, 5.);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_SCALE_INTERVAL, 10.);
restoreValue(settings, DesignerSettingsKey::SMOOTH_RENDERING, false);
restoreValue(settings, DesignerSettingsKey::SHOW_DEBUG_SETTINGS, false);

View File

@@ -33,6 +33,7 @@ inline constexpr char ENABLE_DEBUGVIEW[] = "EnableQtQuickDesignerDebugView";
inline constexpr char EDIT3DVIEW_BACKGROUND_COLOR[] = "Edit3DViewBackgroundColor";
inline constexpr char EDIT3DVIEW_GRID_COLOR[] = "Edit3DViewGridLineColor";
inline constexpr char EDIT3DVIEW_SNAP_ABSOLUTE[] = "Edit3DViewSnapAbsolute";
inline constexpr char EDIT3DVIEW_SNAP_ENABLED[] = "Edit3DViewSnapEnabled";
inline constexpr char EDIT3DVIEW_SNAP_POSITION[] = "Edit3DViewSnapPosition";
inline constexpr char EDIT3DVIEW_SNAP_POSITION_INTERVAL[] = "Edit3DViewSnapPositionInterval";
inline constexpr char EDIT3DVIEW_SNAP_ROTATION[] = "Edit3DViewSnapRotation";

View File

@@ -156,8 +156,8 @@ private:
bool m_snapPosition = false;
bool m_snapRotation = false;
bool m_snapScale = false;
double m_snapPositionInterval = 10.;
double m_snapRotationInterval = 15.;
double m_snapPositionInterval = 50.;
double m_snapRotationInterval = 5.;
double m_snapScaleInterval = .1;
};