From 7d4b0e3f0afde6f3046ce3d0eecdddfaf90561e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 12:34:48 +0200 Subject: [PATCH 01/11] Fix editor clock scene not re-enabling beatmap Could interfere with other tests due to causing crashes on attempts to change `Beatmap.Value`. --- osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs index 390198be04..0b1617b6a6 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs @@ -77,5 +77,11 @@ namespace osu.Game.Tests.Visual.Editing AddStep("start clock again", Clock.Start); AddAssert("clock looped to start", () => Clock.IsRunning && Clock.CurrentTime < 500); } + + protected override void Dispose(bool isDisposing) + { + Beatmap.Disabled = false; + base.Dispose(isDisposing); + } } } From b66ba43bc56f27a096912255c147d31453dba659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 14:02:15 +0200 Subject: [PATCH 02/11] Add failing test scene --- .../Visual/Editing/TestSceneEditorSeeking.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs new file mode 100644 index 0000000000..96ce418851 --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs @@ -0,0 +1,79 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Editing +{ + public class TestSceneEditorSeeking : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = base.CreateBeatmap(ruleset); + + beatmap.BeatmapInfo.BeatDivisor = 1; + + beatmap.ControlPointInfo = new ControlPointInfo(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); + beatmap.ControlPointInfo.Add(2000, new TimingControlPoint { BeatLength = 500 }); + + return beatmap; + } + + [Test] + public void TestSnappedSeeking() + { + AddStep("seek to 0", () => EditorClock.Seek(0)); + AddAssert("time is 0", () => EditorClock.CurrentTime == 0); + + pressAndCheckTime(Key.Right, 1000); + pressAndCheckTime(Key.Right, 2000); + pressAndCheckTime(Key.Right, 2500); + pressAndCheckTime(Key.Right, 3000); + + pressAndCheckTime(Key.Left, 2500); + pressAndCheckTime(Key.Left, 2000); + pressAndCheckTime(Key.Left, 1000); + } + + [Test] + public void TestSnappedSeekingAfterControlPointChange() + { + AddStep("seek to 0", () => EditorClock.Seek(0)); + AddAssert("time is 0", () => EditorClock.CurrentTime == 0); + + pressAndCheckTime(Key.Right, 1000); + pressAndCheckTime(Key.Right, 2000); + pressAndCheckTime(Key.Right, 2500); + pressAndCheckTime(Key.Right, 3000); + + AddStep("remove 2nd timing point", () => + { + EditorBeatmap.BeginChange(); + var group = EditorBeatmap.ControlPointInfo.GroupAt(2000); + EditorBeatmap.ControlPointInfo.RemoveGroup(group); + EditorBeatmap.EndChange(); + }); + + pressAndCheckTime(Key.Left, 2000); + pressAndCheckTime(Key.Left, 1000); + + pressAndCheckTime(Key.Right, 2000); + pressAndCheckTime(Key.Right, 3000); + } + + private void pressAndCheckTime(Key key, double expectedTime) + { + AddStep($"press {key}", () => InputManager.Key(key)); + AddUntilStep($"time is {expectedTime}", () => Precision.AlmostEquals(expectedTime, EditorClock.CurrentTime, 1)); + } + } +} From 4df7ff21c787fc3ebad631fb8d93331903b9c908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 11:43:47 +0200 Subject: [PATCH 03/11] Fix editor arrow seek snapping not updating after control point changes The editor clock, which is responsible for performing the seek, was not aware of changes in control points due to reading from the wrong beatmap. `loadableBeatmap` is not actually changed by any of the editor components; `playableBeatmap` and `editorBeatmap` are. For now this is changed to use `playableBeatmap`. A better follow-up would be to use `editorBeatmap`, but it would probably be best to move the beat snap bindable into `EditorBeatmap` first. --- osu.Game/Screens/Edit/Editor.cs | 32 +++++++++---------- osu.Game/Screens/Edit/EditorClock.cs | 8 ++--- osu.Game/Tests/Visual/EditorClockTestScene.cs | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 389eb79797..0759e21382 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -122,22 +122,6 @@ namespace osu.Game.Screens.Edit return; } - beatDivisor.Value = loadableBeatmap.BeatmapInfo.BeatDivisor; - beatDivisor.BindValueChanged(divisor => loadableBeatmap.BeatmapInfo.BeatDivisor = divisor.NewValue); - - // Todo: should probably be done at a DrawableRuleset level to share logic with Player. - clock = new EditorClock(loadableBeatmap, beatDivisor) { IsCoupled = false }; - - UpdateClockSource(); - - dependencies.CacheAs(clock); - AddInternal(clock); - - clock.SeekingOrStopped.BindValueChanged(_ => updateSampleDisabledState()); - - // todo: remove caching of this and consume via editorBeatmap? - dependencies.Cache(beatDivisor); - try { playableBeatmap = loadableBeatmap.GetPlayableBeatmap(loadableBeatmap.BeatmapInfo.Ruleset); @@ -154,6 +138,22 @@ namespace osu.Game.Screens.Edit return; } + beatDivisor.Value = playableBeatmap.BeatmapInfo.BeatDivisor; + beatDivisor.BindValueChanged(divisor => playableBeatmap.BeatmapInfo.BeatDivisor = divisor.NewValue); + + // Todo: should probably be done at a DrawableRuleset level to share logic with Player. + clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false }; + + UpdateClockSource(); + + dependencies.CacheAs(clock); + AddInternal(clock); + + clock.SeekingOrStopped.BindValueChanged(_ => updateSampleDisabledState()); + + // todo: remove caching of this and consume via editorBeatmap? + dependencies.Cache(beatDivisor); + AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.Skin)); dependencies.CacheAs(editorBeatmap); changeHandler = new EditorChangeHandler(editorBeatmap); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index d0197ce1ec..772f6ea192 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -42,12 +42,12 @@ namespace osu.Game.Screens.Edit /// public bool IsSeeking { get; private set; } - public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) - : this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor) + public EditorClock(IBeatmap beatmap, BindableBeatDivisor beatDivisor) + : this(beatmap.ControlPointInfo, beatDivisor) { } - public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor) + public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor) { this.beatDivisor = beatDivisor; @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Edit } public EditorClock() - : this(new ControlPointInfo(), 1000, new BindableBeatDivisor()) + : this(new ControlPointInfo(), new BindableBeatDivisor()) { } diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 693c9cb792..79cfee8518 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual protected EditorClockTestScene() { - Clock = new EditorClock(new ControlPointInfo(), 5000, BeatDivisor) { IsCoupled = false }; + Clock = new EditorClock(new ControlPointInfo(), BeatDivisor) { IsCoupled = false }; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From eb26f6f4273c638fac4be82a7a8535bcdf42a820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 21:45:11 +0200 Subject: [PATCH 04/11] Add failing test case --- .../Screens/TestSceneGameplayScreen.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index c1159dc000..522567584d 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -1,9 +1,13 @@ // Copyright (c) ppy Pty Ltd . 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.Testing; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Gameplay; +using osu.Game.Tournament.Screens.Gameplay.Components; namespace osu.Game.Tournament.Tests.Screens { @@ -18,5 +22,24 @@ namespace osu.Game.Tournament.Tests.Screens Add(new GameplayScreen()); Add(chat); } + + [Test] + public void TestWarmup() + { + checkScoreVisibility(false); + + toggleWarmup(); + checkScoreVisibility(true); + + toggleWarmup(); + checkScoreVisibility(false); + } + + private void checkScoreVisibility(bool visible) + => AddUntilStep($"scores {(visible ? "shown" : "hidden")}", + () => this.ChildrenOfType().All(score => score.Alpha == (visible ? 1 : 0))); + + private void toggleWarmup() + => AddStep("toggle warmup", () => this.ChildrenOfType().First().Click()); } } From 0d9793797ff07ceb9d9046eaa184e9863010967e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 21:46:34 +0200 Subject: [PATCH 05/11] Fix scores being initially visible incorrectly in gameplay screen --- .../Screens/Gameplay/Components/MatchHeader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index d790f4b754..8048425ce1 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -95,7 +95,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Origin = Anchor.TopRight, }, }; + } + protected override void LoadComplete() + { + base.LoadComplete(); updateDisplay(); } From 0febefd8eb187dc1f9e79d210ffd89dd17bac569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Apr 2021 22:24:55 +0200 Subject: [PATCH 06/11] Fix scores fading out on entering gameplay screen --- .../Gameplay/Components/TeamDisplay.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index 4ba86dcefc..59132bfd2d 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -14,9 +14,21 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { private readonly TeamScore score; + private bool showScore; + public bool ShowScore { - set => score.FadeTo(value ? 1 : 0, 200); + get => showScore; + set + { + if (showScore == value) + return; + + showScore = value; + + if (IsLoaded) + score.FadeTo(value ? 1 : 0, 200); + } } public TeamDisplay(TournamentTeam team, TeamColour colour, Bindable currentTeamScore, int pointsToWin) @@ -92,5 +104,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + score.Alpha = ShowScore ? 1 : 0; + } } } From d4724f4494e8184c4ad3d9ae6e262fe6f8da69b1 Mon Sep 17 00:00:00 2001 From: PercyDan54 <50285552+PercyDan54@users.noreply.github.com> Date: Sun, 4 Apr 2021 09:44:45 +0800 Subject: [PATCH 07/11] Fix crash --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index da1bbd18c7..795540b65d 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -391,7 +391,7 @@ namespace osu.Game.Online.Leaderboards if (score.Mods.Length > 0 && modsContainer.Any(s => s.IsHovered) && songSelect != null) items.Add(new OsuMenuItem("Use these mods", MenuItemType.Highlighted, () => songSelect.Mods.Value = score.Mods)); - if (score.Files.Count > 0) + if (score.Files?.Count > 0) items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(score))); if (score.ID != 0) From 5df27ce3d4e1131bcb8567626582bb256ee9b096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 4 Apr 2021 11:41:40 +0200 Subject: [PATCH 08/11] Split out score transform logic to method --- .../Screens/Gameplay/Components/TeamDisplay.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index 59132bfd2d..33658115cc 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components showScore = value; if (IsLoaded) - score.FadeTo(value ? 1 : 0, 200); + updateDisplay(); } } @@ -108,7 +108,14 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components protected override void LoadComplete() { base.LoadComplete(); - score.Alpha = ShowScore ? 1 : 0; + + updateDisplay(); + FinishTransforms(true); + } + + private void updateDisplay() + { + score.FadeTo(ShowScore ? 1 : 0, 200); } } } From 5f1f8ec0ef9d666fafa109196644691be877e713 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 4 Apr 2021 14:10:07 +0200 Subject: [PATCH 09/11] Fix IPC Source getting read from the incorrect location --- osu.Game.Tournament/Models/StableInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index d390f88d59..2dc47db26d 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -34,10 +34,10 @@ namespace osu.Game.Tournament.Models TournamentStorage tStorage = (TournamentStorage)storage; this.storage = tStorage.AllTournaments; - if (!storage.Exists(config_path)) + if (!this.storage.Exists(config_path)) return; - using (Stream stream = storage.GetStream(config_path, FileAccess.Read, FileMode.Open)) + using (Stream stream = this.storage.GetStream(config_path, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) { JsonConvert.PopulateObject(sr.ReadToEnd(), this); From 4ee8224f8b624320b52743c2e68986b795002388 Mon Sep 17 00:00:00 2001 From: Shivam Date: Sun, 4 Apr 2021 14:31:08 +0200 Subject: [PATCH 10/11] change naming to be less confusing --- osu.Game.Tournament/Models/StableInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 2dc47db26d..c0538ca587 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -27,17 +27,17 @@ namespace osu.Game.Tournament.Models private const string config_path = "stable.json"; - private readonly Storage storage; + private readonly Storage configStorage; public StableInfo(Storage storage) { TournamentStorage tStorage = (TournamentStorage)storage; - this.storage = tStorage.AllTournaments; + configStorage = tStorage.AllTournaments; - if (!this.storage.Exists(config_path)) + if (!configStorage.Exists(config_path)) return; - using (Stream stream = this.storage.GetStream(config_path, FileAccess.Read, FileMode.Open)) + using (Stream stream = configStorage.GetStream(config_path, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) { JsonConvert.PopulateObject(sr.ReadToEnd(), this); @@ -46,7 +46,7 @@ namespace osu.Game.Tournament.Models public void SaveChanges() { - using (var stream = storage.GetStream(config_path, FileAccess.Write, FileMode.Create)) + using (var stream = configStorage.GetStream(config_path, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { sw.Write(JsonConvert.SerializeObject(this, From 879b1ab046eefd501e82a8d4d4ce4baa124872ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Apr 2021 21:58:25 +0900 Subject: [PATCH 11/11] Avoid unnecessary casts --- osu.Game.Tournament.Tests/TournamentTestScene.cs | 3 ++- osu.Game.Tournament/Models/StableInfo.cs | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index cdfd19c157..1fa0ffc8e9 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -10,6 +10,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Tests.Visual; +using osu.Game.Tournament.IO; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; using osu.Game.Users; @@ -28,7 +29,7 @@ namespace osu.Game.Tournament.Tests protected MatchIPCInfo IPCInfo { get; private set; } = new MatchIPCInfo(); [BackgroundDependencyLoader] - private void load(Storage storage) + private void load(TournamentStorage storage) { Ladder.Ruleset.Value ??= rulesetStore.AvailableRulesets.First(); diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index c0538ca587..1ebc81c773 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -29,10 +29,9 @@ namespace osu.Game.Tournament.Models private readonly Storage configStorage; - public StableInfo(Storage storage) + public StableInfo(TournamentStorage storage) { - TournamentStorage tStorage = (TournamentStorage)storage; - configStorage = tStorage.AllTournaments; + configStorage = storage.AllTournaments; if (!configStorage.Exists(config_path)) return;