Swap pan and rotate mouse buttons (#9972)

* Swap pan and rotate buttons

* Add translation
This commit is contained in:
Kiss Lorand
2025-06-24 18:41:41 +03:00
committed by GitHub
parent bec5d9ea57
commit 5707f8f4a5
25 changed files with 183 additions and 66 deletions

View File

@@ -178,6 +178,9 @@ void AppConfig::set_defaults()
if (get("camera_navigation_style").empty())
set("camera_navigation_style", "0");
if (get("swap_mouse_buttons").empty())
set_bool("swap_mouse_buttons", false);
if (get("reverse_mouse_wheel_zoom").empty())
set_bool("reverse_mouse_wheel_zoom", false);

View File

@@ -4104,6 +4104,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
bool any_gizmo_active = m_gizmos.get_current() != nullptr;
bool swapMouseButtons = wxGetApp().app_config->get_bool("swap_mouse_buttons");
if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos)) {
m_mouse.drag.move_requires_threshold = false;
@@ -4305,7 +4306,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
}
else if (evt.Dragging() || is_camera_rotate(evt) || is_camera_pan(evt)) {
else if (evt.Dragging() || is_camera_rotate(evt, swapMouseButtons) || is_camera_pan(evt, swapMouseButtons)) {
m_mouse.dragging = true;
if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
@@ -4315,10 +4316,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
// do not process the dragging if the left mouse was set down in another canvas
else if (is_camera_rotate(evt)) {
else if (is_camera_rotate(evt, swapMouseButtons)) {
// Orca: Sphere rotation for painting view
// if dragging over blank area with left button, rotate
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
// if dragging over blank area with left button or button functions swapped then rotate
if ((any_gizmo_active || swapMouseButtons || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
Camera& camera = wxGetApp().plater()->get_camera();
auto mult_pref = wxGetApp().app_config->get("camera_orbit_mult");
const double mult = mult_pref.empty() ? 1.0 : std::stod(mult_pref);
@@ -4381,15 +4382,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
}
camera.auto_type(Camera::EType::Perspective);
camera.auto_type(Camera::EType::Perspective);
m_dirty = true;
m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
}
m_camera_movement = true;
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
}
else if (is_camera_pan(evt)) {
// If dragging over blank area with right button, pan.
else if (is_camera_pan(evt, swapMouseButtons)) {
// if dragging with right button or if button functions swapped and dragging with left button over blank area then pan
if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0
float z = 0.0f;
@@ -4407,7 +4410,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
camera.set_target(camera.get_target() + orig - cur_pos);
m_dirty = true;
m_mouse.ignore_right_up = true;
m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
}
m_camera_movement = true;
@@ -4415,10 +4418,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
else if ((evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) ||
(m_camera_movement && !is_camera_rotate(evt) && !is_camera_pan(evt))) {
(m_camera_movement && !is_camera_rotate(evt, swapMouseButtons) && !is_camera_pan(evt, swapMouseButtons))) {
m_mouse.position = pos.cast<double>();
if (evt.LeftUp()) {
if (swapMouseButtons ? evt.RightUp() : evt.LeftUp()) {
m_rotation_center(0) = m_rotation_center(1) = m_rotation_center(2) = 0.f;
}
@@ -4603,21 +4606,21 @@ void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style");
}
bool GLCanvas3D::is_camera_rotate(const wxMouseEvent& evt) const
bool GLCanvas3D::is_camera_rotate(const wxMouseEvent& evt, const bool buttonsSwapped) const
{
if (m_is_touchpad_navigation) {
return evt.Moving() && evt.AltDown() && !evt.ShiftDown();
} else {
return evt.Dragging() && evt.LeftIsDown();
return evt.Dragging() && (buttonsSwapped ? evt.RightIsDown() : evt.LeftIsDown());
}
}
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt) const
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt, const bool buttonsSwapped) const
{
if (m_is_touchpad_navigation) {
return evt.Moving() && evt.ShiftDown() && !evt.AltDown();
} else {
return evt.Dragging() && (evt.MiddleIsDown() || evt.RightIsDown());
return evt.Dragging() && (evt.MiddleIsDown() || (buttonsSwapped ? evt.LeftIsDown() : evt.RightIsDown()));
}
}

View File

@@ -216,7 +216,7 @@ class GLCanvas3D
};
static const float THICKNESS_BAR_WIDTH;
// Orca: Shrinkage compensation
void set_shrinkage_compensation(const Vec3d &shrinkage_compensation) { m_shrinkage_compensation = shrinkage_compensation; };
@@ -232,7 +232,7 @@ class GLCanvas3D
// Owned by LayersEditing.
SlicingParameters* m_slicing_parameters{ nullptr };
std::vector<double> m_layer_height_profile;
// Orca: Shrinkage compensation to apply when we need to use object_max_z with Z compensation.
Vec3d m_shrinkage_compensation{ Vec3d::Ones() };
@@ -968,8 +968,8 @@ public:
void on_set_focus(wxFocusEvent& evt);
void force_set_focus();
bool is_camera_rotate(const wxMouseEvent& evt) const;
bool is_camera_pan(const wxMouseEvent& evt) const;
bool is_camera_rotate(const wxMouseEvent& evt, const bool buttonsSwapped) const;
bool is_camera_pan(const wxMouseEvent& evt, const bool buttonsSwapped) const;
Size get_canvas_size() const;
Vec2d get_local_mouse_position() const;
@@ -1063,7 +1063,7 @@ public:
bool is_overhang_shown() const { return m_slope.is_GlobalUsed(); }
void show_overhang(bool show) { m_slope.globalUse(show); }
bool is_using_slope() const { return m_slope.is_used(); }
void use_slope(bool use) { m_slope.use(use); }
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }

View File

@@ -123,7 +123,7 @@ wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxWindow *pa
auto current_setting = app_config->get(param);
if (!current_setting.empty()) {
auto compare = [current_setting](string possible_setting) { return current_setting == possible_setting; };
auto iterator = find_if(config_name_index.begin(), config_name_index.end(), compare);
auto iterator = find_if(config_name_index.begin(), config_name_index.end(), compare);
current_index = iterator - config_name_index.begin();
}
@@ -536,7 +536,7 @@ wxBoxSizer *PreferencesDialog::create_camera_orbit_mult_input(wxString title, wx
sizer_input->Add(input_title, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
sizer_input->Add(input, 0, wxALIGN_CENTER_VERTICAL, 0);
sizer_input->Add(0, 0, 0, wxEXPAND | wxLEFT, 3);
const double min = 0.05;
const double max = 2.0;
@@ -1200,12 +1200,12 @@ wxWindow* PreferencesDialog::create_general_page()
std::vector<wxString> Units = {_L("Metric") + " (mm, g)", _L("Imperial") + " (in, oz)"};
auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units);
auto item_single_instance = create_item_checkbox(_L("Allow only one OrcaSlicer instance"), page,
auto item_single_instance = create_item_checkbox(_L("Allow only one OrcaSlicer instance"), page,
#if __APPLE__
_L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances "
"of same app from the command line. In such case this settings will allow only one instance."),
"of same app from the command line. In such case this settings will allow only one instance."),
#else
_L("If this is enabled, when starting OrcaSlicer and another instance of the same OrcaSlicer is already running, that instance will be reactivated instead."),
_L("If this is enabled, when starting OrcaSlicer and another instance of the same OrcaSlicer is already running, that instance will be reactivated instead."),
#endif
50, "single_instance");
@@ -1217,6 +1217,7 @@ wxWindow* PreferencesDialog::create_general_page()
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page, _L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50, "zoom_to_mouse");
auto item_use_free_camera_settings = create_item_checkbox(_L("Use free camera"), page, _L("If enabled, use free camera. If not enabled, use constrained camera."), 50, "use_free_camera");
auto swap_pan_rotate = create_item_checkbox(_L("Swap pan and rotate mouse buttons"), page, _L("If enabled, swaps the left and right mouse buttons pan and rotate functions."), 50, "swap_mouse_buttons");
auto reverse_mouse_zoom = create_item_checkbox(_L("Reverse mouse zoom"), page, _L("If enabled, reverses the direction of zoom with mouse wheel."), 50, "reverse_mouse_wheel_zoom");
auto camera_orbit_mult = create_camera_orbit_mult_input(_L("Orbit speed multiplier"), page, _L("Multiplies the orbit speed for finer or coarser camera movement."));
@@ -1301,6 +1302,7 @@ wxWindow* PreferencesDialog::create_general_page()
sizer_page->Add(item_single_instance, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_use_free_camera_settings, 0, wxTOP, FromDIP(3));
sizer_page->Add(swap_pan_rotate, 0, wxTOP, FromDIP(3));
sizer_page->Add(reverse_mouse_zoom, 0, wxTOP, FromDIP(3));
sizer_page->Add(camera_orbit_mult, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_show_splash_screen, 0, wxTOP, FromDIP(3));