Merge pull request #1737 from elZanco/fix/trim-out-keeps-playhead-frame

Timeline: trimming the Out point to the playhead keeps its frame visible
This commit is contained in:
BFlat
2026-10-30 04:08:36 +07:00
committed by GitHub
2 changed files with 25 additions and 1 deletions
+3 -1
View File
@@ -42,7 +42,9 @@ pub(super) fn timing(s: &mut Session, p: &Value) -> Result<Value> {
shift(l, d);
}
"trimInToTime" => l.in_point = t.min(l.out_point - fd),
"trimOutToTime" => l.out_point = t.max(l.in_point + fd),
// Alt+]: the Out edge lands one frame after the playhead, so its frame stays the
// layer's last visible one (as in After Effects), never before the In point.
"trimOutToTime" => l.out_point = t.max(l.in_point) + fd,
_ => {
if let Some(d) = delta {
shift(l, d);
+22
View File
@@ -184,6 +184,28 @@ fn in_and_out_points_stretch_to_the_current_time() {
assert!(s.execute("layer.timeStretch", json!({"to": "middle"})).is_err());
}
#[test]
fn trimming_out_to_the_playhead_keeps_its_frame_visible() {
let (mut s, ids) = session([(1.0, 9.0); 3]);
let frame = 1.0 / 30.0;
// Alt+] at 4 s: the Out edge lands one frame after the playhead, so 4 s is the layer's last
// visible frame — it must not be cut away at the playhead (as in After Effects).
s.execute("time.set", json!({"time": 4.0})).unwrap();
s.execute("layer.timing", json!({"layers": [ids[0]], "op": "trimOutToTime"})).unwrap();
assert!((span(&s, ids[0]).1 - (4.0 + frame)).abs() < 1e-9, "{:?}", span(&s, ids[0]));
// Alt+[ at 2 s: the playhead's frame becomes the layer's first visible one.
s.execute("time.set", json!({"time": 2.0})).unwrap();
s.execute("layer.timing", json!({"layers": [ids[1]], "op": "trimInToTime"})).unwrap();
assert!((span(&s, ids[1]).0 - 2.0).abs() < 1e-9, "{:?}", span(&s, ids[1]));
// Trimmed before the In point, the Out point keeps one frame of layer.
s.execute("time.set", json!({"time": 0.5})).unwrap();
s.execute("layer.timing", json!({"layers": [ids[2]], "op": "trimOutToTime"})).unwrap();
assert!((span(&s, ids[2]).1 - (1.0 + frame)).abs() < 1e-9, "{:?}", span(&s, ids[2]));
// One undo step back to the original span.
assert!(s.undo());
assert!((span(&s, ids[2]).1 - 9.0).abs() < 1e-9);
}
#[test]
fn masks_are_stepped_through_and_wrap() {
let (mut s, ids) = session([(0.0, 10.0); 3]);