Merge PR #518: Keep unrelated overlapping clips untouched when deleting fades (#449)

crates/engine/src/edit.rs: kept both tests; delete_fades body merged without conflict.
This commit is contained in:
aiongg
2026-10-24 06:17:53 +00:00
+24 -2
View File
@@ -818,8 +818,10 @@ pub fn create_fades(s: &mut Session, track: TrackId, range: Range, shape: FadeSh
pub fn delete_fades(s: &mut Session, track: TrackId, range: Range) -> usize {
let Some(pl) = s.track_mut(track).and_then(|t| t.playlist_mut()) else { return 0 };
let mut n = 0;
let mut touched: HashSet<ClipId> = HashSet::new();
for c in &mut pl.clips {
if c.range().overlaps(&range) || (range.is_empty() && c.range().contains(range.start)) {
touched.insert(c.id);
if c.fade_in.len > 0 || c.fade_out.len > 0 {
n += 1;
}
@@ -827,11 +829,12 @@ pub fn delete_fades(s: &mut Session, track: TrackId, range: Range) -> usize {
c.fade_out = Fade::default();
}
}
// Overlapping (crossfaded) neighbours are trimmed back to the midpoint.
// Overlapping (crossfaded) neighbours in the range are trimmed back to the midpoint; other overlaps stay as they are.
pl.sort();
for i in 0..pl.clips.len().saturating_sub(1) {
let (Some(a_end), Some(b_start)) = (pl.clips.get(i).map(Clip::end), pl.clips.get(i + 1).map(|c| c.start)) else { continue };
if a_end > b_start {
let in_range = pl.clips.get(i).is_some_and(|a| touched.contains(&a.id)) || pl.clips.get(i + 1).is_some_and(|b| touched.contains(&b.id));
if in_range && a_end > b_start {
let mid = b_start + (a_end - b_start) / 2;
if let Some(a) = pl.clips.get_mut(i) {
a.trim_end_to(mid);
@@ -1108,4 +1111,23 @@ mod tests {
assert!(got.windows(2).all(|w| w[0].0 <= w[1].0), "playlist not sorted: {got:?}");
assert!(got.iter().all(|c| c.1 > 0), "empty clip: {got:?}");
}
#[test]
fn delete_fades_leaves_unrelated_overlaps_alone() {
let (mut s, t) = session_with_clip();
let ids: Vec<ClipId> = (0..4).map(|_| s.new_clip_id()).collect();
if let Some(pl) = s.track_mut(t).and_then(|t| t.playlist_mut()) {
pl.clips.clear();
for (id, start, len) in [(ids[0], 0, 1100), (ids[1], 1000, 1000), (ids[2], 5000, 1100), (ids[3], 6000, 1000)] {
let mut c = Clip::audio(id, "c", SourceId(500), start, start, len);
c.fade_in = Fade { len: 100, shape: FadeShape::Linear, curvature: 0.0 };
c.fade_out = Fade { len: 100, shape: FadeShape::Linear, curvature: 0.0 };
pl.clips.push(c);
}
}
assert_eq!(delete_fades(&mut s, t, Range::new(900, 1200)), 2);
assert_eq!(clips(&s, t), vec![(0, 1050, 0), (1050, 950, 1050), (5000, 1100, 5000), (6000, 1000, 6000)]);
let c = s.track(t).unwrap().clips();
assert_eq!((c[1].fade_in.len, c[2].fade_out.len, c[3].fade_in.len), (0, 100, 100));
}
}