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.
This commit is contained in:
Marco Arnulfo
2026-10-30 00:44:58 +01:00
parent 1f693acea6
commit fc7882b0ee
2 changed files with 16 additions and 1 deletions
+1 -1
View File
@@ -197,7 +197,7 @@ fn scale_comp(s: &mut Session, p: &Value) -> Result<Value> {
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);
}
+15
View File
@@ -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);