From b7329ee9047d47d80f3b3c8fd41f09f6c5236ab7 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:50:42 +0200 Subject: [PATCH] Keep unrelated overlapping clips untouched when deleting fades (#449) --- crates/engine/src/edit.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/edit.rs b/crates/engine/src/edit.rs index 5531953d..b26e14d8 100644 --- a/crates/engine/src/edit.rs +++ b/crates/engine/src/edit.rs @@ -812,8 +812,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 = 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; } @@ -821,11 +823,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); @@ -1041,4 +1044,23 @@ mod tests { s.find_clip_mut(id).unwrap().time_locked = true; assert_eq!(move_clips(&mut s, &[id], 500, &[]), 0); } + + #[test] + fn delete_fades_leaves_unrelated_overlaps_alone() { + let (mut s, t) = session_with_clip(); + let ids: Vec = (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)); + } }