1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 12:33:01 +08:00

Merge pull request #28771 from frenzibyte/sorted-breaks

Fix breaks not showing unless already ordered in the beatmap file
This commit is contained in:
Bartłomiej Dach 2024-07-08 16:46:50 +02:00 committed by GitHub
commit 4dd20ccf79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 100 additions and 7 deletions

View File

@ -0,0 +1,70 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Play;
using osu.Game.Storyboards;
namespace osu.Game.Tests.Visual.Gameplay
{
public partial class TestSceneUnorderedBreaks : OsuPlayerTestScene
{
[Resolved]
private AudioManager audioManager { get; set; } = null!;
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{
var beatmap = new OsuBeatmap();
beatmap.HitObjects.Add(new HitCircle { StartTime = 0 });
beatmap.HitObjects.Add(new HitCircle { StartTime = 5000 });
beatmap.HitObjects.Add(new HitCircle { StartTime = 10000 });
beatmap.Breaks.Add(new BreakPeriod(6000, 9000));
beatmap.Breaks.Add(new BreakPeriod(1000, 4000));
return beatmap;
}
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) =>
new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager);
[SetUpSteps]
public override void SetUpSteps()
{
base.SetUpSteps();
AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning);
}
[Test]
public void TestBreakOverlayVisibility()
{
AddAssert("break overlay hidden", () => !this.ChildrenOfType<BreakOverlay>().Single().Child.IsPresent);
addSeekStep(2000);
AddUntilStep("break overlay visible", () => this.ChildrenOfType<BreakOverlay>().Single().Child.IsPresent);
addSeekStep(5000);
AddAssert("break overlay hidden", () => !this.ChildrenOfType<BreakOverlay>().Single().Child.IsPresent);
addSeekStep(7000);
AddUntilStep("break overlay visible", () => this.ChildrenOfType<BreakOverlay>().Single().Child.IsPresent);
addSeekStep(10000);
AddAssert("break overlay hidden", () => !this.ChildrenOfType<BreakOverlay>().Single().Child.IsPresent);
}
private void addSeekStep(double time)
{
AddStep($"seek to {time}", () => Beatmap.Value.Track.Seek(time));
// Allow a few frames of lenience
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
}
}
}

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps.ControlPoints;
using Newtonsoft.Json;
using osu.Framework.Lists;
using osu.Game.IO.Serialization.Converters;
namespace osu.Game.Beatmaps
@ -61,7 +62,7 @@ namespace osu.Game.Beatmaps
public ControlPointInfo ControlPointInfo { get; set; } = new ControlPointInfo();
public List<BreakPeriod> Breaks { get; set; } = new List<BreakPeriod>();
public SortedList<BreakPeriod> Breaks { get; set; } = new SortedList<BreakPeriod>(Comparer<BreakPeriod>.Default);
public List<string> UnhandledEventLines { get; set; } = new List<string>();

View File

@ -7,6 +7,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using osu.Framework.Lists;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Objects;
@ -50,7 +52,8 @@ namespace osu.Game.Beatmaps
original.ControlPointInfo = original.ControlPointInfo.DeepClone();
// Used in osu!mania conversion.
original.Breaks = original.Breaks.ToList();
original.Breaks = new SortedList<BreakPeriod>(Comparer<BreakPeriod>.Default);
original.Breaks.AddRange(Beatmap.Breaks);
return ConvertBeatmap(original, cancellationToken);
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Lists;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects;
@ -40,7 +41,7 @@ namespace osu.Game.Beatmaps
/// <summary>
/// The breaks in this beatmap.
/// </summary>
List<BreakPeriod> Breaks { get; set; }
SortedList<BreakPeriod> Breaks { get; set; }
/// <summary>
/// All lines from the [Events] section which aren't handled in the encoding process yet.

View File

@ -6,7 +6,7 @@ using osu.Game.Screens.Play;
namespace osu.Game.Beatmaps.Timing
{
public class BreakPeriod : IEquatable<BreakPeriod>
public class BreakPeriod : IEquatable<BreakPeriod>, IComparable<BreakPeriod>
{
/// <summary>
/// The minimum gap between the start of the break and the previous object.
@ -76,5 +76,17 @@ namespace osu.Game.Beatmaps.Timing
&& EndTime == other.EndTime;
public override int GetHashCode() => HashCode.Combine(StartTime, EndTime);
public int CompareTo(BreakPeriod? other)
{
if (ReferenceEquals(this, other)) return 0;
if (ReferenceEquals(null, other)) return 1;
int result = StartTime.CompareTo(other.StartTime);
if (result != 0)
return result;
return EndTime.CompareTo(other.EndTime);
}
}
}

View File

@ -10,6 +10,7 @@ using System.Threading;
using JetBrains.Annotations;
using osu.Framework.Audio.Track;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Lists;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Timing;
@ -327,7 +328,7 @@ namespace osu.Game.Rulesets.Difficulty
set => baseBeatmap.Difficulty = value;
}
public List<BreakPeriod> Breaks
public SortedList<BreakPeriod> Breaks
{
get => baseBeatmap.Breaks;
set => baseBeatmap.Breaks = value;

View File

@ -10,6 +10,7 @@ using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Lists;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
@ -111,7 +112,11 @@ namespace osu.Game.Screens.Edit
trackStartTime(obj);
Breaks = new BindableList<BreakPeriod>(playableBeatmap.Breaks);
Breaks.BindCollectionChanged((_, _) => playableBeatmap.Breaks = Breaks.ToList());
Breaks.BindCollectionChanged((_, _) =>
{
playableBeatmap.Breaks.Clear();
playableBeatmap.Breaks.AddRange(Breaks);
});
PreviewTime = new BindableInt(BeatmapInfo.Metadata.PreviewTime);
PreviewTime.BindValueChanged(s =>
@ -177,7 +182,7 @@ namespace osu.Game.Screens.Edit
public readonly BindableList<BreakPeriod> Breaks;
List<BreakPeriod> IBeatmap.Breaks
SortedList<BreakPeriod> IBeatmap.Breaks
{
get => PlayableBeatmap.Breaks;
set => PlayableBeatmap.Breaks = value;