Engine: Interpret Footage loop coverage for sequences (#1068)

Looped *video* footage had a regression (#1045); a grouped PNG sequence
going through the same path — interpret a fresh placeholder to Loop 15,
drag it onto the timeline — did not. The behaviour is already correct on
main (addItem sizes a sequence layer from looped_duration, the pool's
frame_index wraps per cycle), so this is coverage, not a change:
interpret_footage_loop_extends_sequence_layers asserts a 15-loop of a
0.4 s sequence lands a 6 s layer.

cargo test -p effectcraft-engine --lib interpret_footage: 4 passed.
This commit is contained in:
Vikram Bhaskaran
2026-10-14 02:15:32 +11:00
parent 549e9d8251
commit f12d75e37a
+25
View File
@@ -1556,6 +1556,31 @@ fn interpret_footage_loop_extends_video_layers() {
assert_eq!(s.project.item(effectcraft_project::ItemId(p)).unwrap().duration(), Some(Tick::from_seconds_f64(6.0)));
}
/// #1068: the same for an interpreted PNG sequence — the loop count survives interpretation and
/// a freshly dragged layer plays every cycle.
#[test]
fn interpret_footage_loop_extends_sequence_layers() {
let mut s = comp();
let p = s.execute("file.importPlaceholder", json!({"name": "Seq", "width": 320, "height": 240, "duration": 0.4})).unwrap()["item"].as_u64().unwrap();
let id = effectcraft_project::ItemId(p);
// Make it a sequence like the importer's grouped PNGs.
s.edit("Seq", None, |proj, _| {
if let Some(ItemKind::Footage(f)) = proj.item_mut(id).map(|i| &mut i.kind) {
f.kind = effectcraft_project::FootageKind::Sequence;
f.sequence = (0..12).map(|n| format!("/tmp/seq_{n:04}.png")).collect();
f.sync_sequence_duration();
}
Ok(())
})
.unwrap();
s.state.project_selection = vec![id];
s.execute("file.interpretFootage", json!({"loop": 15.0})).unwrap();
let l = s.execute("layer.addItem", json!({"item": p})).unwrap()["layer"].as_u64().unwrap();
let layer = s.active_comp().unwrap().layer(effectcraft_project::LayerId(l)).unwrap();
let dur = (layer.out_point - layer.in_point).seconds();
assert!((dur - 6.0).abs() < 0.05, "15 loops of a 0.4 s sequence: {dur}");
}
#[test]
fn percentage_guides_follow_the_comp_size() {
let mut s = comp();