mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Merge pull request #1123 from nanox333/fix/808-source-point-convert
# Conflicts: # crates/script/src/tests.rs
This commit is contained in:
commit
5c0ac48f31
3 files changed
+52
-2
No files matched your search
@@ -44,6 +44,7 @@ pub fn query(s: &mut Session, kind: &str, a: &J) -> R {
|
||||
"textdoc" => textdoc(s, a),
|
||||
"markers" => markers(s, a),
|
||||
"sourceRect" => source_rect(s, a),
|
||||
"pointConvert" => point_convert(s, a),
|
||||
"resolveAdd" => resolve_add(s, a),
|
||||
"menuCommandId" => Ok(menu_command_id(a.get("name").and_then(J::as_str).unwrap_or(""))),
|
||||
"commandAt" => {
|
||||
@@ -577,6 +578,29 @@ fn markers(s: &Session, a: &J) -> R {
|
||||
Ok(J::Array(out))
|
||||
}
|
||||
|
||||
/// A layer's source point in comp space (`toComp`) or the reverse, through the layer's transform
|
||||
/// and its parents' at comp time (#808: `sourcePointToComp`, `compPointToSource`).
|
||||
fn point_convert(s: &Session, a: &J) -> R {
|
||||
let (cid, c, l) = layer_of(s, a)?;
|
||||
let t = f(a, "time").map(Tick::from_seconds_f64).unwrap_or_else(|| s.time_of(cid));
|
||||
let p = a.get("point").and_then(J::as_array).ok_or("missing point")?;
|
||||
let x = p.first().and_then(J::as_f64).unwrap_or(0.0);
|
||||
let y = p.get(1).and_then(J::as_f64).unwrap_or(0.0);
|
||||
let mut ctx = EvalCtx::new(&s.project, cid, c, t);
|
||||
ctx.expr = s.expr.as_deref();
|
||||
let (layer_space, _) = ctx.layer_to_comp(l);
|
||||
let m = if a.get("toComp").and_then(J::as_bool).unwrap_or(true) {
|
||||
layer_space
|
||||
} else {
|
||||
layer_space.inverse().ok_or("the layer's transform can't be inverted")?
|
||||
};
|
||||
let k = m.0;
|
||||
let w = k[2][0] * x + k[2][1] * y + k[2][2];
|
||||
let (ox, oy) = (k[0][0] * x + k[0][1] * y + k[0][2], k[1][0] * x + k[1][1] * y + k[1][2]);
|
||||
let (ox, oy) = if w != 0.0 && w.is_finite() { (ox / w, oy / w) } else { (ox, oy) };
|
||||
Ok(json!([ox, oy]))
|
||||
}
|
||||
|
||||
fn source_rect(s: &Session, a: &J) -> R {
|
||||
let (cid, c, l) = layer_of(s, a)?;
|
||||
let t = f(a, "time").map(Tick::from_seconds_f64).unwrap_or_else(|| s.time_of(cid));
|
||||
|
||||
@@ -1285,8 +1285,12 @@ AVLayer.prototype.constructor = AVLayer;
|
||||
P.sourceRectAtTime = function (t, extents) {
|
||||
return __get("sourceRect", { comp: this.__comp, layer: this.__id, time: __num(t, "time"), extents: !!extents });
|
||||
};
|
||||
P.sourcePointToComp = function (p) { return p; };
|
||||
P.compPointToSource = function (p) { return p; };
|
||||
// Source ↔ comp points, through the layer's transform and its parents' at the comp's time (#808).
|
||||
function pointIn(layer, p, toComp) {
|
||||
return __get("pointConvert", { comp: layer.__comp, layer: layer.__id, point: [__num(p[0], "point"), __num(p[1], "point")], toComp: toComp, time: layer.containingComp.time });
|
||||
}
|
||||
P.sourcePointToComp = function (p) { return pointIn(this, p, true); };
|
||||
P.compPointToSource = function (p) { return pointIn(this, p, false); };
|
||||
P.replaceSource = function () { throw __err("replaceSource is not supported yet"); };
|
||||
P.openInViewer = function () { __call("layer.openLayer", this.__p1()); return null; };
|
||||
})();
|
||||
|
||||
@@ -1082,3 +1082,25 @@ fn effect_parameter_interpolation_and_ease() {
|
||||
);
|
||||
assert_eq!(o.result, json!([true, true, 16.67, 33.33, true]));
|
||||
}
|
||||
|
||||
/// #808: sourcePointToComp and compPointToSource follow the layer's transform.
|
||||
#[test]
|
||||
fn source_point_conversions_follow_the_layer_transform() {
|
||||
let mut s = session();
|
||||
let o = ok(
|
||||
&mut s,
|
||||
r#"
|
||||
var comp = app.project.items.addComp("Repro", 1920, 1080, 1, 10, 25);
|
||||
var layer = comp.layers.addSolid([1, 0, 0], "S", 200, 100, 1);
|
||||
layer.transform.position.setValue([400, 300]);
|
||||
layer.transform.scale.setValue([50, 50]);
|
||||
var a = layer.sourcePointToComp([0, 0]);
|
||||
var b = layer.compPointToSource([400, 300]);
|
||||
[a[0], a[1], b[0], b[1]]
|
||||
"#,
|
||||
);
|
||||
let v = o.result;
|
||||
let near = |x: &Value, want: f64| x.as_f64().is_some_and(|g| (g - want).abs() < 1e-6);
|
||||
assert!(near(&v[0], 350.0) && near(&v[1], 275.0), "{v}");
|
||||
assert!(near(&v[2], 100.0) && near(&v[3], 50.0), "{v}");
|
||||
}
|
||||
Reference in new issue
Block a user