diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs index 54dfb557fe..44d2c18dad 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -34,23 +34,62 @@ namespace osu.Game.Rulesets.Edit.Checks { if (breakPeriod.Duration < BreakPeriod.MIN_BREAK_DURATION) yield return new IssueTemplateTooShort(this).Create(breakPeriod.StartTime); - } - foreach (var hitObject in context.Beatmap.HitObjects) - { - foreach (var breakPeriod in context.Beatmap.Breaks) + var previousObject = getPreviousObject(breakPeriod.StartTime, context.Beatmap.HitObjects); + var nextObject = getNextObject(breakPeriod.EndTime, context.Beatmap.HitObjects); + + if (previousObject != null) { - double gapBeforeBreak = breakPeriod.StartTime - hitObject.GetEndTime(); - double gapAfterBreak = hitObject.StartTime - breakPeriod.EndTime; - - if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold && gapBeforeBreak > 0) + double gapBeforeBreak = breakPeriod.StartTime - previousObject.GetEndTime(); + if (gapBeforeBreak < minimum_gap_before_break - leniency_threshold) yield return new IssueTemplateEarlyStart(this).Create(breakPeriod.StartTime, minimum_gap_before_break - gapBeforeBreak); - else if (gapAfterBreak < min_end_threshold - leniency_threshold && gapAfterBreak > 0) + } + + if (nextObject != null) + { + double gapAfterBreak = nextObject.StartTime - breakPeriod.EndTime; + if (gapAfterBreak < min_end_threshold - leniency_threshold) yield return new IssueTemplateLateEnd(this).Create(breakPeriod.StartTime, min_end_threshold - gapAfterBreak); } } } + private HitObject? getPreviousObject(double time, IReadOnlyList hitObjects) + { + int left = 0; + int right = hitObjects.Count - 1; + + while (left <= right) + { + int mid = left + (right - left) / 2; + + if (hitObjects[mid].GetEndTime() < time) + left = mid + 1; + else + right = mid - 1; + } + + return right >= 0 ? hitObjects[right] : null; + } + + private HitObject? getNextObject(double time, IReadOnlyList hitObjects) + { + int left = 0; + int right = hitObjects.Count - 1; + + while (left <= right) + { + int mid = left + (right - left) / 2; + + if (hitObjects[mid].StartTime <= time) + left = mid + 1; + else + right = mid - 1; + } + + return left < hitObjects.Count ? hitObjects[left] : null; + } + public class IssueTemplateEarlyStart : IssueTemplate { public IssueTemplateEarlyStart(ICheck check)