Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix breaks not showing unless already ordered in the beatmap file #28771

Merged
merged 4 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions osu.Game.Tests/Visual/Gameplay/TestSceneUnorderedBreaks.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
3 changes: 2 additions & 1 deletion osu.Game/Beatmaps/Beatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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
Expand Down Expand Up @@ -61,7 +62,7 @@ public Beatmap()

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>();

Expand Down
5 changes: 4 additions & 1 deletion osu.Game/Beatmaps/BeatmapConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
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;

Expand Down Expand Up @@ -50,7 +52,8 @@ public IBeatmap Convert(CancellationToken cancellationToken = default)
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);
}
Expand Down
3 changes: 2 additions & 1 deletion osu.Game/Beatmaps/IBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -40,7 +41,7 @@ public interface IBeatmap
/// <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.
Expand Down
14 changes: 13 additions & 1 deletion osu.Game/Beatmaps/Timing/BreakPeriod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

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.
Expand Down Expand Up @@ -76,5 +76,17 @@ public virtual bool Equals(BreakPeriod? other) =>
&& 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);
}
}
}
3 changes: 2 additions & 1 deletion osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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;
Expand Down Expand Up @@ -327,7 +328,7 @@ public BeatmapDifficulty Difficulty
set => baseBeatmap.Difficulty = value;
}

public List<BreakPeriod> Breaks
public SortedList<BreakPeriod> Breaks
{
get => baseBeatmap.Breaks;
set => baseBeatmap.Breaks = value;
Expand Down
9 changes: 7 additions & 2 deletions osu.Game/Screens/Edit/EditorBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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;
Expand Down Expand Up @@ -111,7 +112,11 @@ public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null, Beatmap
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 =>
Expand Down Expand Up @@ -177,7 +182,7 @@ public ControlPointInfo ControlPointInfo

public readonly BindableList<BreakPeriod> Breaks;

List<BreakPeriod> IBeatmap.Breaks
SortedList<BreakPeriod> IBeatmap.Breaks
{
get => PlayableBeatmap.Breaks;
set => PlayableBeatmap.Breaks = value;
Expand Down
Loading