mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
Ease Presets: tests for Out alone through undo and redo, and a single key on a curved path (#1329)
Out on an auto-Bezier key leaves its in side playing the same values, and undo and redo restore each state. On a curved Position path with unequal segment lengths and durations, In sets the key's speed from the incoming path length, playback arrives faster than a constant speed, and the out side plays as before.
This commit is contained in:
@@ -413,6 +413,65 @@ fn roving_keyframes_are_skipped_and_reported() {
|
||||
assert!(eased(op.keys[1].in_ease[0], 0.0, 0.5) && eased(op.keys[1].out_ease[0], 0.0, 0.5));
|
||||
}
|
||||
|
||||
/// Out alone leaves an auto-Bezier in side playing as it did, and undo and redo restore each state.
|
||||
#[test]
|
||||
fn out_alone_keeps_the_in_side_playing_through_undo_and_redo() {
|
||||
let store = Arc::new(MemoryConfig::default());
|
||||
let mut s = session(&store);
|
||||
let l = setup(&mut s);
|
||||
animate(&mut s, l, "transform/rotation", &[(0.0, json!(0)), (1.0, json!(90)), (3.0, json!(30))]);
|
||||
ok(
|
||||
&mut s,
|
||||
r#"var r = app.project.activeItem.layer(1).transform.rotation, K = KeyframeInterpolationType;
|
||||
r.setInterpolationTypeAtKey(2, K.BEZIER, K.BEZIER);
|
||||
r.setTemporalAutoBezierAtKey(2, true);"#,
|
||||
);
|
||||
let before = prop(&s, l, "transform/rotation");
|
||||
let win = open_panel(&mut s);
|
||||
select_keys(&mut s, l, &[("transform/rotation", 1.0)]);
|
||||
apply_typed(&mut s, win, "Out", [60.0, 0.0, 33.0, 1.0]);
|
||||
let after = prop(&s, l, "transform/rotation");
|
||||
assert!(eased(after.keys[1].out_ease[0], 0.0, 0.6), "{:?}", after.keys[1].out_ease);
|
||||
for t in [0.25, 0.5, 0.75] {
|
||||
assert!(close(after.value_at(at(t)).as_f64(), before.value_at(at(t)).as_f64(), 1e-6), "the in side at {t}");
|
||||
}
|
||||
assert!(!close(after.value_at(at(2.0)).as_f64(), before.value_at(at(2.0)).as_f64(), 1e-3), "the out side changed");
|
||||
s.execute("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(prop(&s, l, "transform/rotation").keys, before.keys);
|
||||
s.execute("edit.redo", json!({})).unwrap();
|
||||
assert_eq!(prop(&s, l, "transform/rotation").keys, after.keys);
|
||||
}
|
||||
|
||||
/// On a curved path, a single key's in and out speeds follow the length of the path on each side
|
||||
/// (unequal lengths and durations), and the side not eased plays as it did.
|
||||
#[test]
|
||||
fn a_single_key_on_a_curved_path_eases_along_each_side() {
|
||||
let store = Arc::new(MemoryConfig::default());
|
||||
let mut s = session(&store);
|
||||
let l = setup(&mut s);
|
||||
animate(&mut s, l, "transform/position", &[(0.0, json!([0, 0, 0])), (1.0, json!([100, 0, 0])), (3.0, json!([100, 300, 0]))]);
|
||||
let before = prop(&s, l, "transform/position");
|
||||
let (len_in, len_out) = (effectcraft_keyframe::spatial_segment_length(&before.keys, 0), effectcraft_keyframe::spatial_segment_length(&before.keys, 1));
|
||||
let win = open_panel(&mut s);
|
||||
select_keys(&mut s, l, &[("transform/position", 1.0)]);
|
||||
apply_typed(&mut s, win, "In", [40.0, 1.5, 50.0, 2.0]);
|
||||
let pos = prop(&s, l, "transform/position");
|
||||
let k = &pos.keys[1];
|
||||
// In speed: twice the incoming segment's average (its path length over 1 s).
|
||||
assert!(k.in_ease.iter().all(|e| close(e.speed, 2.0 * len_in, 0.05 * len_in) && close(e.influence, 0.5, 1e-9)), "{:?} vs {len_in}", k.in_ease);
|
||||
// The out side (2 s along a longer path) plays as before.
|
||||
for t in [1.5, 2.0, 2.5] {
|
||||
let (a, b) = (pos.value_at(at(t)).as_vec2(), before.value_at(at(t)).as_vec2());
|
||||
assert!(close(a[0], b[0], 1e-6) && close(a[1], b[1], 1e-6), "out side at {t}: {a:?} vs {b:?}");
|
||||
}
|
||||
// Playback on the in side: arriving at twice the average speed, the last tenth of a second
|
||||
// covers more of the path than a constant speed would (len_in / 10).
|
||||
let (p9, p10) = (pos.value_at(at(0.9)).as_vec2(), pos.value_at(at(1.0)).as_vec2());
|
||||
let step = ((p10[0] - p9[0]).powi(2) + (p10[1] - p9[1]).powi(2)).sqrt();
|
||||
assert!(step > len_in / 10.0 * 1.2, "{step} vs {len_in}");
|
||||
assert!(len_out > len_in, "{len_out} {len_in}");
|
||||
}
|
||||
|
||||
/// On one key, each side scales to its own segment: per dimension, and along the motion path.
|
||||
#[test]
|
||||
fn single_keys_scale_each_side_to_its_dimensions_and_motion_path() {
|
||||
|
||||
Reference in New Issue
Block a user