From 0f08c2a4799d3002861b199205c0e20e4498ff23 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 11:44:29 +0300 Subject: [PATCH 01/47] Add star rating display underneath the beatmap metadata --- .../Screens/Play/BeatmapMetadataDisplay.cs | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index c56344a8fb..7ad634afed 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -12,8 +12,10 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Ranking.Expanded; using osuTK; namespace osu.Game.Screens.Play @@ -30,6 +32,9 @@ namespace osu.Game.Screens.Play public IBindable> Mods => mods; + [Resolved] + private IBindable ruleset { get; set; } + public bool Loading { set @@ -51,10 +56,12 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load() + private void load(BeatmapDifficultyCache difficultyCache) { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + var starDifficulty = difficultyCache.GetDifficultyAsync(beatmap.BeatmapInfo, ruleset.Value, mods.Value).Result; + AutoSizeAxes = Axes.Both; Children = new Drawable[] { @@ -107,16 +114,29 @@ namespace osu.Game.Screens.Play loading = new LoadingLayer(true) } }, - new OsuSpriteText + new FillFlowContainer { - Text = beatmap?.BeatmapInfo?.Version, - Font = OsuFont.GetFont(size: 26, italics: true), - Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, - Margin = new MarginPadding + Origin = Anchor.TopCentre, + Direction = FillDirection.Vertical, + Spacing = new Vector2(5f), + Margin = new MarginPadding { Bottom = 40 }, + Children = new Drawable[] { - Bottom = 40 - }, + new OsuSpriteText + { + Text = beatmap?.BeatmapInfo?.Version, + Font = OsuFont.GetFont(size: 26, italics: true), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + new StarRatingDisplay(starDifficulty) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } + } }, new GridContainer { From 7b7e7a86bf70423464fa078b10b52301790ad5dc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 11:46:28 +0300 Subject: [PATCH 02/47] Allow null logo facade --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 7ad634afed..8e760c38ba 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -27,7 +28,7 @@ namespace osu.Game.Screens.Play { private readonly WorkingBeatmap beatmap; private readonly Bindable> mods; - private readonly Drawable facade; + private readonly Drawable logoFacade; private LoadingSpinner loading; public IBindable> Mods => mods; @@ -46,10 +47,10 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable facade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, [CanBeNull] Drawable logoFacade) { this.beatmap = beatmap; - this.facade = facade; + this.logoFacade = logoFacade; this.mods = new Bindable>(); this.mods.BindTo(mods); @@ -73,11 +74,11 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Vertical, Children = new[] { - facade.With(d => + logoFacade?.With(d => { d.Anchor = Anchor.TopCentre; d.Origin = Anchor.TopCentre; - }), + }) ?? Drawable.Empty(), new OsuSpriteText { Text = new RomanisableString(metadata.TitleUnicode, metadata.Title), From 169a28340286aeca24e73f47ce76c190c3f7c87d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 11:46:42 +0300 Subject: [PATCH 03/47] Add visual test scene --- .../TestSceneBeatmapMetadataDisplay.cs | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs new file mode 100644 index 0000000000..02c9c6b7a3 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -0,0 +1,78 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play; +using osuTK; + +namespace osu.Game.Tests.Visual.SongSelect +{ + [System.ComponentModel.Description("player loader beatmap metadata")] + public class TestSceneBeatmapMetadataDisplay : OsuTestScene + { + private BeatmapMetadataDisplay display; + + [Resolved] + private BeatmapManager manager { get; set; } + + private IReadOnlyList randomMods => Ruleset.Value.CreateInstance() + .GetAllMods() + .OrderBy(_ => RNG.Next()) + .Take(5) + .ToList(); + + private void createDisplay(Func getBeatmap) + { + AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), null) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.5f), + }); + + AddToggleStep("trigger loading", v => display.Loading = v); + } + + [Test] + public void TestLocal([Values("Beatmap", "Some long title and stuff")] + string title, + [Values("Trial", "Some1's very hardest difficulty")] + string version) + { + createDisplay(() => CreateWorkingBeatmap(new Beatmap + { + BeatmapInfo = + { + Metadata = new BeatmapMetadata + { + Title = title, + }, + Version = version, + StarDifficulty = RNG.NextDouble(0, 10), + } + })); + } + + [Test] + public void TestRandomFromDatabase() + { + createDisplay(() => + { + var allBeatmapSets = manager.GetAllUsableBeatmapSets(IncludedDetails.Minimal); + var randomBeatmapSet = allBeatmapSets[RNG.Next(0, allBeatmapSets.Count - 1)]; + var randomBeatmap = randomBeatmapSet.Beatmaps[RNG.Next(0, randomBeatmapSet.Beatmaps.Count - 1)]; + + return manager.GetWorkingBeatmap(randomBeatmap); + }); + } + } +} From b4801faf32bed6a2bc279305d4237930f60a683d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 11:57:12 +0300 Subject: [PATCH 04/47] Pass ruleset info to constructor instead Follows the way working beatmap is passed, not sure why mods are passed as a bindable though, don't wanna bother too much with that. --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 2 +- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 9 ++++----- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 02c9c6b7a3..ee87877860 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void createDisplay(Func getBeatmap) { - AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), null) + AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), Ruleset.Value, new Bindable>(randomMods), null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 8e760c38ba..daaf3b73cb 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -27,15 +27,13 @@ namespace osu.Game.Screens.Play public class BeatmapMetadataDisplay : Container { private readonly WorkingBeatmap beatmap; + private readonly RulesetInfo ruleset; private readonly Bindable> mods; private readonly Drawable logoFacade; private LoadingSpinner loading; public IBindable> Mods => mods; - [Resolved] - private IBindable ruleset { get; set; } - public bool Loading { set @@ -47,9 +45,10 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, [CanBeNull] Drawable logoFacade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, RulesetInfo ruleset, Bindable> mods, [CanBeNull] Drawable logoFacade) { this.beatmap = beatmap; + this.ruleset = ruleset; this.logoFacade = logoFacade; this.mods = new Bindable>(); @@ -61,7 +60,7 @@ namespace osu.Game.Screens.Play { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); - var starDifficulty = difficultyCache.GetDifficultyAsync(beatmap.BeatmapInfo, ruleset.Value, mods.Value).Result; + var starDifficulty = difficultyCache.GetDifficultyAsync(beatmap.BeatmapInfo, ruleset, mods.Value).Result; AutoSizeAxes = Axes.Both; Children = new Drawable[] diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ce580e2b53..066ca25790 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -134,7 +134,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, }).WithChildren(new Drawable[] { - MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Mods, content.LogoFacade) + MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Ruleset.Value, Mods, content.LogoFacade) { Alpha = 0, Anchor = Anchor.Centre, From 0410edecaff273d81d023af07044bbd46a88b9a5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 12:55:07 +0300 Subject: [PATCH 05/47] Refactor `StarRatingDisplay` to be mutable with a current bindable --- .../Ranking/TestSceneStarRatingDisplay.cs | 15 +++- .../Ranking/Expanded/StarRatingDisplay.cs | 87 ++++++++++++------- 2 files changed, 68 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index d0067c3396..a043f506c1 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -1,8 +1,10 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Screens.Ranking.Expanded; @@ -10,8 +12,11 @@ namespace osu.Game.Tests.Visual.Ranking { public class TestSceneStarRatingDisplay : OsuTestScene { - public TestSceneStarRatingDisplay() + [SetUp] + public void SetUp() => Schedule(() => { + StarRatingDisplay changingStarRating; + Child = new FillFlowContainer { Anchor = Anchor.Centre, @@ -25,8 +30,14 @@ namespace osu.Game.Tests.Visual.Ranking new StarRatingDisplay(new StarDifficulty(5.67, 0)), new StarRatingDisplay(new StarDifficulty(6.78, 0)), new StarRatingDisplay(new StarDifficulty(10.11, 0)), + changingStarRating = new StarRatingDisplay(), } }; - } + + Scheduler.AddDelayed(() => + { + changingStarRating.Current.Value = new StarDifficulty(RNG.NextDouble(0, 10), RNG.Next()); + }, 500, true); + }); } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index f7e50fdc8a..a1f48fa811 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -3,12 +3,14 @@ using System.Globalization; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -20,17 +22,29 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A pill that displays the star rating of a . /// - public class StarRatingDisplay : CompositeDrawable + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { - private readonly StarDifficulty difficulty; + private Box background; + private OsuTextFlowContainer textFlow; + + [Resolved] + private OsuColour colours { get; set; } + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } /// /// Creates a new using an already computed . /// /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty) + public StarRatingDisplay(StarDifficulty starDifficulty = default) { - difficulty = starDifficulty; + Current.Value = starDifficulty; } [BackgroundDependencyLoader] @@ -38,15 +52,6 @@ namespace osu.Game.Screens.Ranking.Expanded { AutoSizeAxes = Axes.Both; - var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - - ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); - InternalChildren = new Drawable[] { new CircularContainer @@ -55,10 +60,9 @@ namespace osu.Game.Screens.Ranking.Expanded Masking = true, Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = backgroundColour }, } }, @@ -78,32 +82,51 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, TextAnchor = Anchor.BottomLeft, - }.With(t => - { - t.AddText($"{wholePart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - t.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }) + } } } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + Current.BindValueChanged(difficulty => updateDisplay(difficulty.NewValue), true); + } + + private void updateDisplay(StarDifficulty difficulty) + { + var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + string wholePart = starRatingParts[0]; + string fractionPart = starRatingParts[1]; + string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + + background.Colour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + + textFlow.Clear(); + + textFlow.AddText($"{wholePart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + + textFlow.AddText($"{separator}{fractionPart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + } } } From 43090067da8a199eca6e2d4202d0bef1eae7fe5c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 12:59:59 +0300 Subject: [PATCH 06/47] Use `BeatmapDifficultyCache.GetBindableDifficulty(...)` instead --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index daaf3b73cb..54c739bd9f 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -55,12 +55,14 @@ namespace osu.Game.Screens.Play this.mods.BindTo(mods); } + private IBindable starDifficulty; + [BackgroundDependencyLoader] private void load(BeatmapDifficultyCache difficultyCache) { - var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + StarRatingDisplay starRatingDisplay; - var starDifficulty = difficultyCache.GetDifficultyAsync(beatmap.BeatmapInfo, ruleset, mods.Value).Result; + var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); AutoSizeAxes = Axes.Both; Children = new Drawable[] @@ -131,7 +133,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - new StarRatingDisplay(starDifficulty) + starRatingDisplay = new StarRatingDisplay { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -179,6 +181,13 @@ namespace osu.Game.Screens.Play } }; + starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo); + starDifficulty.BindValueChanged(difficulty => + { + if (difficulty.NewValue is StarDifficulty diff) + starRatingDisplay.Current.Value = diff; + }, true); + Loading = true; } From dca5efc59afc5876b794e6cb3610e4cb18f3a64d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 13:00:39 +0300 Subject: [PATCH 07/47] Remove no longer necessary ruleset info requirement --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 2 +- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 5 +---- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index ee87877860..02c9c6b7a3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void createDisplay(Func getBeatmap) { - AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), Ruleset.Value, new Bindable>(randomMods), null) + AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 54c739bd9f..670d99c462 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -13,7 +13,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Ranking.Expanded; @@ -27,7 +26,6 @@ namespace osu.Game.Screens.Play public class BeatmapMetadataDisplay : Container { private readonly WorkingBeatmap beatmap; - private readonly RulesetInfo ruleset; private readonly Bindable> mods; private readonly Drawable logoFacade; private LoadingSpinner loading; @@ -45,10 +43,9 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, RulesetInfo ruleset, Bindable> mods, [CanBeNull] Drawable logoFacade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, [CanBeNull] Drawable logoFacade) { this.beatmap = beatmap; - this.ruleset = ruleset; this.logoFacade = logoFacade; this.mods = new Bindable>(); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 066ca25790..ce580e2b53 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -134,7 +134,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, }).WithChildren(new Drawable[] { - MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Ruleset.Value, Mods, content.LogoFacade) + MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Mods, content.LogoFacade) { Alpha = 0, Anchor = Anchor.Centre, From 26c0010fe659915ebebb152be37032b6003b4ff3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 13:03:50 +0300 Subject: [PATCH 08/47] Fix test not handling 0 beatmap sets --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 02c9c6b7a3..5ea7a0e83b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -68,6 +68,9 @@ namespace osu.Game.Tests.Visual.SongSelect createDisplay(() => { var allBeatmapSets = manager.GetAllUsableBeatmapSets(IncludedDetails.Minimal); + if (allBeatmapSets.Count == 0) + return manager.DefaultBeatmap; + var randomBeatmapSet = allBeatmapSets[RNG.Next(0, allBeatmapSets.Count - 1)]; var randomBeatmap = randomBeatmapSet.Beatmaps[RNG.Next(0, randomBeatmapSet.Beatmaps.Count - 1)]; From d9605e807049ceabb9af5a53568738a1a424c341 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:18:23 +0300 Subject: [PATCH 09/47] Remove test scene description --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 5ea7a0e83b..381ccd2dd3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -16,7 +16,6 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - [System.ComponentModel.Description("player loader beatmap metadata")] public class TestSceneBeatmapMetadataDisplay : OsuTestScene { private BeatmapMetadataDisplay display; From 3575d9847cd120941ad3737ff140c01184edd4e5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:21:29 +0300 Subject: [PATCH 10/47] Use regular test steps rather than one-time set up and scheduling --- .../Visual/Ranking/TestSceneStarRatingDisplay.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index a043f506c1..2ff664a0d9 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -12,12 +12,12 @@ namespace osu.Game.Tests.Visual.Ranking { public class TestSceneStarRatingDisplay : OsuTestScene { - [SetUp] - public void SetUp() => Schedule(() => + [Test] + public void TestDisplay() { - StarRatingDisplay changingStarRating; + StarRatingDisplay changingStarRating = null; - Child = new FillFlowContainer + AddStep("load displays", () => Child = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -32,12 +32,12 @@ namespace osu.Game.Tests.Visual.Ranking new StarRatingDisplay(new StarDifficulty(10.11, 0)), changingStarRating = new StarRatingDisplay(), } - }; + }); - Scheduler.AddDelayed(() => + AddRepeatStep("change bottom rating", () => { changingStarRating.Current.Value = new StarDifficulty(RNG.NextDouble(0, 10), RNG.Next()); - }, 500, true); - }); + }, 10); + } } } From a75347cb2a5dc933b9f2952d3449208379eee935 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:43:17 +0300 Subject: [PATCH 11/47] Remove nullable facade logic --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 670d99c462..98829d079b 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -43,7 +42,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, [CanBeNull] Drawable logoFacade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable logoFacade) { this.beatmap = beatmap; this.logoFacade = logoFacade; @@ -72,11 +71,11 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Vertical, Children = new[] { - logoFacade?.With(d => + logoFacade.With(d => { d.Anchor = Anchor.TopCentre; d.Origin = Anchor.TopCentre; - }) ?? Drawable.Empty(), + }), new OsuSpriteText { Text = new RomanisableString(metadata.TitleUnicode, metadata.Title), From ca55287dd07a9d958e35c738d331dad21b8295ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:43:45 +0300 Subject: [PATCH 12/47] Pass empty facade and replace random property with method instead --- .../SongSelect/TestSceneBeatmapMetadataDisplay.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 381ccd2dd3..552d19ac26 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -23,15 +23,9 @@ namespace osu.Game.Tests.Visual.SongSelect [Resolved] private BeatmapManager manager { get; set; } - private IReadOnlyList randomMods => Ruleset.Value.CreateInstance() - .GetAllMods() - .OrderBy(_ => RNG.Next()) - .Take(5) - .ToList(); - private void createDisplay(Func getBeatmap) { - AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), null) + AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(getRandomMods()), Empty()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -76,5 +70,11 @@ namespace osu.Game.Tests.Visual.SongSelect return manager.GetWorkingBeatmap(randomBeatmap); }); } + + private IReadOnlyList getRandomMods() => Ruleset.Value.CreateInstance() + .GetAllMods() + .OrderBy(_ => RNG.Next()) + .Take(5) + .ToList(); } } From 655e8d3d867c5a2956caeea928e0704c98b580e6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:44:28 +0300 Subject: [PATCH 13/47] Remove pattern-matching on nullable with simple `.HasValue`/`.Value` --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 98829d079b..d31033ef15 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -180,8 +180,8 @@ namespace osu.Game.Screens.Play starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo); starDifficulty.BindValueChanged(difficulty => { - if (difficulty.NewValue is StarDifficulty diff) - starRatingDisplay.Current.Value = diff; + if (difficulty.NewValue.HasValue) + starRatingDisplay.Current.Value = difficulty.NewValue.Value; }, true); Loading = true; From c52f1733be73b49af4f3dea4257fd0b9eaa5610a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 21:13:18 +0300 Subject: [PATCH 14/47] Apply further refactoring to star rating display UX-wise --- .../Screens/Play/BeatmapMetadataDisplay.cs | 6 +- .../Ranking/Expanded/StarRatingDisplay.cs | 106 +++++++++++++----- 2 files changed, 77 insertions(+), 35 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index d31033ef15..0164fe9179 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -178,11 +178,7 @@ namespace osu.Game.Screens.Play }; starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo); - starDifficulty.BindValueChanged(difficulty => - { - if (difficulty.NewValue.HasValue) - starRatingDisplay.Current.Value = difficulty.NewValue.Value; - }, true); + starDifficulty.BindValueChanged(d => starRatingDisplay.Current.Value = d.NewValue, true); Loading = true; } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index a1f48fa811..77c43ad863 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -22,27 +22,50 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A pill that displays the star rating of a . /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private Box background; - private OsuTextFlowContainer textFlow; + private OsuSpriteText wholePart; + private OsuSpriteText fractionPart; + + private double displayedStarRating; + + protected double DisplayedStarRating + { + get => displayedStarRating; + set + { + displayedStarRating = value; + + var starRatingParts = value.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + wholePart.Text = starRatingParts[0]; + fractionPart.Text = starRatingParts[1]; + } + } [Resolved] private OsuColour colours { get; set; } - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; } + /// + /// Creates a new without any set, displaying a placeholder until is changed. + /// + public StarRatingDisplay() + { + } + /// /// Creates a new using an already computed . /// /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty = default) + public StarRatingDisplay(StarDifficulty starDifficulty) { Current.Value = starDifficulty; } @@ -82,13 +105,40 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - TextAnchor = Anchor.BottomLeft, + Children = new[] + { + wholePart = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Font = OsuFont.Numeric.With(size: 14, weight: FontWeight.Black), + UseFullGlyphHeight = false, + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Text = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, + Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), + UseFullGlyphHeight = false, + }, + fractionPart = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), + UseFullGlyphHeight = false, + } + } } } } @@ -98,35 +148,31 @@ namespace osu.Game.Screens.Ranking.Expanded protected override void LoadComplete() { base.LoadComplete(); - Current.BindValueChanged(difficulty => updateDisplay(difficulty.NewValue), true); + + Current.BindValueChanged(_ => updateDisplay(), true); + FinishTransforms(true); } - private void updateDisplay(StarDifficulty difficulty) + private void updateDisplay() { - var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + const double duration = 400; + const Easing easing = Easing.OutQuint; - background.Colour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + ColourInfo backgroundColour; - textFlow.Clear(); - - textFlow.AddText($"{wholePart}", s => + if (Current.Value == null) + backgroundColour = Color4.SlateGray.Opacity(0.3f); + else { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); + var rating = Current.Value.Value.DifficultyRating; - textFlow.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); + backgroundColour = rating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(rating); + } + + background.FadeColour(backgroundColour, duration, easing); + this.TransformTo(nameof(DisplayedStarRating), Current.Value?.Stars ?? 0.0f, duration, easing); } } } From f701c331f285834f4814b4e070384a54637214f4 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 21:15:15 +0300 Subject: [PATCH 15/47] Add initial fade in to the metadata display Avoids first frame discrepancies from appearing in the test scene, those can be delt with later on, if needed. --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 552d19ac26..f41180acf2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -30,8 +30,10 @@ namespace osu.Game.Tests.Visual.SongSelect Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(1.5f), + Alpha = 0f, }); + AddStep("fade in", () => display.FadeIn(400, Easing.OutQuint)); AddToggleStep("trigger loading", v => display.Loading = v); } From 8fba655d2e9007449f19b67abf2876ce61656b67 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 21:20:17 +0300 Subject: [PATCH 16/47] Allow changing ruleset during test --- .../TestSceneBeatmapMetadataDisplay.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index f41180acf2..0fbf42da6f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osuTK; @@ -23,7 +24,18 @@ namespace osu.Game.Tests.Visual.SongSelect [Resolved] private BeatmapManager manager { get; set; } - private void createDisplay(Func getBeatmap) + [Resolved] + private RulesetStore rulesets { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + foreach (var ruleset in rulesets.AvailableRulesets) + AddStep($"switch to {ruleset.Name}", () => Ruleset.Value = ruleset); + } + + private void createTest(Func getBeatmap) { AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(getRandomMods()), Empty()) { @@ -43,7 +55,7 @@ namespace osu.Game.Tests.Visual.SongSelect [Values("Trial", "Some1's very hardest difficulty")] string version) { - createDisplay(() => CreateWorkingBeatmap(new Beatmap + createTest(() => CreateWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -60,7 +72,7 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestRandomFromDatabase() { - createDisplay(() => + createTest(() => { var allBeatmapSets = manager.GetAllUsableBeatmapSets(IncludedDetails.Minimal); if (allBeatmapSets.Count == 0) From 0c973feb53f1e76a593994340d522e1afb439e46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:34:21 +0900 Subject: [PATCH 17/47] Tidy up test scene --- .../TestSceneBeatmapMetadataDisplay.cs | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 0fbf42da6f..e80c453da9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -35,27 +35,13 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep($"switch to {ruleset.Name}", () => Ruleset.Value = ruleset); } - private void createTest(Func getBeatmap) - { - AddStep("setup display", () => Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(getRandomMods()), Empty()) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.5f), - Alpha = 0f, - }); - - AddStep("fade in", () => display.FadeIn(400, Easing.OutQuint)); - AddToggleStep("trigger loading", v => display.Loading = v); - } - [Test] public void TestLocal([Values("Beatmap", "Some long title and stuff")] string title, [Values("Trial", "Some1's very hardest difficulty")] string version) { - createTest(() => CreateWorkingBeatmap(new Beatmap + showMetadataForBeatmap(() => CreateWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -72,7 +58,7 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestRandomFromDatabase() { - createTest(() => + showMetadataForBeatmap(() => { var allBeatmapSets = manager.GetAllUsableBeatmapSets(IncludedDetails.Minimal); if (allBeatmapSets.Count == 0) @@ -85,10 +71,23 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - private IReadOnlyList getRandomMods() => Ruleset.Value.CreateInstance() - .GetAllMods() - .OrderBy(_ => RNG.Next()) - .Take(5) - .ToList(); + private void showMetadataForBeatmap(Func getBeatmap) + { + AddStep("setup display", () => + { + var randomMods = Ruleset.Value.CreateInstance().GetAllMods().OrderBy(_ => RNG.Next()).Take(5).ToList(); + + Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), Empty()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.5f), + Alpha = 0f, + }; + }); + + AddStep("fade in", () => display.FadeIn(400, Easing.OutQuint)); + AddToggleStep("trigger loading", v => display.Loading = v); + } } } From 2b90bc4f1f85e35d1610e3e1e993e97dd5df643b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:35:23 +0900 Subject: [PATCH 18/47] Remove unnecessary ruleset switching steps --- .../SongSelect/TestSceneBeatmapMetadataDisplay.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index e80c453da9..0fd9197ab4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osuTK; @@ -24,17 +23,6 @@ namespace osu.Game.Tests.Visual.SongSelect [Resolved] private BeatmapManager manager { get; set; } - [Resolved] - private RulesetStore rulesets { get; set; } - - protected override void LoadComplete() - { - base.LoadComplete(); - - foreach (var ruleset in rulesets.AvailableRulesets) - AddStep($"switch to {ruleset.Name}", () => Ruleset.Value = ruleset); - } - [Test] public void TestLocal([Values("Beatmap", "Some long title and stuff")] string title, From b7acf9de52606a8a3bc87983d5deb096a773e6ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:36:56 +0900 Subject: [PATCH 19/47] Make test work without manually clicking things --- .../Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 0fd9197ab4..49aec02aa0 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -72,10 +72,13 @@ namespace osu.Game.Tests.Visual.SongSelect Scale = new Vector2(1.5f), Alpha = 0f, }; + + display.FadeIn(400, Easing.OutQuint); }); - AddStep("fade in", () => display.FadeIn(400, Easing.OutQuint)); - AddToggleStep("trigger loading", v => display.Loading = v); + AddWaitStep("wait a bit", 5); + + AddStep("finish loading", () => display.Loading = false); } } } From 9ba412d27e9fe2161530a133efe2d74d329cdb8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:41:22 +0900 Subject: [PATCH 20/47] Add the osu! logo to the test scene Makes no sense to add a test intended to test visual behaviour with one of the main elements missing. Not sure how you would be able to test the flow with the logo's presence. --- .../SongSelect/TestSceneBeatmapMetadataDisplay.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 49aec02aa0..230822e070 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Menu; using osu.Game.Screens.Play; using osuTK; @@ -65,12 +66,16 @@ namespace osu.Game.Tests.Visual.SongSelect { var randomMods = Ruleset.Value.CreateInstance().GetAllMods().OrderBy(_ => RNG.Next()).Take(5).ToList(); - Child = display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), Empty()) + OsuLogo logo = new OsuLogo { Scale = new Vector2(0.15f) }; + + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.5f), - Alpha = 0f, + display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), logo) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0f, + } }; display.FadeIn(400, Easing.OutQuint); From 301dab1ce8d8eb481a4180f63a7aa213919279c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 12:55:07 +0300 Subject: [PATCH 21/47] Refactor `StarRatingDisplay` to be mutable with a current bindable --- .../Ranking/TestSceneStarRatingDisplay.cs | 15 +++- .../Ranking/Expanded/StarRatingDisplay.cs | 87 ++++++++++++------- 2 files changed, 68 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index d0067c3396..a043f506c1 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -1,8 +1,10 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Screens.Ranking.Expanded; @@ -10,8 +12,11 @@ namespace osu.Game.Tests.Visual.Ranking { public class TestSceneStarRatingDisplay : OsuTestScene { - public TestSceneStarRatingDisplay() + [SetUp] + public void SetUp() => Schedule(() => { + StarRatingDisplay changingStarRating; + Child = new FillFlowContainer { Anchor = Anchor.Centre, @@ -25,8 +30,14 @@ namespace osu.Game.Tests.Visual.Ranking new StarRatingDisplay(new StarDifficulty(5.67, 0)), new StarRatingDisplay(new StarDifficulty(6.78, 0)), new StarRatingDisplay(new StarDifficulty(10.11, 0)), + changingStarRating = new StarRatingDisplay(), } }; - } + + Scheduler.AddDelayed(() => + { + changingStarRating.Current.Value = new StarDifficulty(RNG.NextDouble(0, 10), RNG.Next()); + }, 500, true); + }); } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index f7e50fdc8a..a1f48fa811 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -3,12 +3,14 @@ using System.Globalization; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -20,17 +22,29 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A pill that displays the star rating of a . /// - public class StarRatingDisplay : CompositeDrawable + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { - private readonly StarDifficulty difficulty; + private Box background; + private OsuTextFlowContainer textFlow; + + [Resolved] + private OsuColour colours { get; set; } + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } /// /// Creates a new using an already computed . /// /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty) + public StarRatingDisplay(StarDifficulty starDifficulty = default) { - difficulty = starDifficulty; + Current.Value = starDifficulty; } [BackgroundDependencyLoader] @@ -38,15 +52,6 @@ namespace osu.Game.Screens.Ranking.Expanded { AutoSizeAxes = Axes.Both; - var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - - ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); - InternalChildren = new Drawable[] { new CircularContainer @@ -55,10 +60,9 @@ namespace osu.Game.Screens.Ranking.Expanded Masking = true, Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = backgroundColour }, } }, @@ -78,32 +82,51 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, TextAnchor = Anchor.BottomLeft, - }.With(t => - { - t.AddText($"{wholePart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - t.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }) + } } } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + Current.BindValueChanged(difficulty => updateDisplay(difficulty.NewValue), true); + } + + private void updateDisplay(StarDifficulty difficulty) + { + var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + string wholePart = starRatingParts[0]; + string fractionPart = starRatingParts[1]; + string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + + background.Colour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + + textFlow.Clear(); + + textFlow.AddText($"{wholePart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + + textFlow.AddText($"{separator}{fractionPart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + } } } From ca772b60b183e33d0c42896f5340088c5f3206b8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 18:21:29 +0300 Subject: [PATCH 22/47] Use regular test steps rather than one-time set up and scheduling --- .../Visual/Ranking/TestSceneStarRatingDisplay.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index a043f506c1..2ff664a0d9 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -12,12 +12,12 @@ namespace osu.Game.Tests.Visual.Ranking { public class TestSceneStarRatingDisplay : OsuTestScene { - [SetUp] - public void SetUp() => Schedule(() => + [Test] + public void TestDisplay() { - StarRatingDisplay changingStarRating; + StarRatingDisplay changingStarRating = null; - Child = new FillFlowContainer + AddStep("load displays", () => Child = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -32,12 +32,12 @@ namespace osu.Game.Tests.Visual.Ranking new StarRatingDisplay(new StarDifficulty(10.11, 0)), changingStarRating = new StarRatingDisplay(), } - }; + }); - Scheduler.AddDelayed(() => + AddRepeatStep("change bottom rating", () => { changingStarRating.Current.Value = new StarDifficulty(RNG.NextDouble(0, 10), RNG.Next()); - }, 500, true); - }); + }, 10); + } } } From 1c49590ba2e37ca79e03f7de0599e20f8be3a2f3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 21:13:18 +0300 Subject: [PATCH 23/47] Apply further refactoring to star rating display UX-wise --- .../Ranking/Expanded/StarRatingDisplay.cs | 106 +++++++++++++----- 1 file changed, 76 insertions(+), 30 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index a1f48fa811..77c43ad863 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -22,27 +22,50 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A pill that displays the star rating of a . /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private Box background; - private OsuTextFlowContainer textFlow; + private OsuSpriteText wholePart; + private OsuSpriteText fractionPart; + + private double displayedStarRating; + + protected double DisplayedStarRating + { + get => displayedStarRating; + set + { + displayedStarRating = value; + + var starRatingParts = value.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + wholePart.Text = starRatingParts[0]; + fractionPart.Text = starRatingParts[1]; + } + } [Resolved] private OsuColour colours { get; set; } - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; } + /// + /// Creates a new without any set, displaying a placeholder until is changed. + /// + public StarRatingDisplay() + { + } + /// /// Creates a new using an already computed . /// /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty = default) + public StarRatingDisplay(StarDifficulty starDifficulty) { Current.Value = starDifficulty; } @@ -82,13 +105,40 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - TextAnchor = Anchor.BottomLeft, + Children = new[] + { + wholePart = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Font = OsuFont.Numeric.With(size: 14, weight: FontWeight.Black), + UseFullGlyphHeight = false, + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Text = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, + Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), + UseFullGlyphHeight = false, + }, + fractionPart = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), + UseFullGlyphHeight = false, + } + } } } } @@ -98,35 +148,31 @@ namespace osu.Game.Screens.Ranking.Expanded protected override void LoadComplete() { base.LoadComplete(); - Current.BindValueChanged(difficulty => updateDisplay(difficulty.NewValue), true); + + Current.BindValueChanged(_ => updateDisplay(), true); + FinishTransforms(true); } - private void updateDisplay(StarDifficulty difficulty) + private void updateDisplay() { - var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + const double duration = 400; + const Easing easing = Easing.OutQuint; - background.Colour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + ColourInfo backgroundColour; - textFlow.Clear(); - - textFlow.AddText($"{wholePart}", s => + if (Current.Value == null) + backgroundColour = Color4.SlateGray.Opacity(0.3f); + else { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); + var rating = Current.Value.Value.DifficultyRating; - textFlow.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); + backgroundColour = rating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(rating); + } + + background.FadeColour(backgroundColour, duration, easing); + this.TransformTo(nameof(DisplayedStarRating), Current.Value?.Stars ?? 0.0f, duration, easing); } } } From afc9a1bf235ef9c3026292254d788ce98072158d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 10 May 2021 10:16:52 +0300 Subject: [PATCH 24/47] Remove rolling support and apply few adjustments --- .../Ranking/Expanded/StarRatingDisplay.cs | 81 +++++++------------ 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 77c43ad863..422833555f 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.Containers; using osuTK; using osuTK.Graphics; @@ -25,23 +25,7 @@ namespace osu.Game.Screens.Ranking.Expanded public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private Box background; - private OsuSpriteText wholePart; - private OsuSpriteText fractionPart; - - private double displayedStarRating; - - protected double DisplayedStarRating - { - get => displayedStarRating; - set - { - displayedStarRating = value; - - var starRatingParts = value.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - wholePart.Text = starRatingParts[0]; - fractionPart.Text = starRatingParts[1]; - } - } + private OsuTextFlowContainer textFlow; [Resolved] private OsuColour colours { get; set; } @@ -105,40 +89,13 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - new FillFlowContainer + textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Children = new[] - { - wholePart = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Colour = Color4.Black, - Font = OsuFont.Numeric.With(size: 14, weight: FontWeight.Black), - UseFullGlyphHeight = false, - }, - new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Colour = Color4.Black, - Text = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, - Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), - UseFullGlyphHeight = false, - }, - fractionPart = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Colour = Color4.Black, - Font = OsuFont.Numeric.With(size: 7, weight: FontWeight.Black), - UseFullGlyphHeight = false, - } - } + TextAnchor = Anchor.BottomLeft, } } } @@ -158,21 +115,39 @@ namespace osu.Game.Screens.Ranking.Expanded const double duration = 400; const Easing easing = Easing.OutQuint; - ColourInfo backgroundColour; + double stars = Current.Value?.Stars ?? 0.00f; + + var starRatingParts = stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + string wholePart = starRatingParts[0]; + string fractionPart = starRatingParts[1]; + string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; if (Current.Value == null) - backgroundColour = Color4.SlateGray.Opacity(0.3f); + background.FadeColour(Color4.SlateGray.Opacity(0.3f)); else { var rating = Current.Value.Value.DifficultyRating; - backgroundColour = rating == DifficultyRating.ExpertPlus + background.FadeColour(rating == DifficultyRating.ExpertPlus ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(rating); + : (ColourInfo)colours.ForDifficultyRating(rating), duration, easing); } - background.FadeColour(backgroundColour, duration, easing); - this.TransformTo(nameof(DisplayedStarRating), Current.Value?.Stars ?? 0.0f, duration, easing); + textFlow.Clear(); + + textFlow.AddText($"{wholePart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + + textFlow.AddText($"{separator}{fractionPart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); } } } From c13b93e6f15254845e62046551b5e17802915826 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Wed, 12 May 2021 02:29:18 +0200 Subject: [PATCH 25/47] Replace `IWorkingBeatmap` arg with `BeatmapVerifierContext` in checks This simplifies passing of contextual information by enabling addition without needing to refactor lots of classes. See next commit for example. --- .../Checks/CheckOffscreenObjectsTest.cs | 10 +++++-- .../Edit/Checks/CheckOffscreenObjects.cs | 3 +- .../Edit/OsuBeatmapVerifier.cs | 4 +-- .../Editing/Checks/CheckAudioQualityTest.cs | 28 ++++++++++------- .../Checks/CheckBackgroundQualityTest.cs | 30 +++++++++++-------- .../Editing/Checks/CheckFilePresenceTest.cs | 10 +++++-- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 4 +-- .../Rulesets/Edit/BeatmapVerifierContext.cs | 25 ++++++++++++++++ .../Rulesets/Edit/Checks/CheckAudioQuality.cs | 4 +-- .../Edit/Checks/CheckBackgroundQuality.cs | 6 ++-- .../Edit/Checks/CheckConcurrentObjects.cs | 2 +- .../Rulesets/Edit/Checks/CheckFilePresence.cs | 2 +- .../Edit/Checks/CheckUnsnappedObjects.cs | 2 +- .../Rulesets/Edit/Checks/Components/ICheck.cs | 4 +-- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 2 +- osu.Game/Screens/Edit/Verify/IssueList.cs | 7 +++-- 16 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index 6139b0e676..5545273af2 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Checks; @@ -224,12 +225,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOk(IBeatmap beatmap) { - Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + Assert.That(check.Run(beatmap, context), Is.Empty); } private void assertOffscreenCircle(IBeatmap beatmap) { - var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenCircle); @@ -237,7 +240,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOffscreenSlider(IBeatmap beatmap) { - var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenSlider); diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index 4b0a7531a1..c25539201e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -31,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { foreach (var hitobject in playableBeatmap.HitObjects) { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index dab6483179..18faeb4f9f 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -17,9 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckOffscreenObjects() }; - public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap)); + return checks.SelectMany(check => check.Run(playableBeatmap, context)); } } } diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs index 7658ca728d..fbd02ea54e 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -6,6 +6,7 @@ using Moq; using NUnit.Framework; using osu.Framework.Audio.Track; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; @@ -40,23 +41,23 @@ namespace osu.Game.Tests.Editing.Checks mock.SetupGet(w => w.Beatmap).Returns(beatmap); mock.SetupGet(w => w.Track).Returns((Track)null); - Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, new BeatmapVerifierContext(mock.Object)), Is.Empty); } [Test] public void TestAcceptable() { - var mock = getMockWorkingBeatmap(192); + var context = getContext(192); - Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, context), Is.Empty); } [Test] public void TestNullBitrate() { - var mock = getMockWorkingBeatmap(null); + var context = getContext(null); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); @@ -65,9 +66,9 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestZeroBitrate() { - var mock = getMockWorkingBeatmap(0); + var context = getContext(0); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); @@ -76,9 +77,9 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestTooHighBitrate() { - var mock = getMockWorkingBeatmap(320); + var context = getContext(320); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooHighBitrate); @@ -87,14 +88,19 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestTooLowBitrate() { - var mock = getMockWorkingBeatmap(64); + var context = getContext(64); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooLowBitrate); } + private BeatmapVerifierContext getContext(int? audioBitrate) + { + return new BeatmapVerifierContext(getMockWorkingBeatmap(audioBitrate).Object); + } + /// /// Returns the mock of the working beatmap with the given audio properties. /// diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index f0f972d2fa..e96ec5485d 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -9,6 +9,7 @@ using Moq; using NUnit.Framework; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using FileInfo = osu.Game.IO.FileInfo; @@ -53,25 +54,25 @@ namespace osu.Game.Tests.Editing.Checks { // While this is a problem, it is out of scope for this check and is caught by a different one. beatmap.Metadata.BackgroundFile = null; - var mock = getMockWorkingBeatmap(null, System.Array.Empty()); + var context = getContext(null, System.Array.Empty()); - Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, context), Is.Empty); } [Test] public void TestAcceptable() { - var mock = getMockWorkingBeatmap(new Texture(1920, 1080)); + var context = getContext(new Texture(1920, 1080)); - Assert.That(check.Run(beatmap, mock.Object), Is.Empty); + Assert.That(check.Run(beatmap, context), Is.Empty); } [Test] public void TestTooHighResolution() { - var mock = getMockWorkingBeatmap(new Texture(3840, 2160)); + var context = getContext(new Texture(3840, 2160)); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooHighResolution); @@ -80,9 +81,9 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestLowResolution() { - var mock = getMockWorkingBeatmap(new Texture(640, 480)); + var context = getContext(new Texture(640, 480)); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateLowResolution); @@ -91,9 +92,9 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestTooLowResolution() { - var mock = getMockWorkingBeatmap(new Texture(100, 100)); + var context = getContext(new Texture(100, 100)); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooLowResolution); @@ -102,14 +103,19 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestTooUncompressed() { - var mock = getMockWorkingBeatmap(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); + var context = getContext(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); - var issues = check.Run(beatmap, mock.Object).ToList(); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooUncompressed); } + private BeatmapVerifierContext getContext(Texture background, [CanBeNull] byte[] fileBytes = null) + { + return new BeatmapVerifierContext(getMockWorkingBeatmap(background, fileBytes).Object); + } + /// /// Returns the mock of the working beatmap with the given background and filesize. /// diff --git a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index f6e875a8fc..424dffcbc2 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.IO; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using osu.Game.Tests.Beatmaps; @@ -45,7 +46,8 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestBackgroundSetAndInFiles() { - Assert.That(check.Run(beatmap, new TestWorkingBeatmap(beatmap)), Is.Empty); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + Assert.That(check.Run(beatmap, context), Is.Empty); } [Test] @@ -53,7 +55,8 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.BeatmapInfo.BeatmapSet.Files.Clear(); - var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateDoesNotExist); @@ -64,7 +67,8 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.Metadata.BackgroundFile = null; - var issues = check.Run(beatmap, new TestWorkingBeatmap(beatmap)).ToList(); + var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); + var issues = check.Run(beatmap, context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateNoneSet); diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 2f7b7b0ab8..50902d3ff1 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -29,9 +29,9 @@ namespace osu.Game.Rulesets.Edit new CheckConcurrentObjects() }; - public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(playableBeatmap, workingBeatmap)); + return checks.SelectMany(check => check.Run(playableBeatmap, context)); } } } diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs new file mode 100644 index 0000000000..86ca81491a --- /dev/null +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Beatmaps; + +namespace osu.Game.Rulesets.Edit +{ + /// + /// Represents the context provided by the beatmap verifier to the checks it runs. + /// Contains information about what is being checked and how it should be checked. + /// + public class BeatmapVerifierContext + { + /// + /// The working beatmap instance of the current beatmap. + /// + public readonly IWorkingBeatmap WorkingBeatmap; + + public BeatmapVerifierContext(IWorkingBeatmap workingBeatmap) + { + WorkingBeatmap = workingBeatmap; + } + } +} diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index c1074d7c74..82e572f0b3 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -26,13 +26,13 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateNoBitrate(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { var audioFile = playableBeatmap.Metadata?.AudioFile; if (audioFile == null) yield break; - var track = workingBeatmap.Track; + var track = context.WorkingBeatmap.Track; if (track?.Bitrate == null || track.Bitrate.Value == 0) yield return new IssueTemplateNoBitrate(this).Create(); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 59fee74023..2af1eca340 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -30,13 +30,13 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateTooUncompressed(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { var backgroundFile = playableBeatmap.Metadata?.BackgroundFile; if (backgroundFile == null) yield break; - var texture = workingBeatmap.Background; + var texture = context.WorkingBeatmap.Background; if (texture == null) yield break; @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Edit.Checks yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); string storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); - double filesizeMb = workingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); + double filesizeMb = context.WorkingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); if (filesizeMb > max_filesize_mb) yield return new IssueTemplateTooUncompressed(this).Create(filesizeMb); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs index ddebe2923a..d6e779d147 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateConcurrentDifferent(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { for (int i = 0; i < playableBeatmap.HitObjects.Count - 1; ++i) { diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index 006fc57c04..cf990a2106 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { var filename = GetFilename(playableBeatmap); diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs index cdf3f05465..f073915a39 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateSmallUnsnap(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap) + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) { var controlPointInfo = playableBeatmap.ControlPointInfo; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index 31a7583941..f669e2161c 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// Runs this check and returns any issues detected for the provided beatmap. /// /// The playable beatmap of the beatmap to run the check on. - /// The working beatmap of the beatmap to run the check on. - public IEnumerable Run(IBeatmap playableBeatmap, IWorkingBeatmap workingBeatmap); + /// The beatmap verifier context associated with the beatmap. + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context); } } diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index b598176a35..4e712351e0 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Edit /// public interface IBeatmapVerifier { - public IEnumerable Run(IBeatmap playableBeatmap, WorkingBeatmap workingBeatmap); + public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context); } } diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index 3e836c4010..96d056fba4 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -40,6 +40,7 @@ namespace osu.Game.Screens.Edit.Verify private IBeatmapVerifier rulesetVerifier; private BeatmapVerifier generalVerifier; + private BeatmapVerifierContext context; [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) @@ -57,6 +58,8 @@ namespace osu.Game.Screens.Edit.Verify InterpretedDifficulty = new Bindable(beatmap.BeatmapInfo.DifficultyRating); + context = new BeatmapVerifierContext(workingBeatmap.Value); + RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] @@ -101,10 +104,10 @@ namespace osu.Game.Screens.Edit.Verify public void Refresh() { - var issues = generalVerifier.Run(beatmap, workingBeatmap.Value); + var issues = generalVerifier.Run(beatmap, context); if (rulesetVerifier != null) - issues = issues.Concat(rulesetVerifier.Run(beatmap, workingBeatmap.Value)); + issues = issues.Concat(rulesetVerifier.Run(beatmap, context)); issues = filter(issues); From 64d96b06a66c9f35026b925573b9f3fc7ebfb72d Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Wed, 12 May 2021 02:30:21 +0200 Subject: [PATCH 26/47] Add interpreted difficulty info to `BeatmapVerifierContext` Enables checks to make use of the difficulty level as shown in the settings UI. --- osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs | 8 +++++++- osu.Game/Screens/Edit/Verify/IssueList.cs | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 86ca81491a..59d43ba3d6 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -17,9 +17,15 @@ namespace osu.Game.Rulesets.Edit /// public readonly IWorkingBeatmap WorkingBeatmap; - public BeatmapVerifierContext(IWorkingBeatmap workingBeatmap) + /// + /// The difficulty level which the current beatmap is considered to be. + /// + public readonly Bindable InterpretedDifficulty; + + public BeatmapVerifierContext(IWorkingBeatmap workingBeatmap, DifficultyRating difficultyRating = DifficultyRating.ExpertPlus) { WorkingBeatmap = workingBeatmap; + InterpretedDifficulty = new Bindable(difficultyRating); } } } diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index 96d056fba4..2ae86ed198 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -59,6 +59,7 @@ namespace osu.Game.Screens.Edit.Verify InterpretedDifficulty = new Bindable(beatmap.BeatmapInfo.DifficultyRating); context = new BeatmapVerifierContext(workingBeatmap.Value); + context.InterpretedDifficulty.BindTo(InterpretedDifficulty); RelativeSizeAxes = Axes.Both; From b7bc42e0d37db4f5d5bfc201d70e036e25bf9ce7 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Wed, 12 May 2021 02:34:16 +0200 Subject: [PATCH 27/47] Rename "playableBeatmap" check arg to "beatmap" The working beatmap is now in the context, so it's easier to distinguish beatmap type, hence no need for this prefix. --- .../Edit/Checks/CheckOffscreenObjects.cs | 4 ++-- osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs | 4 ++-- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 4 ++-- osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs | 4 ++-- .../Rulesets/Edit/Checks/CheckBackgroundPresence.cs | 2 +- .../Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 6 +++--- .../Rulesets/Edit/Checks/CheckConcurrentObjects.cs | 10 +++++----- osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs | 8 ++++---- osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs | 6 +++--- osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs | 4 ++-- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 2 +- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index c25539201e..86bb7f203f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -32,9 +32,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - foreach (var hitobject in playableBeatmap.HitObjects) + foreach (var hitobject in beatmap.HitObjects) { switch (hitobject) { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 18faeb4f9f..c62f472d75 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -17,9 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckOffscreenObjects() }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(playableBeatmap, context)); + return checks.SelectMany(check => check.Run(beatmap, context)); } } } diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 50902d3ff1..1860d54b57 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -29,9 +29,9 @@ namespace osu.Game.Rulesets.Edit new CheckConcurrentObjects() }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(playableBeatmap, context)); + return checks.SelectMany(check => check.Run(beatmap, context)); } } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs index 2d572a521e..94c48c300a 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Audio; protected override string TypeOfFile => "audio"; - protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.AudioFile; + protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata?.AudioFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index 82e572f0b3..1015f267aa 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -26,9 +26,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateNoBitrate(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - var audioFile = playableBeatmap.Metadata?.AudioFile; + var audioFile = beatmap.Metadata?.AudioFile; if (audioFile == null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs index 233c708a25..067800b409 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Resources; protected override string TypeOfFile => "background"; - protected override string GetFilename(IBeatmap playableBeatmap) => playableBeatmap.Metadata?.BackgroundFile; + protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata?.BackgroundFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 2af1eca340..87f5c80c89 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -30,9 +30,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateTooUncompressed(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - var backgroundFile = playableBeatmap.Metadata?.BackgroundFile; + var backgroundFile = beatmap.Metadata?.BackgroundFile; if (backgroundFile == null) yield break; @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Edit.Checks else if (texture.Width < low_width || texture.Height < low_height) yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); - string storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); + string storagePath = beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); double filesizeMb = context.WorkingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); if (filesizeMb > max_filesize_mb) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs index d6e779d147..fd6ed664e6 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs @@ -22,15 +22,15 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateConcurrentDifferent(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - for (int i = 0; i < playableBeatmap.HitObjects.Count - 1; ++i) + for (int i = 0; i < beatmap.HitObjects.Count - 1; ++i) { - var hitobject = playableBeatmap.HitObjects[i]; + var hitobject = beatmap.HitObjects[i]; - for (int j = i + 1; j < playableBeatmap.HitObjects.Count; ++j) + for (int j = i + 1; j < beatmap.HitObjects.Count; ++j) { - var nextHitobject = playableBeatmap.HitObjects[j]; + var nextHitobject = beatmap.HitObjects[j]; // Accounts for rulesets with hitobjects separated by columns, such as Mania. // In these cases we only care about concurrent objects within the same column. diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index cf990a2106..f04909d175 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Edit.Checks { protected abstract CheckCategory Category { get; } protected abstract string TypeOfFile { get; } - protected abstract string GetFilename(IBeatmap playableBeatmap); + protected abstract string GetFilename(IBeatmap beatmap); public CheckMetadata Metadata => new CheckMetadata(Category, $"Missing {TypeOfFile}"); @@ -21,9 +21,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - var filename = GetFilename(playableBeatmap); + var filename = GetFilename(beatmap); if (filename == null) { @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit.Checks } // If the file is set, also make sure it still exists. - var storagePath = playableBeatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); + var storagePath = beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); if (storagePath != null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs index f073915a39..aa19f3df07 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs @@ -22,11 +22,11 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateSmallUnsnap(this) }; - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context) + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) { - var controlPointInfo = playableBeatmap.ControlPointInfo; + var controlPointInfo = beatmap.ControlPointInfo; - foreach (var hitobject in playableBeatmap.HitObjects) + foreach (var hitobject in beatmap.HitObjects) { double startUnsnap = hitobject.StartTime - controlPointInfo.GetClosestSnappedTime(hitobject.StartTime); string startPostfix = hitobject is IHasDuration ? "start" : ""; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index f669e2161c..511d6aaa0f 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -24,8 +24,8 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// /// Runs this check and returns any issues detected for the provided beatmap. /// - /// The playable beatmap of the beatmap to run the check on. + /// The playable beatmap of the beatmap to run the check on. /// The beatmap verifier context associated with the beatmap. - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context); + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context); } } diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 4e712351e0..1dafc6938e 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Edit /// public interface IBeatmapVerifier { - public IEnumerable Run(IBeatmap playableBeatmap, BeatmapVerifierContext context); + public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context); } } From 4eeeaf6a1aa9588932c2c096c40232d6bb5527d4 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Thu, 13 May 2021 07:57:32 +0200 Subject: [PATCH 28/47] Keep track of local bound copy --- osu.Game/Screens/Edit/Verify/IssueList.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index 2a90834537..f150f4175b 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.Edit.Verify [Resolved] private VerifyScreen verify { get; set; } + private Bindable interpretedDifficulty; + private IBeatmapVerifier rulesetVerifier; private BeatmapVerifier generalVerifier; private BeatmapVerifierContext context; @@ -45,8 +47,10 @@ namespace osu.Game.Screens.Edit.Verify generalVerifier = new BeatmapVerifier(); rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); + interpretedDifficulty = verify.InterpretedDifficulty.GetBoundCopy(); + context = new BeatmapVerifierContext(workingBeatmap.Value); - context.InterpretedDifficulty.BindTo(verify.InterpretedDifficulty.GetBoundCopy()); + context.InterpretedDifficulty.BindTo(interpretedDifficulty); RelativeSizeAxes = Axes.Both; From b37cb3bdbeadefb2bba7a71575e8be9c535c54d3 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Thu, 13 May 2021 09:00:30 +0200 Subject: [PATCH 29/47] Change interpreted difficulty from bindable to regular value There's no reason for why checks would need this to be bindable. A 1-directional binding is more appropriate. --- osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs | 5 ++--- osu.Game/Screens/Edit/Verify/IssueList.cs | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 59d43ba3d6..76b74cb993 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Bindables; using osu.Game.Beatmaps; namespace osu.Game.Rulesets.Edit @@ -20,12 +19,12 @@ namespace osu.Game.Rulesets.Edit /// /// The difficulty level which the current beatmap is considered to be. /// - public readonly Bindable InterpretedDifficulty; + public DifficultyRating InterpretedDifficulty; public BeatmapVerifierContext(IWorkingBeatmap workingBeatmap, DifficultyRating difficultyRating = DifficultyRating.ExpertPlus) { WorkingBeatmap = workingBeatmap; - InterpretedDifficulty = new Bindable(difficultyRating); + InterpretedDifficulty = difficultyRating; } } } diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index f150f4175b..abf22ead10 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -35,8 +35,6 @@ namespace osu.Game.Screens.Edit.Verify [Resolved] private VerifyScreen verify { get; set; } - private Bindable interpretedDifficulty; - private IBeatmapVerifier rulesetVerifier; private BeatmapVerifier generalVerifier; private BeatmapVerifierContext context; @@ -47,10 +45,11 @@ namespace osu.Game.Screens.Edit.Verify generalVerifier = new BeatmapVerifier(); rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); - interpretedDifficulty = verify.InterpretedDifficulty.GetBoundCopy(); - - context = new BeatmapVerifierContext(workingBeatmap.Value); - context.InterpretedDifficulty.BindTo(interpretedDifficulty); + context = new BeatmapVerifierContext(workingBeatmap.Value, verify.InterpretedDifficulty.Value); + verify.InterpretedDifficulty.BindValueChanged(change => + { + context.InterpretedDifficulty = change.NewValue; + }); RelativeSizeAxes = Axes.Both; From 19800f5f7f22d81bc0784796b78dc811e4a8458b Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Thu, 13 May 2021 11:24:22 +0200 Subject: [PATCH 30/47] Move `IBeatmap` arg into context --- .../Editor/Checks/CheckOffscreenObjectsTest.cs | 12 ++++++------ .../Edit/Checks/CheckOffscreenObjects.cs | 5 ++--- osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs | 5 ++--- .../Editing/Checks/CheckAudioQualityTest.cs | 14 +++++++------- .../Editing/Checks/CheckBackgroundQualityTest.cs | 14 +++++++------- .../Editing/Checks/CheckConcurrentObjectsTest.cs | 15 ++++++++------- .../Editing/Checks/CheckFilePresenceTest.cs | 12 ++++++------ .../Editing/Checks/CheckUnsnappedObjectsTest.cs | 15 ++++++++------- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 5 ++--- osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs | 8 +++++++- .../Rulesets/Edit/Checks/CheckAudioQuality.cs | 5 ++--- .../Edit/Checks/CheckBackgroundQuality.cs | 7 +++---- .../Edit/Checks/CheckConcurrentObjects.cs | 11 +++++------ .../Rulesets/Edit/Checks/CheckFilePresence.cs | 6 +++--- .../Rulesets/Edit/Checks/CheckUnsnappedObjects.cs | 7 +++---- .../Rulesets/Edit/Checks/Components/ICheck.cs | 4 +--- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 3 +-- osu.Game/Screens/Edit/Verify/IssueList.cs | 6 +++--- 18 files changed, 76 insertions(+), 78 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index 5545273af2..a6873c6de9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -225,14 +225,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOk(IBeatmap beatmap) { - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - Assert.That(check.Run(beatmap, context), Is.Empty); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + Assert.That(check.Run(context), Is.Empty); } private void assertOffscreenCircle(IBeatmap beatmap) { - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - var issues = check.Run(beatmap, context).ToList(); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenCircle); @@ -240,8 +240,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks private void assertOffscreenSlider(IBeatmap beatmap) { - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - var issues = check.Run(beatmap, context).ToList(); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckOffscreenObjects.IssueTemplateOffscreenSlider); diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index 86bb7f203f..a342c2a821 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Osu.Objects; @@ -32,9 +31,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks new IssueTemplateOffscreenSlider(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - foreach (var hitobject in beatmap.HitObjects) + foreach (var hitobject in context.Beatmap.HitObjects) { switch (hitobject) { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index c62f472d75..04e881fbf3 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Osu.Edit.Checks; @@ -17,9 +16,9 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckOffscreenObjects() }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(beatmap, context)); + return checks.SelectMany(check => check.Run(context)); } } } diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs index fbd02ea54e..1cbdc43140 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Editing.Checks mock.SetupGet(w => w.Beatmap).Returns(beatmap); mock.SetupGet(w => w.Track).Returns((Track)null); - Assert.That(check.Run(beatmap, new BeatmapVerifierContext(mock.Object)), Is.Empty); + Assert.That(check.Run(new BeatmapVerifierContext(beatmap, mock.Object)), Is.Empty); } [Test] @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(192); - Assert.That(check.Run(beatmap, context), Is.Empty); + Assert.That(check.Run(context), Is.Empty); } [Test] @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(null); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(0); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateNoBitrate); @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(320); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooHighBitrate); @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(64); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run( context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooLowBitrate); @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Editing.Checks private BeatmapVerifierContext getContext(int? audioBitrate) { - return new BeatmapVerifierContext(getMockWorkingBeatmap(audioBitrate).Object); + return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(audioBitrate).Object); } /// diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index e96ec5485d..3424cfe732 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Editing.Checks beatmap.Metadata.BackgroundFile = null; var context = getContext(null, System.Array.Empty()); - Assert.That(check.Run(beatmap, context), Is.Empty); + Assert.That(check.Run(context), Is.Empty); } [Test] @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(new Texture(1920, 1080)); - Assert.That(check.Run(beatmap, context), Is.Empty); + Assert.That(check.Run(context), Is.Empty); } [Test] @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(new Texture(3840, 2160)); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooHighResolution); @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(new Texture(640, 480)); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateLowResolution); @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(new Texture(100, 100)); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooLowResolution); @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(new Texture(1920, 1080), new byte[1024 * 1024 * 3]); - var issues = check.Run(beatmap, context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckBackgroundQuality.IssueTemplateTooUncompressed); @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Editing.Checks private BeatmapVerifierContext getContext(Texture background, [CanBeNull] byte[] fileBytes = null) { - return new BeatmapVerifierContext(getMockWorkingBeatmap(background, fileBytes).Object); + return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(background, fileBytes).Object); } /// diff --git a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs index ffe5d34e67..ba0a130a25 100644 --- a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs @@ -6,6 +6,7 @@ using System.Linq; using Moq; using NUnit.Framework; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -105,7 +106,7 @@ namespace osu.Game.Tests.Editing.Checks new HitCircle { StartTime = 300 } }; - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(3)); Assert.That(issues.Where(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentDifferent).ToList(), Has.Count.EqualTo(2)); @@ -164,12 +165,12 @@ namespace osu.Game.Tests.Editing.Checks private void assertOk(List hitobjects) { - Assert.That(check.Run(getPlayableBeatmap(hitobjects), null), Is.Empty); + Assert.That(check.Run(getContext(hitobjects)), Is.Empty); } private void assertConcurrentSame(List hitobjects, int count = 1) { - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentSame)); @@ -177,18 +178,18 @@ namespace osu.Game.Tests.Editing.Checks private void assertConcurrentDifferent(List hitobjects, int count = 1) { - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentDifferent)); } - private IBeatmap getPlayableBeatmap(List hitobjects) + private BeatmapVerifierContext getContext(List hitobjects) { - return new Beatmap + return new BeatmapVerifierContext(new Beatmap { HitObjects = hitobjects - }; + }, null); } } } diff --git a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index 424dffcbc2..39a1d76d83 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -46,8 +46,8 @@ namespace osu.Game.Tests.Editing.Checks [Test] public void TestBackgroundSetAndInFiles() { - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - Assert.That(check.Run(beatmap, context), Is.Empty); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + Assert.That(check.Run(context), Is.Empty); } [Test] @@ -55,8 +55,8 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.BeatmapInfo.BeatmapSet.Files.Clear(); - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - var issues = check.Run(beatmap, context).ToList(); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateDoesNotExist); @@ -67,8 +67,8 @@ namespace osu.Game.Tests.Editing.Checks { beatmap.Metadata.BackgroundFile = null; - var context = new BeatmapVerifierContext(new TestWorkingBeatmap(beatmap)); - var issues = check.Run(beatmap, context).ToList(); + var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckFilePresence.IssueTemplateNoneSet); diff --git a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs index 5e65b263f2..02159fa57b 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -105,7 +106,7 @@ namespace osu.Game.Tests.Editing.Checks getSliderMock(startTime: 98, endTime: 398.75d).Object }; - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(2)); Assert.That(issues.Any(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap)); @@ -124,12 +125,12 @@ namespace osu.Game.Tests.Editing.Checks private void assertOk(List hitobjects) { - Assert.That(check.Run(getPlayableBeatmap(hitobjects), null), Is.Empty); + Assert.That(check.Run(getContext(hitobjects)), Is.Empty); } private void assert1Ms(List hitobjects, int count = 1) { - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap)); @@ -137,19 +138,19 @@ namespace osu.Game.Tests.Editing.Checks private void assert2Ms(List hitobjects, int count = 1) { - var issues = check.Run(getPlayableBeatmap(hitobjects), null).ToList(); + var issues = check.Run(getContext(hitobjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateLargeUnsnap)); } - private IBeatmap getPlayableBeatmap(List hitobjects) + private BeatmapVerifierContext getContext(List hitobjects) { - return new Beatmap + return new BeatmapVerifierContext(new Beatmap { ControlPointInfo = cpi, HitObjects = hitobjects - }; + }, null); } } } diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 1860d54b57..d208c7fe07 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Edit.Checks.Components; @@ -29,9 +28,9 @@ namespace osu.Game.Rulesets.Edit new CheckConcurrentObjects() }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - return checks.SelectMany(check => check.Run(beatmap, context)); + return checks.SelectMany(check => check.Run(context)); } } } diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 76b74cb993..53bdf3140c 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -11,6 +11,11 @@ namespace osu.Game.Rulesets.Edit /// public class BeatmapVerifierContext { + /// + /// The playable beatmap instance of the current beatmap. + /// + public readonly IBeatmap Beatmap; + /// /// The working beatmap instance of the current beatmap. /// @@ -21,8 +26,9 @@ namespace osu.Game.Rulesets.Edit /// public DifficultyRating InterpretedDifficulty; - public BeatmapVerifierContext(IWorkingBeatmap workingBeatmap, DifficultyRating difficultyRating = DifficultyRating.ExpertPlus) + public BeatmapVerifierContext(IBeatmap beatmap, IWorkingBeatmap workingBeatmap, DifficultyRating difficultyRating = DifficultyRating.ExpertPlus) { + Beatmap = beatmap; WorkingBeatmap = workingBeatmap; InterpretedDifficulty = difficultyRating; } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index 1015f267aa..70d11883b7 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit.Checks @@ -26,9 +25,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateNoBitrate(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - var audioFile = beatmap.Metadata?.AudioFile; + var audioFile = context.Beatmap.Metadata?.AudioFile; if (audioFile == null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 87f5c80c89..085c558eaf 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit.Checks @@ -30,9 +29,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateTooUncompressed(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - var backgroundFile = beatmap.Metadata?.BackgroundFile; + var backgroundFile = context.Beatmap.Metadata?.BackgroundFile; if (backgroundFile == null) yield break; @@ -48,7 +47,7 @@ namespace osu.Game.Rulesets.Edit.Checks else if (texture.Width < low_width || texture.Height < low_height) yield return new IssueTemplateLowResolution(this).Create(texture.Width, texture.Height); - string storagePath = beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); + string storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(backgroundFile); double filesizeMb = context.WorkingBeatmap.GetStream(storagePath).Length / (1024d * 1024d); if (filesizeMb > max_filesize_mb) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs index fd6ed664e6..51277298ab 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -22,15 +21,15 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateConcurrentDifferent(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - for (int i = 0; i < beatmap.HitObjects.Count - 1; ++i) + for (int i = 0; i < context.Beatmap.HitObjects.Count - 1; ++i) { - var hitobject = beatmap.HitObjects[i]; + var hitobject = context.Beatmap.HitObjects[i]; - for (int j = i + 1; j < beatmap.HitObjects.Count; ++j) + for (int j = i + 1; j < context.Beatmap.HitObjects.Count; ++j) { - var nextHitobject = beatmap.HitObjects[j]; + var nextHitobject = context.Beatmap.HitObjects[j]; // Accounts for rulesets with hitobjects separated by columns, such as Mania. // In these cases we only care about concurrent objects within the same column. diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index f04909d175..36a0bf8c5d 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -21,9 +21,9 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateDoesNotExist(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - var filename = GetFilename(beatmap); + var filename = GetFilename(context.Beatmap); if (filename == null) { @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit.Checks } // If the file is set, also make sure it still exists. - var storagePath = beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); + var storagePath = context.Beatmap.BeatmapInfo.BeatmapSet.GetPathForFile(filename); if (storagePath != null) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs index aa19f3df07..ded1bb54ca 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -22,11 +21,11 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateSmallUnsnap(this) }; - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context) + public IEnumerable Run(BeatmapVerifierContext context) { - var controlPointInfo = beatmap.ControlPointInfo; + var controlPointInfo = context.Beatmap.ControlPointInfo; - foreach (var hitobject in beatmap.HitObjects) + foreach (var hitobject in context.Beatmap.HitObjects) { double startUnsnap = hitobject.StartTime - controlPointInfo.GetClosestSnappedTime(hitobject.StartTime); string startPostfix = hitobject is IHasDuration ? "start" : ""; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index 511d6aaa0f..141de55f1d 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; namespace osu.Game.Rulesets.Edit.Checks.Components { @@ -24,8 +23,7 @@ namespace osu.Game.Rulesets.Edit.Checks.Components /// /// Runs this check and returns any issues detected for the provided beatmap. /// - /// The playable beatmap of the beatmap to run the check on. /// The beatmap verifier context associated with the beatmap. - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context); + public IEnumerable Run(BeatmapVerifierContext context); } } diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 1dafc6938e..06f0abedb0 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit @@ -12,6 +11,6 @@ namespace osu.Game.Rulesets.Edit /// public interface IBeatmapVerifier { - public IEnumerable Run(IBeatmap beatmap, BeatmapVerifierContext context); + public IEnumerable Run(BeatmapVerifierContext context); } } diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index abf22ead10..fc9d4c7526 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Verify generalVerifier = new BeatmapVerifier(); rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); - context = new BeatmapVerifierContext(workingBeatmap.Value, verify.InterpretedDifficulty.Value); + context = new BeatmapVerifierContext(beatmap, workingBeatmap.Value, verify.InterpretedDifficulty.Value); verify.InterpretedDifficulty.BindValueChanged(change => { context.InterpretedDifficulty = change.NewValue; @@ -98,10 +98,10 @@ namespace osu.Game.Screens.Edit.Verify private void refresh() { - var issues = generalVerifier.Run(beatmap, context); + var issues = generalVerifier.Run(context); if (rulesetVerifier != null) - issues = issues.Concat(rulesetVerifier.Run(beatmap, context)); + issues = issues.Concat(rulesetVerifier.Run(context)); issues = filter(issues); From 94538b38429f5d7a2447c44e0617f7c868e44437 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Thu, 13 May 2021 12:56:36 +0200 Subject: [PATCH 31/47] Remove accidental whitespace --- osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs index 1cbdc43140..39fbf11d51 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Editing.Checks { var context = getContext(64); - var issues = check.Run( context).ToList(); + var issues = check.Run(context).ToList(); Assert.That(issues, Has.Count.EqualTo(1)); Assert.That(issues.Single().Template is CheckAudioQuality.IssueTemplateTooLowBitrate); From 90e0b3374e2a975e2df4e99cffebb520653d12c9 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Fri, 14 May 2021 03:34:50 +0200 Subject: [PATCH 32/47] Add `#nullable enable` Co-authored-by: Dean Herbert --- osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 53bdf3140c..13a892def4 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; - + #nullable enable namespace osu.Game.Rulesets.Edit { /// From a447f200958977b86129d5159edb9891fc6e2031 Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Fri, 14 May 2021 03:38:35 +0200 Subject: [PATCH 33/47] Fix formatting of `#nullable enable` --- osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 13a892def4..6feee82bda 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; - #nullable enable + +#nullable enable + namespace osu.Game.Rulesets.Edit { /// From 9860e482afe591d5b68916fe594b77ff913ef85e Mon Sep 17 00:00:00 2001 From: Naxess <30292137+Naxesss@users.noreply.github.com> Date: Fri, 14 May 2021 05:32:52 +0200 Subject: [PATCH 34/47] Use `TestWorkingBeatmap` instead of null in tests Fixes the warning that #12801 will give. --- .../Editing/Checks/CheckConcurrentObjectsTest.cs | 7 +++---- osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs | 7 +++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs index ba0a130a25..5adb91a22e 100644 --- a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Editing.Checks { @@ -186,10 +187,8 @@ namespace osu.Game.Tests.Editing.Checks private BeatmapVerifierContext getContext(List hitobjects) { - return new BeatmapVerifierContext(new Beatmap - { - HitObjects = hitobjects - }, null); + var beatmap = new Beatmap { HitObjects = hitobjects }; + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); } } } diff --git a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs index 02159fa57b..639f5b5ab4 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Editing.Checks { @@ -146,11 +147,13 @@ namespace osu.Game.Tests.Editing.Checks private BeatmapVerifierContext getContext(List hitobjects) { - return new BeatmapVerifierContext(new Beatmap + var beatmap = new Beatmap { ControlPointInfo = cpi, HitObjects = hitobjects - }, null); + }; + + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); } } } From 9069db07437154554fb6c1b55fa323dcac2c6c45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 May 2021 16:22:19 +0900 Subject: [PATCH 35/47] Fix case of `hitObjects` variables --- .../Checks/CheckUnsnappedObjectsTest.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs index 639f5b5ab4..882baba8fa 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs @@ -102,12 +102,12 @@ namespace osu.Game.Tests.Editing.Checks }, count: 2); // Start and end are 2 ms and 1.25 ms off respectively, hence two different issues in one object. - var hitobjects = new List + var hitObjects = new List { getSliderMock(startTime: 98, endTime: 398.75d).Object }; - var issues = check.Run(getContext(hitobjects)).ToList(); + var issues = check.Run(getContext(hitObjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(2)); Assert.That(issues.Any(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap)); @@ -124,33 +124,33 @@ namespace osu.Game.Tests.Editing.Checks return mockSlider; } - private void assertOk(List hitobjects) + private void assertOk(List hitObjects) { - Assert.That(check.Run(getContext(hitobjects)), Is.Empty); + Assert.That(check.Run(getContext(hitObjects)), Is.Empty); } - private void assert1Ms(List hitobjects, int count = 1) + private void assert1Ms(List hitObjects, int count = 1) { - var issues = check.Run(getContext(hitobjects)).ToList(); + var issues = check.Run(getContext(hitObjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateSmallUnsnap)); } - private void assert2Ms(List hitobjects, int count = 1) + private void assert2Ms(List hitObjects, int count = 1) { - var issues = check.Run(getContext(hitobjects)).ToList(); + var issues = check.Run(getContext(hitObjects)).ToList(); Assert.That(issues, Has.Count.EqualTo(count)); Assert.That(issues.All(issue => issue.Template is CheckUnsnappedObjects.IssueTemplateLargeUnsnap)); } - private BeatmapVerifierContext getContext(List hitobjects) + private BeatmapVerifierContext getContext(List hitObjects) { var beatmap = new Beatmap { ControlPointInfo = cpi, - HitObjects = hitobjects + HitObjects = hitObjects }; return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); From fcb226bd206ed17e01de4aa18e0ed2ece8416f80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 May 2021 16:23:45 +0900 Subject: [PATCH 36/47] Add local variable for regular access to `HitObjects` --- .../Rulesets/Edit/Checks/CheckConcurrentObjects.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs index 51277298ab..ba5fbcf58d 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs @@ -23,13 +23,15 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - for (int i = 0; i < context.Beatmap.HitObjects.Count - 1; ++i) - { - var hitobject = context.Beatmap.HitObjects[i]; + var hitObjects = context.Beatmap.HitObjects; - for (int j = i + 1; j < context.Beatmap.HitObjects.Count; ++j) + for (int i = 0; i < hitObjects.Count - 1; ++i) + { + var hitobject = hitObjects[i]; + + for (int j = i + 1; j < hitObjects.Count; ++j) { - var nextHitobject = context.Beatmap.HitObjects[j]; + var nextHitobject = hitObjects[j]; // Accounts for rulesets with hitobjects separated by columns, such as Mania. // In these cases we only care about concurrent objects within the same column. From 67a99c83a35ab4e4cf5281faddce1b4b689f1f42 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 May 2021 16:24:52 +0900 Subject: [PATCH 37/47] Tidy bindable changed code up --- osu.Game/Screens/Edit/Verify/IssueList.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index fc9d4c7526..0b1f988447 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -46,10 +46,7 @@ namespace osu.Game.Screens.Edit.Verify rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier(); context = new BeatmapVerifierContext(beatmap, workingBeatmap.Value, verify.InterpretedDifficulty.Value); - verify.InterpretedDifficulty.BindValueChanged(change => - { - context.InterpretedDifficulty = change.NewValue; - }); + verify.InterpretedDifficulty.BindValueChanged(difficulty => context.InterpretedDifficulty = difficulty.NewValue); RelativeSizeAxes = Axes.Both; From 0655825057cf47520211f5ac99021eb2730cf5e2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 14:24:56 +0300 Subject: [PATCH 38/47] Separate changing star rating display to own test --- .../Ranking/TestSceneStarRatingDisplay.cs | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index 2ff664a0d9..64f78b0802 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Screens.Ranking.Expanded; +using osuTK; namespace osu.Game.Tests.Visual.Ranking { @@ -15,28 +16,38 @@ namespace osu.Game.Tests.Visual.Ranking [Test] public void TestDisplay() { - StarRatingDisplay changingStarRating = null; - AddStep("load displays", () => Child = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] { - new StarRatingDisplay(new StarDifficulty(1.23, 0)), - new StarRatingDisplay(new StarDifficulty(2.34, 0)), - new StarRatingDisplay(new StarDifficulty(3.45, 0)), - new StarRatingDisplay(new StarDifficulty(4.56, 0)), - new StarRatingDisplay(new StarDifficulty(5.67, 0)), - new StarRatingDisplay(new StarDifficulty(6.78, 0)), - new StarRatingDisplay(new StarDifficulty(10.11, 0)), - changingStarRating = new StarRatingDisplay(), + new StarRatingDisplay(new StarDifficulty(1.23, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(2.34, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(3.45, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(4.56, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(5.67, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(6.78, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, + new StarRatingDisplay(new StarDifficulty(10.11, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, } }); + } - AddRepeatStep("change bottom rating", () => + [Test] + public void TestChangingStarRatingDisplay() + { + StarRatingDisplay starRating = null; + + AddStep("load display", () => Child = starRating = new StarRatingDisplay { - changingStarRating.Current.Value = new StarDifficulty(RNG.NextDouble(0, 10), RNG.Next()); + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3f), + }); + + AddRepeatStep("change display value", () => + { + starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), RNG.Next(2000)); }, 10); } } From 34aab11ff3fc9e3f9c0370ff076bfd00e25d3cb8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 14:25:46 +0300 Subject: [PATCH 39/47] Add null star rating display test case --- .../Visual/Ranking/TestSceneStarRatingDisplay.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index 64f78b0802..7730d6868d 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -33,6 +33,17 @@ namespace osu.Game.Tests.Visual.Ranking }); } + [Test] + public void TestNullStarRatingDisplay() + { + AddStep("load null", () => Child = new StarRatingDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3f), + }); + } + [Test] public void TestChangingStarRatingDisplay() { From e0728a6e194297b55eb8f9f4502f919ba3907a0d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 15:52:36 +0300 Subject: [PATCH 40/47] Make `BeatmapDifficultyCache.GetDifficultyAsync` virtual --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 53d82c385d..6ed623d0c0 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -103,8 +103,8 @@ namespace osu.Game.Beatmaps /// The s to get the difficulty with. /// An optional which stops computing the star difficulty. /// The . - public Task GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null, [CanBeNull] IEnumerable mods = null, - CancellationToken cancellationToken = default) + public virtual Task GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null, + [CanBeNull] IEnumerable mods = null, CancellationToken cancellationToken = default) { // In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset. rulesetInfo ??= beatmapInfo.Ruleset; From db361efecfacce01093783caa0031bee658cdd02 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 15:52:51 +0300 Subject: [PATCH 41/47] Add test beatmap difficulty cache with calc. blocking support --- .../TestSceneBeatmapMetadataDisplay.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 230822e070..271fbde5c3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -4,12 +4,15 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; @@ -24,6 +27,9 @@ namespace osu.Game.Tests.Visual.SongSelect [Resolved] private BeatmapManager manager { get; set; } + [Cached(typeof(BeatmapDifficultyCache))] + private readonly TestBeatmapDifficultyCache testDifficultyCache = new TestBeatmapDifficultyCache(); + [Test] public void TestLocal([Values("Beatmap", "Some long title and stuff")] string title, @@ -44,6 +50,27 @@ namespace osu.Game.Tests.Visual.SongSelect })); } + [Test] + public void TestDelayedStarRating() + { + AddStep("block calculation", () => testDifficultyCache.BlockCalculation = true); + + showMetadataForBeatmap(() => CreateWorkingBeatmap(new Beatmap + { + BeatmapInfo = + { + Metadata = new BeatmapMetadata + { + Title = "Heavy beatmap", + }, + Version = "10k objects", + StarDifficulty = 99.99f, + } + })); + + AddStep("allow calculation", () => testDifficultyCache.BlockCalculation = false); + } + [Test] public void TestRandomFromDatabase() { @@ -68,8 +95,11 @@ namespace osu.Game.Tests.Visual.SongSelect OsuLogo logo = new OsuLogo { Scale = new Vector2(0.15f) }; + Remove(testDifficultyCache); + Children = new Drawable[] { + testDifficultyCache, display = new BeatmapMetadataDisplay(getBeatmap(), new Bindable>(randomMods), logo) { Anchor = Anchor.Centre, @@ -85,5 +115,37 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("finish loading", () => display.Loading = false); } + + private class TestBeatmapDifficultyCache : BeatmapDifficultyCache + { + private TaskCompletionSource calculationBlocker; + + private bool blockCalculation; + + public bool BlockCalculation + { + get => blockCalculation; + set + { + if (value == blockCalculation) + return; + + blockCalculation = value; + + if (value) + calculationBlocker = new TaskCompletionSource(); + else + calculationBlocker?.SetResult(false); + } + } + + public override async Task GetDifficultyAsync(BeatmapInfo beatmapInfo, RulesetInfo rulesetInfo = null, IEnumerable mods = null, CancellationToken cancellationToken = default) + { + if (blockCalculation) + await calculationBlocker.Task; + + return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken); + } + } } } From 0dc3bfd0c11cc45f060ecb627cef78db1beb6f5c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 15:55:26 +0300 Subject: [PATCH 42/47] Apply simple transforms to star rating display when ready if not --- .../Screens/Play/BeatmapMetadataDisplay.cs | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 0164fe9179..6dd9900d8c 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -53,11 +53,12 @@ namespace osu.Game.Screens.Play private IBindable starDifficulty; + private FillFlowContainer versionFlow; + private StarRatingDisplay starRatingDisplay; + [BackgroundDependencyLoader] private void load(BeatmapDifficultyCache difficultyCache) { - StarRatingDisplay starRatingDisplay; - var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); AutoSizeAxes = Axes.Both; @@ -112,7 +113,7 @@ namespace osu.Game.Screens.Play loading = new LoadingLayer(true) } }, - new FillFlowContainer + versionFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, @@ -178,11 +179,32 @@ namespace osu.Game.Screens.Play }; starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo); - starDifficulty.BindValueChanged(d => starRatingDisplay.Current.Value = d.NewValue, true); Loading = true; } + protected override void LoadComplete() + { + base.LoadComplete(); + + if (starDifficulty.Value != null) + starRatingDisplay.Current.Value = starDifficulty.Value; + else + { + starRatingDisplay.Hide(); + + starDifficulty.ValueChanged += d => + { + starRatingDisplay.Current.Value = d.NewValue; + + versionFlow.AutoSizeDuration = 300; + versionFlow.AutoSizeEasing = Easing.OutQuint; + + starRatingDisplay.FadeIn(300, Easing.InQuint); + }; + } + } + private class MetadataLineLabel : OsuSpriteText { public MetadataLineLabel(string text) From 6cc678f497b1cdb1aa461ebd4749e145fdc5c80f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 16:01:25 +0300 Subject: [PATCH 43/47] Remove nullability and transition support from star rating display --- .../Ranking/TestSceneStarRatingDisplay.cs | 23 +++++-------- .../Ranking/Expanded/StarRatingDisplay.cs | 33 +++++-------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index 7730d6868d..ef077970d6 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -33,33 +33,28 @@ namespace osu.Game.Tests.Visual.Ranking }); } - [Test] - public void TestNullStarRatingDisplay() - { - AddStep("load null", () => Child = new StarRatingDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(3f), - }); - } - [Test] public void TestChangingStarRatingDisplay() { StarRatingDisplay starRating = null; - AddStep("load display", () => Child = starRating = new StarRatingDisplay + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(3f), }); - AddRepeatStep("change display value", () => + AddRepeatStep("set random value", () => { - starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), RNG.Next(2000)); + starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1); }, 10); + + AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d => + { + if (starRating != null) + starRating.Current.Value = new StarDifficulty(d, 1); + }); } } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 422833555f..625bdaf888 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Ranking.Expanded /// /// A pill that displays the star rating of a . /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { private Box background; private OsuTextFlowContainer textFlow; @@ -30,21 +30,14 @@ namespace osu.Game.Screens.Ranking.Expanded [Resolved] private OsuColour colours { get; set; } - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; } - /// - /// Creates a new without any set, displaying a placeholder until is changed. - /// - public StarRatingDisplay() - { - } - /// /// Creates a new using an already computed . /// @@ -112,26 +105,16 @@ namespace osu.Game.Screens.Ranking.Expanded private void updateDisplay() { - const double duration = 400; - const Easing easing = Easing.OutQuint; - - double stars = Current.Value?.Stars ?? 0.00f; - - var starRatingParts = stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + var starRatingParts = Current.Value.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); string wholePart = starRatingParts[0]; string fractionPart = starRatingParts[1]; string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - if (Current.Value == null) - background.FadeColour(Color4.SlateGray.Opacity(0.3f)); - else - { - var rating = Current.Value.Value.DifficultyRating; + var rating = Current.Value.DifficultyRating; - background.FadeColour(rating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(rating), duration, easing); - } + background.Colour = rating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(rating); textFlow.Clear(); From 7c2fc9b412e5e5835ea0b949de5814224d201de7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 16:12:25 +0300 Subject: [PATCH 44/47] Update usage due to nullability removal --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 6dd9900d8c..e26dd24de7 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -130,8 +131,9 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - starRatingDisplay = new StarRatingDisplay + starRatingDisplay = new StarRatingDisplay(default) { + Alpha = 0f, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, } @@ -188,14 +190,19 @@ namespace osu.Game.Screens.Play base.LoadComplete(); if (starDifficulty.Value != null) - starRatingDisplay.Current.Value = starDifficulty.Value; + { + starRatingDisplay.Current.Value = starDifficulty.Value.Value; + starRatingDisplay.Show(); + } else { starRatingDisplay.Hide(); starDifficulty.ValueChanged += d => { - starRatingDisplay.Current.Value = d.NewValue; + Debug.Assert(d.NewValue != null); + + starRatingDisplay.Current.Value = d.NewValue.Value; versionFlow.AutoSizeDuration = 300; versionFlow.AutoSizeEasing = Easing.OutQuint; From 8b4e6d29112db730e873dd5828bcb3cd6cda514c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 14 May 2021 21:52:09 +0200 Subject: [PATCH 45/47] Remove no longer necessary `FinishTransforms(true)` call As the component no longer has any transition transforms applied. --- osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 625bdaf888..7aba699216 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -100,7 +100,6 @@ namespace osu.Game.Screens.Ranking.Expanded base.LoadComplete(); Current.BindValueChanged(_ => updateDisplay(), true); - FinishTransforms(true); } private void updateDisplay() From 1c92b3a8f52af41f45d026c41a0d09ce890a7b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 14 May 2021 21:58:04 +0200 Subject: [PATCH 46/47] De-duplicate star rating display creation in test --- .../Ranking/TestSceneStarRatingDisplay.cs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs index ef077970d6..566452249f 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs @@ -1,6 +1,7 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; @@ -20,16 +21,20 @@ namespace osu.Game.Tests.Visual.Ranking { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Children = new Drawable[] + ChildrenEnumerable = new[] { - new StarRatingDisplay(new StarDifficulty(1.23, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(2.34, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(3.45, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(4.56, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(5.67, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(6.78, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new StarRatingDisplay(new StarDifficulty(10.11, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - } + 1.23, + 2.34, + 3.45, + 4.56, + 5.67, + 6.78, + 10.11, + }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }) }); } From 34d14907548cef21ae02cd8bf3eb7d26a3d16a3b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 15 May 2021 10:00:04 +0300 Subject: [PATCH 47/47] Remove null conditional Shouldn't guard against that here. --- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index e26dd24de7..fd1150650c 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(BeatmapDifficultyCache difficultyCache) { - var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + var metadata = beatmap.BeatmapInfo.Metadata; AutoSizeAxes = Axes.Both; Children = new Drawable[]