From d25be223a5a44710b25c1d26afadb846baa8c9be Mon Sep 17 00:00:00 2001 From: Derrick Timmermans Date: Fri, 22 Jul 2022 18:50:23 +0200 Subject: [PATCH 1/3] Prevent SlideFans from having twins --- .../Beatmaps/SentakkiBeatmapConverter.cs | 80 +++++++++++++------ 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs index fd4512b1c..d015d506d 100644 --- a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs +++ b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs @@ -155,36 +155,20 @@ private IEnumerable convertSlider(HitObject original) twin = true; } + // See if we can convert to a slide object if (special && slider.Duration >= 350) { - List slides = new List(); - if (EnabledExperiments.HasFlag(ConversionExperiments.twinSlides)) + var result = tryConvertSliderToSlide(original, nodeSamples, twin, breakNote); + if (result.Any()) { - if (twin) - slides.Add((Slide)createSlideNote(original, nodeSamples, true, breakNote)); - else - foreach (var note in createTapsFromTicks(original, nodeSamples)) - yield return note; - } - - slides.Add((Slide)createSlideNote(original, nodeSamples, false, breakNote)); - - // Make sure duplicates are cleared - if (slides.Count == 2 && slides.First().Lane == slides.Last().Lane) - { - // Make sure that both slides patterns are unique - if (!slides.First().SlideInfoList.Exists(x => x.ID == slides.Last().SlideInfoList.First().ID)) - slides.First().SlideInfoList.AddRange(slides.Last().SlideInfoList); + foreach (var ho in result) + yield return ho; - slides.Remove(slides.Last()); + yield break; } - - foreach (var slide in slides) - yield return slide; - - yield break; } + // Fallback to hold notes if (EnabledExperiments.HasFlag(ConversionExperiments.twinNotes)) if (twin) yield return createHoldNote(original, nodeSamples, true, breakNote); @@ -195,6 +179,52 @@ private IEnumerable convertSlider(HitObject original) yield return createHoldNote(original, nodeSamples, false, breakNote); } + private IEnumerable tryConvertSliderToSlide(HitObject original, IList> nodeSamples, bool twin = false, bool isBreak = false) + { + List slides = new List(); + List taps = new List(); + if (EnabledExperiments.HasFlag(ConversionExperiments.twinSlides)) + { + if (twin) + slides.Add((Slide)createSlideNote(original, nodeSamples, true, isBreak)); + else + taps.AddRange(createTapsFromTicks(original, nodeSamples)); + } + + slides.Add((Slide)createSlideNote(original, nodeSamples, false, isBreak)); + + // Perform sanitization pass + if (slides.Count == 2) + { + // If there is a SlideFan, we always prioritize that, and ignore the rest + foreach (var slide in slides) + if (slide.SlideInfoList[0].ID == SlidePaths.FANID) + { + yield return slide; + yield break; + } + + // If both slides have the same start lane, we attempt to merge them + if (slides[0].Lane == slides[1].Lane) + { + // Make sure that both slides patterns are unique + if (slides[0].SlideInfoList[0].ID != slides[1].SlideInfoList[0].ID) + slides[0].SlideInfoList.AddRange(slides[1].SlideInfoList); + + slides.RemoveAt(1); + } + } + + if (slides.Count > 0) + { + foreach (var slide in slides) + yield return slide; + + foreach (var tap in taps) + yield return tap; + } + } + #endregion #region SentakkiHitObject creation methods @@ -260,7 +290,7 @@ private SentakkiHitObject createSlideNote(HitObject original, IList pathEnumerable = SlidePaths.VALIDPATHS.Where(p => ((IHasDuration)original).Duration >= p.Item1.MinDuration && ((IHasDuration)original).Duration <= p.Item1.MaxDuration); if (!EnabledExperiments.HasFlag(ConversionExperiments.fanSlides)) - pathEnumerable = pathEnumerable.Where(s => s != SlidePaths.VALIDPATHS.Last()); + pathEnumerable = pathEnumerable.Where(s => s != SlidePaths.VALIDPATHS[^1]); validPaths = pathEnumerable.ToList(); } @@ -285,7 +315,7 @@ private SentakkiHitObject createSlideNote(HitObject original, IList createTapsFromTicks(HitObject original, IList> nodeSamples) + private IEnumerable createTapsFromTicks(HitObject original, IList> nodeSamples) { if (original is not IHasPathWithRepeats) yield break; From 9fc2865fe4e2578f3ee5dcaa091cd0b18533658a Mon Sep 17 00:00:00 2001 From: Derrick Timmermans Date: Fri, 22 Jul 2022 18:51:32 +0200 Subject: [PATCH 2/3] Consider mirror flags as well when merging slides --- .../Beatmaps/SentakkiBeatmapConverter.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs index d015d506d..140bc90fe 100644 --- a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs +++ b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs @@ -207,8 +207,11 @@ private IEnumerable tryConvertSliderToSlide(HitObject origina // If both slides have the same start lane, we attempt to merge them if (slides[0].Lane == slides[1].Lane) { - // Make sure that both slides patterns are unique - if (slides[0].SlideInfoList[0].ID != slides[1].SlideInfoList[0].ID) + bool isSamePattern = slides[0].SlideInfoList[0].ID == slides[1].SlideInfoList[0].ID; + bool isSameOrientation = slides[0].SlideInfoList[0].Mirrored == slides[1].SlideInfoList[0].Mirrored; + + // We merge both slides only if they both have the same pattern AND orientation + if (!isSamePattern || !isSameOrientation) slides[0].SlideInfoList.AddRange(slides[1].SlideInfoList); slides.RemoveAt(1); From cb207d9ff26cf21d919c1a59b8ac13b16139b079 Mon Sep 17 00:00:00 2001 From: Derrick Timmermans Date: Sat, 23 Jul 2022 14:17:35 +0200 Subject: [PATCH 3/3] Fix bug causing SlideFan to still have twins --- .../Beatmaps/SentakkiBeatmapConverter.cs | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs index 140bc90fe..40e6e7a1e 100644 --- a/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs +++ b/osu.Game.Rulesets.Sentakki/Beatmaps/SentakkiBeatmapConverter.cs @@ -158,7 +158,7 @@ private IEnumerable convertSlider(HitObject original) // See if we can convert to a slide object if (special && slider.Duration >= 350) { - var result = tryConvertSliderToSlide(original, nodeSamples, twin, breakNote); + var result = tryConvertSliderToSlide(original, nodeSamples, twin, breakNote).ToList(); if (result.Any()) { foreach (var ho in result) @@ -193,29 +193,25 @@ private IEnumerable tryConvertSliderToSlide(HitObject origina slides.Add((Slide)createSlideNote(original, nodeSamples, false, isBreak)); - // Perform sanitization pass - if (slides.Count == 2) - { - // If there is a SlideFan, we always prioritize that, and ignore the rest - foreach (var slide in slides) - if (slide.SlideInfoList[0].ID == SlidePaths.FANID) - { - yield return slide; - yield break; - } - - // If both slides have the same start lane, we attempt to merge them - if (slides[0].Lane == slides[1].Lane) + // If there is a SlideFan, we always prioritize that, and ignore the rest + foreach (var slide in slides) + if (slide.SlideInfoList[0].ID == SlidePaths.FANID) { - bool isSamePattern = slides[0].SlideInfoList[0].ID == slides[1].SlideInfoList[0].ID; - bool isSameOrientation = slides[0].SlideInfoList[0].Mirrored == slides[1].SlideInfoList[0].Mirrored; + yield return slide; + yield break; + } - // We merge both slides only if they both have the same pattern AND orientation - if (!isSamePattern || !isSameOrientation) - slides[0].SlideInfoList.AddRange(slides[1].SlideInfoList); + // If both slides have the same start lane, we attempt to merge them + if (slides.Count == 2 && slides[0].Lane == slides[1].Lane) + { + bool isSamePattern = slides[0].SlideInfoList[0].ID == slides[1].SlideInfoList[0].ID; + bool isSameOrientation = slides[0].SlideInfoList[0].Mirrored == slides[1].SlideInfoList[0].Mirrored; - slides.RemoveAt(1); - } + // We merge both slides only if they both have the same pattern AND orientation + if (!isSamePattern || !isSameOrientation) + slides[0].SlideInfoList.AddRange(slides[1].SlideInfoList); + + slides.RemoveAt(1); } if (slides.Count > 0)