diff --git a/crates/engine/src/edit.rs b/crates/engine/src/edit.rs index c32f8767..900dfe39 100644 --- a/crates/engine/src/edit.rs +++ b/crates/engine/src/edit.rs @@ -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 = 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 = (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)); + } }