From fc7882b0eed5c15d78b643c1a972b0081340b329 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo Date: Fri, 23 Oct 2026 22:23:21 +0200 Subject: [PATCH] Scale Composition: scale the Point of Interest depth of a camera or light under a 2D parent Otherwise the eye moves back while the point it looks at stays put, and the view direction changes. --- crates/engine/src/cmd/comp_more.rs | 2 +- crates/engine/src/tests/scale_comp.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/comp_more.rs b/crates/engine/src/cmd/comp_more.rs index 00f1bb200..940c09f8d 100644 --- a/crates/engine/src/cmd/comp_more.rs +++ b/crates/engine/src/cmd/comp_more.rs @@ -197,7 +197,7 @@ fn scale_comp(s: &mut Session, p: &Value) -> Result { if let Some(pr) = tr.get_mut("positionZ") { scale_prop(pr, f); } - for name in ["position", "scale"] { + for name in ["position", "poi", "scale"] { if let Some(pr) = tr.get_mut(name) { scale_prop_z(pr, f); } diff --git a/crates/engine/src/tests/scale_comp.rs b/crates/engine/src/tests/scale_comp.rs index 27397e744..28cc1ba88 100644 --- a/crates/engine/src/tests/scale_comp.rs +++ b/crates/engine/src/tests/scale_comp.rs @@ -243,6 +243,21 @@ fn scale_comp_scales_once_through_a_camera_under_a_scaled_null() { assert!(near, "{held0:?} → {held1:?}"); } +#[test] +fn scale_comp_scales_the_point_of_interest_depth_of_a_camera_under_a_2d_null() { + let mut s = comp(200, 100); + let cam = s.execute("layer.newCamera", json!({})).unwrap()["layer"].as_u64().unwrap(); + let rig = s.execute("layer.newNull", json!({})).unwrap()["layer"].as_u64().unwrap(); + s.execute("layer.setParent", json!({"layers": [cam], "parent": rig})).unwrap(); + s.execute("prop.set", json!({"layer": cam, "path": "transform/position", "value": [10, 20, -1000]})).unwrap(); + s.execute("prop.set", json!({"layer": cam, "path": "transform/poi", "value": [10, 20, 200]})).unwrap(); + + s.execute("comp.scale", json!({"factor": 2})).unwrap(); + // The 2D null carries X and Y; the camera's own Z doubles at both ends, so it looks the same way. + assert_eq!(v3(&s, cam, "transform/position", 0.0), [10.0, 20.0, -2000.0]); + assert_eq!(v3(&s, cam, "transform/poi", 0.0), [10.0, 20.0, 400.0]); +} + #[test] fn scale_comp_refuses_a_bad_factor_and_changes_nothing() { let mut s = comp(640, 360);