navigation: selectable mouse navigation style

Options → User Preferences → Navigation style picks which mouse
gestures pan and orbit the model view (#1480):

- CAD (default): middle button pans, Shift + middle button orbits.
- Blender: middle button orbits, Shift + middle button pans.
- CATIA: middle button pans; pressing the left button during it orbits,
  so 3D navigation needs only the mouse.

An armed orbit tool always orbits. The choice is saved with the user
settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-15 11:17:13 +03:00
1 parent 74df9ff84a
commit 19ecf78bd9
30 files changed
+183 -1

No files matched your search

+2
View File
@@ -778,6 +778,7 @@ impl OpenCADStudio {
polar: self.polar_mode,
polar_increment_deg: self.polar_increment_deg,
zoom_wheel_reversed: self.zoom_wheel_reversed,
navigation_style: self.navigation_style,
touchpad_pan: self.touchpad_pan,
ui_scale_percent: self.ui_scale_percent,
zoom_factor: self.zoom_factor,
@@ -913,6 +914,7 @@ impl OpenCADStudio {
self.polar_mode = s.polar;
self.polar_increment_deg = s.polar_increment_deg;
self.zoom_wheel_reversed = s.zoom_wheel_reversed;
self.navigation_style = s.navigation_style;
self.touchpad_pan = s.touchpad_pan;
self.ui_scale_percent = crate::app::settings::clamp_ui_scale(s.ui_scale_percent);
self.zoom_factor = crate::app::settings::clamp_zoom_factor(s.zoom_factor);
+26
View File
@@ -4482,6 +4482,25 @@ impl OpenCADStudio {
Task::none()
}
// CATIA navigation: the left button pressed during a middle drag
// turns the drag into an orbit instead of starting a pick.
Message::ViewportLeftPressAt(_) | Message::ViewportLeftPress | Message::PanePress(_)
if self.navigation_style == crate::app::settings::NavigationStyle::Catia
&& self.tabs[self.active_tab]
.scene
.selection
.borrow()
.input
.middle_down =>
{
self.nav_left_with_middle = true;
Task::none()
}
Message::ViewportLeftRelease | Message::PaneRelease(_) if self.nav_left_with_middle => {
self.nav_left_with_middle = false;
Task::none()
}
Message::ViewportMove(p) => self.on_viewport_move(p),
Message::ViewportExit => self.on_viewport_exit(),
@@ -4686,6 +4705,7 @@ impl OpenCADStudio {
}
Message::ViewportMiddleRelease => {
self.nav_left_with_middle = false;
let i = self.active_tab;
let mut sel = self.tabs[i].scene.selection.borrow_mut();
sel.input.middle_down = false;
@@ -9225,6 +9245,12 @@ impl OpenCADStudio {
Task::none()
}
Message::NavigationStyleChanged(style) => {
self.navigation_style = style;
self.persist_settings_if_changed();
Task::none()
}
Message::MenuBarChanged(shown) => {
self.show_menu_bar = shown;
self.persist_settings_if_changed();
+13 -1
View File
@@ -1416,7 +1416,7 @@ impl OpenCADStudio {
// — the requested Zoom=wheel / Pan=MMB / Rotate=Shift+MMB
// scheme (#229). Floating viewports and paper keep the
// plain MMB pan.
if self.shift_down || self.tabs[i].orbit_mode {
if self.middle_drag_orbits(i) {
if self.tabs[i].scene.active_viewport.is_some() {
// Orbit the floating viewport's own model view.
drop(sel);
@@ -3165,6 +3165,18 @@ impl OpenCADStudio {
Task::none()
}
/// Whether a middle-button drag orbits rather than pans, by the
/// navigation style (an armed orbit tool always orbits).
fn middle_drag_orbits(&self, i: usize) -> bool {
use crate::app::settings::NavigationStyle;
self.tabs[i].orbit_mode
|| match self.navigation_style {
NavigationStyle::Cad => self.shift_down,
NavigationStyle::Blender => !self.shift_down,
NavigationStyle::Catia => self.nav_left_with_middle,
}
}
pub(crate) fn on_viewport_exit(&mut self) -> Task<Message> {
let i = self.active_tab;
self.tabs[i].measurement.live_visible = false;