diff --git a/crates/fj-app/src/config.rs b/crates/fj-app/src/config.rs index 94d6e8967..a2d7ba359 100644 --- a/crates/fj-app/src/config.rs +++ b/crates/fj-app/src/config.rs @@ -11,6 +11,7 @@ use serde::Deserialize; pub struct Config { pub default_path: Option, pub default_model: Option, + pub invert_zoom: Option, } impl Config { diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index 6513cdc58..3744d32a9 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -80,11 +80,13 @@ fn main() -> anyhow::Result<()> { return Ok(()); } + let invert_zoom = config.invert_zoom.unwrap_or(false); + if let Some(model) = model { let watcher = model.load_and_watch(parameters)?; - run(Some(watcher), shape_processor, status)?; + run(Some(watcher), shape_processor, status, invert_zoom)?; } else { - run(None, shape_processor, status)?; + run(None, shape_processor, status, invert_zoom)?; } Ok(()) diff --git a/crates/fj-viewer/src/input/zoom.rs b/crates/fj-viewer/src/input/zoom.rs index f4f7a0eb1..9c6e495b7 100644 --- a/crates/fj-viewer/src/input/zoom.rs +++ b/crates/fj-viewer/src/input/zoom.rs @@ -14,6 +14,6 @@ impl Zoom { let distance = (focus_point.0 - camera.position()).magnitude(); let displacement = zoom_delta * distance.into_f64(); camera.translation = camera.translation - * Transform::translation(Vector::from([0.0, 0.0, -displacement])); + * Transform::translation(Vector::from([0.0, 0.0, displacement])); } } diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index b1168dd58..cdebae724 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -32,6 +32,7 @@ pub fn run( watcher: Option, shape_processor: ShapeProcessor, mut status: StatusReport, + invert_zoom: bool, ) -> Result<(), Error> { let event_loop = EventLoop::new(); let window = Window::new(&event_loop)?; @@ -214,6 +215,7 @@ pub fn run( &window, &held_mouse_button, &mut previous_cursor, + invert_zoom, ); if let (Some(input_event), Some(fp)) = (input_event, focus_point) { input_handler.handle_event(input_event, fp, &mut camera); @@ -226,6 +228,7 @@ fn input_event( window: &Window, held_mouse_button: &Option, previous_cursor: &mut Option, + invert_zoom: bool, ) -> Option { match event { Event::WindowEvent { @@ -264,12 +267,20 @@ fn input_event( Event::WindowEvent { event: WindowEvent::MouseWheel { delta, .. }, .. - } => Some(input::Event::Zoom(match delta { - MouseScrollDelta::LineDelta(_, y) => (*y as f64) * ZOOM_FACTOR_LINE, - MouseScrollDelta::PixelDelta(PhysicalPosition { y, .. }) => { - y * ZOOM_FACTOR_PIXEL - } - })), + } => { + let delta = match delta { + MouseScrollDelta::LineDelta(_, y) => { + (*y as f64) * ZOOM_FACTOR_LINE + } + MouseScrollDelta::PixelDelta(PhysicalPosition { + y, .. + }) => y * ZOOM_FACTOR_PIXEL, + }; + + let delta = if invert_zoom { -delta } else { delta }; + + Some(input::Event::Zoom(delta)) + } _ => None, } } diff --git a/fj.toml b/fj.toml index eb26a979f..a7b7a4a93 100644 --- a/fj.toml +++ b/fj.toml @@ -5,3 +5,7 @@ default_path = "models" # The default models that is loaded, if none is specified. If this is a relative # path, it should be relative to `default_path`. default_model = "test" + +# Indicate whether to invert the zoom direction. Can be used to override the +# OS-level setting. +invert_zoom = false