Merge pull request #1146 from redonion23/fix/1078-reset-keeps-keyframes

This commit is contained in:
Brandon Thomas committed 2026-10-13 04:28:54 -04:00
commit f0fa92ceef
3 files changed
+37 -8

No files matched your search

+5 -4
View File
@@ -631,11 +631,12 @@ fn reset(s: &mut Session, p: &Value) -> Result<Value> {
let (cid, lid, uid) = prop_ref(s, p, "prop.reset")?;
let def = p.get("default").cloned();
let own = default_value(s, cid, lid, uid);
with_prop(s, "Reset Property", None, cid, lid, uid, |pr, _| {
pr.keys.clear();
with_prop(s, "Reset Property", None, cid, lid, uid, |pr, t| {
pr.expr = None;
// An animated property keeps its keyframes and gets the default as a key at the
// current time, as in After Effects (#1078).
if let Some(d) = def.as_ref().and_then(|d| pr.value.coerce_json(d)).or(own) {
pr.value = d;
pr.set_value_at(t, d);
}
Ok(Value::Null)
})
@@ -1238,7 +1239,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Reset Property",
[],
None,
"{layer?, path|prop, default?} → removes keyframes and expression; the value becomes `default`, else the property's own (an effect parameter's, a Transform property's)",
"{layer?, path|prop, default?} → removes the expression; the value becomes `default`, else the property's own (an effect parameter's, a Transform property's), as a keyframe at the current time when the property is animated",
has_layers,
reset
),
+29 -2
View File
@@ -597,8 +597,10 @@ fn reset_gives_a_property_its_default() {
assert_eq!(v(&s, "transform/anchor"), KV::Vec3([50.0, 50.0, 0.0]), "the solid's centre");
assert_eq!(v(&s, "transform/position"), KV::Vec3([200.0, 150.0, 0.0]), "the comp's centre");
assert_eq!(v(&s, "transform/scale"), KV::Vec3([100.0; 3]));
assert_eq!(v(&s, "transform/rotation"), KV::Scalar(0.0));
assert!(!prop(&s, l, "transform/rotation").is_animated());
// Animated: the default becomes the key at the current time (0 s), the 1 s key stays (#1078).
let rot = prop(&s, l, "transform/rotation");
assert_eq!(rot.keys.len(), 2);
assert_eq!(rot.value_at(effectcraft_time::Tick::ZERO), KV::Scalar(0.0));
assert_eq!(v(&s, "transform/opacity"), KV::Scalar(100.0));
assert!(prop(&s, l, "transform/opacity").expr.is_none());
assert_eq!(v(&s, "effects/#1/blurriness"), blur);
@@ -607,6 +609,31 @@ fn reset_gives_a_property_its_default() {
assert_eq!(v(&s, "transform/opacity"), KV::Scalar(30.0));
}
/// #1078: resetting an animated property keeps its keyframes and keys the default at the
/// current time, as in After Effects; undo brings the old keys back.
#[test]
fn reset_keys_the_default_on_an_animated_property() {
let (mut s, l) = setup();
animate(&mut s, l, "transform/scale", &[(0.0, json!([50, 50, 100])), (2.0, json!([150, 150, 100]))]);
s.execute("time.set", json!({"time": 1})).unwrap();
s.execute("prop.reset", json!({"layer": l, "path": "transform/scale"})).unwrap();
let pr = prop(&s, l, "transform/scale");
let at = |sec: f64| pr.value_at(effectcraft_time::Tick::from_seconds_f64(sec));
assert_eq!(pr.keys.len(), 3, "the 0 s and 2 s keys stay, one is added at 1 s");
assert_eq!(at(0.0), KV::Vec3([50.0, 50.0, 100.0]));
assert_eq!(at(1.0), KV::Vec3([100.0; 3]));
assert_eq!(at(2.0), KV::Vec3([150.0, 150.0, 100.0]));
// On a key, the key takes the default.
s.execute("time.set", json!({"time": 2})).unwrap();
s.execute("prop.reset", json!({"layer": l, "path": "transform/scale"})).unwrap();
let pr = prop(&s, l, "transform/scale");
assert_eq!(pr.keys.len(), 3);
assert_eq!(pr.value_at(effectcraft_time::Tick::from_seconds_f64(2.0)), KV::Vec3([100.0; 3]));
s.execute("edit.undo", json!({})).unwrap();
s.execute("edit.undo", json!({})).unwrap();
assert_eq!(prop(&s, l, "transform/scale").keys.len(), 2);
}
/// #363: dropped on one of the target's values the pick whip picks that dimension
/// (`position[0]`), as in After Effects; a multi-dimension property follows it on every axis.
#[test]
+3 -2
View File
@@ -573,8 +573,9 @@ Extension points and the bundled extensions: [plugins.md](plugins.md).
(`effectControls.prop.<uid>.value[.<d>]`), it runs `prop.pickWhip`: the reference replaces the
property's expression, or is added as one, and the expression is enabled.
* A property's menu (right-click its name; entries `timeline.prop.<uid>.menu.<entry>`): Reset
(`prop.reset`: no keyframes or expression, and the property's default value, an effect
parameter's or a Transform property's), Edit Value… (`prop.set {layer, prop}` without `value`
(`prop.reset`: no expression, and the property's default value, an effect parameter's or a
Transform property's; an animated property keeps its keyframes and gets the default as a
keyframe at the current time), Edit Value… (`prop.set {layer, prop}` without `value`
opens the value dialog), Separate Dimensions (Position: `prop.separateDimensions {layer,
value}`), Add / Remove Expression (`prop.setExpression {layer, prop}`) and Add Property to
Essential Graphics (`essential.addProperty`).