Merge PR #8 from storybored379
Timeline: Slide moves linked audio with the video Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
d0048b0256
|
|
@ -1793,7 +1793,21 @@ fn build() -> Vec<CommandSpec> {
|
|||
.map(Tick)
|
||||
.or_else(|| p.get("deltaFrames").and_then(Value::as_i64).map(|f| s.sequence_rate().tick_of(f)))
|
||||
.unwrap_or_default();
|
||||
s.edit_sequence("Slide", |q, ctx, _| Ok(edit::slide(q, c, d, ctx)?))?;
|
||||
let clips = with_links(s, &[c]);
|
||||
s.edit_sequence("Slide", |q, ctx, _| {
|
||||
// clamp across all linked partners, then slide them by the common delta
|
||||
let mut dd = d;
|
||||
for c in &clips {
|
||||
let x = edit::slide(&mut q.clone(), *c, dd, ctx)?;
|
||||
if x.abs() < dd.abs() {
|
||||
dd = x;
|
||||
}
|
||||
}
|
||||
for c in &clips {
|
||||
edit::slide(q, *c, dd, ctx)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(Value::Null)
|
||||
}),
|
||||
cmd!("timeline.rateStretch", "Rate Stretch", [], None, r#"{"clip":id,"edge":"in|out","delta":ticks}"#, has_seq, |s, p| {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,18 @@ fn trim_linked_and_ripple_delete() {
|
|||
assert_eq!(q.video_tracks[0].items[0].start, s.sequence_rate().tick_of(12), "the trim gap remains");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slide_moves_linked_audio_with_the_video() {
|
||||
let mut s = demo();
|
||||
let v = s.active_sequence().unwrap().video_tracks[0].items[1].clone();
|
||||
s.execute("timeline.slide", json!({"clip": v.id.0, "deltaFrames": 5})).unwrap();
|
||||
let q = s.active_sequence().unwrap();
|
||||
let (_, nv) = q.find_item(v.id).unwrap();
|
||||
let a = q.audio_tracks[0].items.iter().find(|i| i.link == v.link).unwrap();
|
||||
assert_eq!(nv.start, v.start + s.sequence_rate().tick_of(5));
|
||||
assert_eq!((a.start, a.source_in), (nv.start, nv.source_in), "linked audio slides too and stays in sync");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_fps_is_refused() {
|
||||
let mut s = demo();
|
||||
|
|
|
|||
Loading…
Reference in New Issue