mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-18 19:12:17 +00:00
Add ability to assign None/Pan/Rotate to mouse buttons (#10736)
* Add logic to handle the left, middle and right buttons being assigned to do nothing, pan or rotate * Add entries for setting the drag actions to preferences * Allow the label text in preferences to wrap * Show mouse mappings in Help -> Keyboard Shortcuts * Re-add preferences in updated layout * Add camera mouse options under camera * Change mouse action strings to use L() for localization * Display "None" when it is selected instead of blank in keyboard shortcuts --------- Co-authored-by: Rob O <robertolabode@gmail.com> Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
@@ -212,8 +212,14 @@ 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("left_mouse_drag_action").empty())
|
||||
set("left_mouse_drag_action", "2");
|
||||
|
||||
if (get("middle_mouse_drag_action").empty())
|
||||
set("middle_mouse_drag_action", "1");
|
||||
|
||||
if (get("right_mouse_drag_action").empty())
|
||||
set("right_mouse_drag_action", "1");
|
||||
|
||||
if (get("reverse_mouse_wheel_zoom").empty())
|
||||
set_bool("reverse_mouse_wheel_zoom", false);
|
||||
|
||||
@@ -4272,7 +4272,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
|
||||
bool any_gizmo_active = m_gizmos.get_current() != nullptr;
|
||||
bool swap_mouse_buttons = wxGetApp().app_config->get_bool("swap_mouse_buttons");
|
||||
|
||||
std::map<MouseButton, MouseAction> button_mappings;
|
||||
button_mappings[MouseButton::Left] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("left_mouse_drag_action").c_str()));
|
||||
button_mappings[MouseButton::Middle] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("middle_mouse_drag_action").c_str()));
|
||||
button_mappings[MouseButton::Right] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("right_mouse_drag_action").c_str()));
|
||||
|
||||
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;
|
||||
@@ -4485,7 +4489,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
else if (evt.Dragging() || is_camera_rotate(evt, swap_mouse_buttons) || is_camera_pan(evt, swap_mouse_buttons)) {
|
||||
else if (evt.Dragging() || is_camera_rotate(evt, button_mappings) || is_camera_pan(evt, button_mappings)) {
|
||||
m_mouse.dragging = true;
|
||||
|
||||
if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
|
||||
@@ -4495,10 +4499,13 @@ 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, swap_mouse_buttons)) {
|
||||
else if (is_camera_rotate(evt, button_mappings)) {
|
||||
// Orca: Sphere rotation for painting view
|
||||
// if dragging over blank area with left button or button functions swapped then rotate
|
||||
if ((any_gizmo_active || swap_mouse_buttons || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
|
||||
// if dragging over blank area with left button or other button mapped to rotate, then rotate
|
||||
bool middle_or_right_button_used_as_rotate = (evt.MiddleIsDown() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
|
||||
(evt.RightIsDown() && button_mappings[MouseButton::Right] == MouseAction::Rotation);
|
||||
if ((any_gizmo_active || middle_or_right_button_used_as_rotate || 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);
|
||||
@@ -4571,7 +4578,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
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, swap_mouse_buttons)) {
|
||||
else if (is_camera_pan(evt, button_mappings)) {
|
||||
// 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
|
||||
@@ -4599,10 +4606,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
else if ((evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) ||
|
||||
(m_camera_movement && !is_camera_rotate(evt, swap_mouse_buttons) && !is_camera_pan(evt, swap_mouse_buttons))) {
|
||||
(m_camera_movement && !is_camera_rotate(evt, button_mappings) && !is_camera_pan(evt, button_mappings))) {
|
||||
m_mouse.position = pos.cast<double>();
|
||||
|
||||
if (swap_mouse_buttons ? evt.RightUp() : evt.LeftUp()) {
|
||||
// Check if the button that was released is mapped to rotation
|
||||
if ((evt.LeftUp() && button_mappings[MouseButton::Left] == MouseAction::Rotation) ||
|
||||
(evt.MiddleUp() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
|
||||
(evt.RightUp() && button_mappings[MouseButton::Right] == MouseAction::Rotation)) {
|
||||
m_rotation_center(0) = m_rotation_center(1) = m_rotation_center(2) = 0.f;
|
||||
}
|
||||
|
||||
@@ -4795,21 +4805,42 @@ 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 buttonsSwapped) const
|
||||
bool GLCanvas3D::clicked_button_matches_action(const wxMouseEvent& evt, const MouseAction action, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
MouseButton clicked = MouseButton::None;
|
||||
if (evt.LeftIsDown()) {
|
||||
clicked = MouseButton::Left;
|
||||
}
|
||||
if (evt.MiddleIsDown()) {
|
||||
clicked = MouseButton::Middle;
|
||||
}
|
||||
if (evt.RightIsDown()) {
|
||||
clicked = MouseButton::Right;
|
||||
}
|
||||
|
||||
auto it = mappings.find(clicked);
|
||||
if (it == mappings.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second == action;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_camera_rotate(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
if (m_is_touchpad_navigation) {
|
||||
return evt.Moving() && evt.AltDown() && !evt.ShiftDown();
|
||||
} else {
|
||||
return evt.Dragging() && (buttonsSwapped ? evt.RightIsDown() : evt.LeftIsDown());
|
||||
return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Rotation, mappings);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt, const bool buttonsSwapped) const
|
||||
bool GLCanvas3D::is_camera_pan(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const
|
||||
{
|
||||
if (m_is_touchpad_navigation) {
|
||||
return evt.Moving() && evt.ShiftDown() && !evt.AltDown();
|
||||
} else {
|
||||
return evt.Dragging() && (evt.MiddleIsDown() || (buttonsSwapped ? evt.LeftIsDown() : evt.RightIsDown()));
|
||||
return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Pan, mappings);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1038,8 +1038,11 @@ public:
|
||||
void on_set_focus(wxFocusEvent& evt);
|
||||
void force_set_focus();
|
||||
|
||||
bool is_camera_rotate(const wxMouseEvent& evt, const bool buttonsSwapped) const;
|
||||
bool is_camera_pan(const wxMouseEvent& evt, const bool buttonsSwapped) const;
|
||||
enum class MouseButton { None, Left, Middle, Right };
|
||||
enum class MouseAction { None, Pan, Rotation };
|
||||
bool clicked_button_matches_action(const wxMouseEvent& evt, MouseAction action, const std::map<MouseButton, MouseAction>& mappings) const;
|
||||
bool is_camera_rotate(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const;
|
||||
bool is_camera_pan(const wxMouseEvent& evt, const std::map<MouseButton, MouseAction>& mappings) const;
|
||||
|
||||
Size get_canvas_size() const;
|
||||
Vec2d get_local_mouse_position() const;
|
||||
|
||||
@@ -207,13 +207,19 @@ void KBShortcutsDialog::fill_shortcuts()
|
||||
{ "?", L("Show keyboard shortcuts list") }
|
||||
};
|
||||
m_full_shortcuts.push_back({{_L("Global shortcuts"), ""}, global_shortcuts});
|
||||
|
||||
|
||||
bool swap_mouse_buttons = wxGetApp().app_config->get_bool("swap_mouse_buttons");
|
||||
// Retrieve mouse actions from config and map to MouseAction
|
||||
std::map<std::string, std::string> mouse_actions;
|
||||
mouse_actions["0"] = L("None");
|
||||
mouse_actions["1"] = L("Pan View");
|
||||
mouse_actions["2"] = L("Rotate View");
|
||||
|
||||
Shortcuts plater_shortcuts = {
|
||||
{ L("Left mouse button"), swap_mouse_buttons ? L("Pan view") : L("Rotate view") },
|
||||
{ L("Right mouse button"), swap_mouse_buttons ? L("Rotate view") : L("Pan view") },
|
||||
{ L("Mouse wheel"), L("Zoom view") },
|
||||
{ L("Left mouse button"), mouse_actions[wxGetApp().app_config->get("left_mouse_drag_action").c_str()]},
|
||||
{ L("Middle mouse button"), mouse_actions[wxGetApp().app_config->get("middle_mouse_drag_action").c_str()]},
|
||||
{ L("Right mouse button"), mouse_actions[wxGetApp().app_config->get("right_mouse_drag_action").c_str()]},
|
||||
{ L("Mouse wheel"), L("Zoom View") },
|
||||
{ "A", L("Arrange all objects") },
|
||||
{ shift + "A", L("Arrange objects on selected plates") },
|
||||
|
||||
|
||||
@@ -1500,12 +1500,17 @@ void PreferencesDialog::create_items()
|
||||
auto item_use_free_camera = create_item_checkbox(_L("Use free camera"), _L("If enabled, use free camera. If not enabled, use constrained camera."), "use_free_camera");
|
||||
g_sizer->Add(item_use_free_camera);
|
||||
|
||||
auto swap_pan_rotate = create_item_checkbox(_L("Swap pan and rotate mouse buttons"), _L("If enabled, swaps the left and right mouse buttons pan and rotate functions."), "swap_mouse_buttons");
|
||||
g_sizer->Add(swap_pan_rotate);
|
||||
|
||||
auto reverse_mouse_zoom = create_item_checkbox(_L("Reverse mouse zoom"), _L("If enabled, reverses the direction of zoom with mouse wheel."), "reverse_mouse_wheel_zoom");
|
||||
g_sizer->Add(reverse_mouse_zoom);
|
||||
|
||||
std::vector<wxString> ButtonDragActions = {_L("None"), _L("Pan"), _L("Rotate")};
|
||||
auto item_left_mouse_drag = create_item_combobox(_L("Left Mouse Drag"), _L("Set the action that dragging the left mouse button should perform."), "left_mouse_drag_action", ButtonDragActions);
|
||||
g_sizer->Add(item_left_mouse_drag);
|
||||
auto item_middle_mouse_drag = create_item_combobox(_L("Middle Mouse Drag"), _L("Set the action that dragging the middle mouse button should perform."), "middle_mouse_drag_action", ButtonDragActions);
|
||||
g_sizer->Add(item_middle_mouse_drag);
|
||||
auto item_right_mouse_drag = create_item_combobox(_L("Right Mouse Drag"), _L("Set the action that dragging the right mouse button should perform."), "right_mouse_drag_action", ButtonDragActions);
|
||||
g_sizer->Add(item_right_mouse_drag);
|
||||
|
||||
//// CONTROL > Clear my choice on ...
|
||||
g_sizer->Add(create_item_title(_L("Clear my choice on...")), 1, wxEXPAND);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user