mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-21 19:22:52 -05:00
Merge pull request #1558 from AyberkA0/script-keys-closed-comp
fix(script): per-key methods act on keys outside the active comp (#1531)
This commit is contained in:
2 files changed
+46
-6
No files matched your search
@@ -157,11 +157,16 @@ pub(crate) fn exec(s: &mut Session, id: &str, params: J) -> Result<J, String> {
|
||||
s.state.selected_layers.clear();
|
||||
}
|
||||
let r = s.execute_for_script(id, params);
|
||||
if let Some(c) = target
|
||||
&& prev != Some(c)
|
||||
&& s.state.active_comp == Some(c)
|
||||
&& id != "comp.open"
|
||||
{
|
||||
if let Some(c) = target {
|
||||
leave_comp(s, id, c, prev);
|
||||
}
|
||||
r.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// After a script's command on comp `c`, make `prev` (the comp active before it) active again,
|
||||
/// unless the command opened `c` on purpose; with no comp to go back to, `c` stays open.
|
||||
fn leave_comp(s: &mut Session, id: &str, c: effectcraft_engine::project::ItemId, prev: Option<effectcraft_engine::project::ItemId>) {
|
||||
if prev != Some(c) && s.state.active_comp == Some(c) && id != "comp.open" {
|
||||
match prev {
|
||||
Some(p) if s.project.comp(p).is_some() => s.activate_comp(p),
|
||||
_ => {
|
||||
@@ -171,7 +176,6 @@ pub(crate) fn exec(s: &mut Session, id: &str, params: J) -> Result<J, String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
r.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Run a keyframe command that acts on the selected keys (`keys.velocity`, `keys.interpolation`,
|
||||
@@ -195,11 +199,17 @@ fn exec_on_keys(s: &mut Session, id: &str, params: J, targets: &J) -> Result<J,
|
||||
let key = l.props.find(prop).and_then(|pr| pr.keys.get(usize::try_from(index).ok()?)).ok_or("the keyframe no longer exists")?;
|
||||
keys.push(KeyRef { layer: LayerId(layer), prop, time: key.time });
|
||||
}
|
||||
// Make the keys' comp active before selecting them: activating a comp brings back the key
|
||||
// selection it had, which would replace these keys and leave the command nothing to act on
|
||||
// when the comp isn't the active one (#1531).
|
||||
let prev = s.state.active_comp;
|
||||
s.activate_comp(cid);
|
||||
let saved = std::mem::replace(&mut s.state.selected_keys, keys);
|
||||
let r = exec(s, id, params);
|
||||
let comp = s.active_comp();
|
||||
let exists = |k: &KeyRef| comp.and_then(|c| c.layer(k.layer)).and_then(|l| l.props.find(k.prop)).is_some_and(|pr| pr.keys.iter().any(|x| x.time == k.time));
|
||||
s.state.selected_keys = saved.into_iter().filter(exists).collect();
|
||||
leave_comp(s, id, cid, prev);
|
||||
r
|
||||
}
|
||||
|
||||
|
||||
@@ -1270,6 +1270,36 @@ fn effect_parameter_interpolation_and_ease() {
|
||||
assert_eq!(o.result, json!([true, true, 16.67, 33.33, true]));
|
||||
}
|
||||
|
||||
/// #1531: the per-key methods act on a comp that isn't the active one too. Activating the keys'
|
||||
/// comp brought back its own (empty) key selection over the keys named, so the interpolation and
|
||||
/// the ease were silently dropped once another comp with a layer had been made first.
|
||||
#[test]
|
||||
fn key_interpolation_and_ease_apply_outside_the_active_comp() {
|
||||
let mut s = session();
|
||||
let o = ok(
|
||||
&mut s,
|
||||
r#"
|
||||
var a = app.project.items.addComp("A", 400, 400, 1, 10, 20); a.layers.addNull();
|
||||
var c = app.project.items.addComp("C", 400, 400, 1, 10, 20);
|
||||
var n = c.layers.addNull(); n.threeDLayer = true;
|
||||
var p = n.property("ADBE Transform Group").property("ADBE Rotate Y");
|
||||
p.setValueAtTime(1, 0); p.setValueAtTime(2, -178);
|
||||
for (var j = 1; j <= 2; j++) {
|
||||
p.setInterpolationTypeAtKey(j, KeyframeInterpolationType.BEZIER, KeyframeInterpolationType.BEZIER);
|
||||
p.setTemporalEaseAtKey(j, [new KeyframeEase(0, 60)], [new KeyframeEase(0, 60)]);
|
||||
}
|
||||
[p.keyOutInterpolationType(1) == KeyframeInterpolationType.BEZIER,
|
||||
p.keyInInterpolationType(2) == KeyframeInterpolationType.BEZIER,
|
||||
p.keyOutTemporalEase(1)[0].influence,
|
||||
Math.round(p.valueAtTime(1.25, false) * 100) / 100]
|
||||
"#,
|
||||
);
|
||||
let v = o.result;
|
||||
assert_eq!((&v[0], &v[1], &v[2]), (&json!(true), &json!(true), &json!(60)), "{v}");
|
||||
// Eased, not the linear -44.5.
|
||||
assert!(v[3].as_f64().is_some_and(|x| (x - -44.5).abs() > 1.0), "{v}");
|
||||
}
|
||||
|
||||
/// #808: sourcePointToComp and compPointToSource follow the layer's transform.
|
||||
#[test]
|
||||
fn source_point_conversions_follow_the_layer_transform() {
|
||||
|
||||
Reference in new issue
Block a user