From 0f08c2a4799d3002861b199205c0e20e4498ff23 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 8 May 2021 11:44:29 +0300 Subject: [PATCH 01/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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/26] 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 e0728a6e194297b55eb8f9f4502f919ba3907a0d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 15:52:36 +0300 Subject: [PATCH 21/26] 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 22/26] 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 23/26] 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 7c2fc9b412e5e5835ea0b949de5814224d201de7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 May 2021 16:12:25 +0300 Subject: [PATCH 24/26] 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 34d14907548cef21ae02cd8bf3eb7d26a3d16a3b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 15 May 2021 10:00:04 +0300 Subject: [PATCH 25/26] 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[] From 265a89e5cc778e5c7054f566bdcaba16d61bf3a6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 18 May 2021 09:45:32 +0300 Subject: [PATCH 26/26] Fix `LegacySkinPlayerTestScene` overriden by default beatmap skin --- .../Tests/Visual/LegacySkinPlayerTestScene.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs index c186525757..27ddd77c03 100644 --- a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs +++ b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs @@ -1,11 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.IO.Stores; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Skinning; +using osu.Game.Storyboards; namespace osu.Game.Tests.Visual { @@ -16,6 +22,9 @@ namespace osu.Game.Tests.Visual protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(legacySkinSource); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) + => new LegacySkinWorkingBeatmap(beatmap, storyboard, Clock, Audio); + [BackgroundDependencyLoader] private void load(OsuGameBase game, SkinManager skins) { @@ -23,6 +32,14 @@ namespace osu.Game.Tests.Visual legacySkinSource = new SkinProvidingContainer(legacySkin); } + public override void SetUpSteps() + { + base.SetUpSteps(); + + // check presence of a random legacy HUD component to ensure this is using legacy skin. + AddAssert("using legacy skin", () => this.ChildrenOfType().Any()); + } + public class SkinProvidingPlayer : TestPlayer { [Cached(typeof(ISkinSource))] @@ -33,5 +50,15 @@ namespace osu.Game.Tests.Visual this.skinSource = skinSource; } } + + private class LegacySkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + public LegacySkinWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock frameBasedClock, AudioManager audio) + : base(beatmap, storyboard, frameBasedClock, audio) + { + } + + protected override ISkin GetSkin() => new LegacyBeatmapSkin(BeatmapInfo, null, null); + } } }