diff --git a/crates/engine/src/cmd/view.rs b/crates/engine/src/cmd/view.rs index c58c31d94..0dfd4f28a 100644 --- a/crates/engine/src/cmd/view.rs +++ b/crates/engine/src/cmd/view.rs @@ -688,4 +688,33 @@ mod start_on_home_tests { let v = &s.ds().unwrap().view; assert_eq!((v.cx, v.cy), (364.0, -120.0), "Shift pans 320 px"); } + + #[test] + fn the_arrow_pan_is_the_same_screen_distance_at_any_zoom_on_both_axes() { + // (zoom, dx, dy, big, expected centre change in document px) + let cases = [ + (2.0, 1.0, 0.0, false, 32.0, 0.0), + (0.5, 1.0, 0.0, false, 128.0, 0.0), + (2.0, 0.0, 1.0, true, 0.0, 160.0), + (0.5, 0.0, 1.0, true, 0.0, 640.0), + (1.0, -1.0, 0.0, false, -64.0, 0.0), + (1.0, 1.0, 0.0, true, 320.0, 0.0), + (1.0, -1.0, 0.0, true, -320.0, 0.0), + (1.0, 0.0, -1.0, false, 0.0, -64.0), + (1.0, 0.0, 1.0, false, 0.0, 64.0), + (1.0, 0.0, -1.0, true, 0.0, -320.0), + ]; + for (zoom, dx, dy, big, ex, ey) in cases { + let mut s = crate::Session::new(); + s.execute("view.set", &json!({"zoom": zoom, "cx": 300, "cy": 200})).unwrap(); + s.execute("view.pan", &json!({"dx": dx, "dy": dy, "big": big})).unwrap(); + let v = &s.ds().unwrap().view; + let got = (v.cx - 300.0, v.cy - 200.0); + assert!( + (got.0 - ex).abs() < 1e-6 && (got.1 - ey).abs() < 1e-6, + "zoom {zoom} dx {dx} dy {dy} big {big}: moved {got:?}, expected {:?}", + (ex, ey) + ); + } + } } diff --git a/crates/ui-egui/src/inspect_fields_tests.rs b/crates/ui-egui/src/inspect_fields_tests.rs index bdd0abcd8..9164f02b8 100644 --- a/crates/ui-egui/src/inspect_fields_tests.rs +++ b/crates/ui-egui/src/inspect_fields_tests.rs @@ -62,12 +62,12 @@ fn control_key_arrows_pan_with_nothing_selected() { (v.cx, v.cy) }; call(&mut u, "ui.key", json!({"key": "ArrowRight"})).unwrap(); - assert_eq!(view(&u), (10.0, 0.0), "20 screen pixels at 200%"); + assert_eq!(view(&u), (32.0, 0.0), "64 screen pixels at 200% are 32 document pixels"); call(&mut u, "ui.key", json!({"key": "ArrowUp", "shift": true})).unwrap(); - assert_eq!(view(&u), (10.0, -100.0), "Shift: ten times as far"); + assert_eq!(view(&u), (32.0, -160.0), "Shift: 320 screen pixels, 160 document pixels"); u.app.run("select.set", json!({"ids": [r]})); call(&mut u, "ui.key", json!({"key": "ArrowRight"})).unwrap(); - assert_eq!(view(&u), (10.0, -100.0), "with a selection the view stays"); + assert_eq!(view(&u), (32.0, -160.0), "with a selection the view stays"); let id = figcraft_engine::params::id_of(&r).unwrap(); assert_eq!(u.app.session.doc().unwrap().world_bounds(id).unwrap().x0, 1.0, "the selection moved instead"); // With a shape tool chosen and nothing selected the arrows move the placement crosshair diff --git a/crates/ui-egui/src/shortcut_keys_tests.rs b/crates/ui-egui/src/shortcut_keys_tests.rs index dbe6ab3b9..e48a3d0bb 100644 --- a/crates/ui-egui/src/shortcut_keys_tests.rs +++ b/crates/ui-egui/src/shortcut_keys_tests.rs @@ -44,13 +44,13 @@ fn arrows_pan_the_view_when_nothing_is_selected() { u.app.run("select.set", json!({"ids": []})); u.app.run("view.set", json!({"zoom": 2.0, "cx": 0, "cy": 0})); press(&mut u, Key::ArrowRight, Modifiers::NONE); - assert_eq!(view(&u), (10.0, 0.0, 2.0), "20 screen pixels at 200%"); + assert_eq!(view(&u), (32.0, 0.0, 2.0), "64 screen pixels at 200% are 32 document pixels"); press(&mut u, Key::ArrowUp, Modifiers::SHIFT); - assert_eq!(view(&u), (10.0, -100.0, 2.0), "Shift: ten times as far"); + assert_eq!(view(&u), (32.0, -160.0, 2.0), "Shift: 320 screen pixels, 160 document pixels"); // With a selection the arrows nudge it and the view stays. u.app.run("select.set", json!({"ids": [r]})); press(&mut u, Key::ArrowRight, Modifiers::NONE); - assert_eq!(view(&u), (10.0, -100.0, 2.0)); + assert_eq!(view(&u), (32.0, -160.0, 2.0)); assert_eq!(u.app.session.doc().unwrap().world_bounds(r).unwrap().x0, 1.0); }