From e7ab54379933937e8affbb008b0e3dacd3e3c92a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 13 Jan 2023 16:08:34 -0800 Subject: [PATCH 1/8] Add ability to view converted beatmaps on beatmap set overlay --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 4 ++++ osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 3 +++ osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 3 +++ osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 5 +++-- osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs | 3 ++- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 1665ec52fa..41db2399ac 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -116,6 +117,9 @@ namespace osu.Game.Beatmaps.Drawables private Drawable getRulesetIcon() { + if ((beatmap as APIBeatmap)?.Convert == true) + return rulesets.GetRuleset(0)!.CreateInstance().CreateIcon(); + int? onlineID = ruleset.OnlineID; if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 27ad2a746c..7d6740ee46 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -63,6 +63,9 @@ namespace osu.Game.Online.API.Requests.Responses set => Length = TimeSpan.FromSeconds(value).TotalMilliseconds; } + [JsonProperty(@"convert")] + public bool Convert { get; set; } + [JsonProperty(@"count_circles")] public int CircleCount { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index aeae3edde2..d39ed1e1ed 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -125,6 +125,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"beatmaps")] public APIBeatmap[] Beatmaps { get; set; } = Array.Empty(); + [JsonProperty(@"converts")] + public APIBeatmap[] Converts { get; set; } = Array.Empty(); + private BeatmapMetadata metadata => new BeatmapMetadata { Title = Title, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 84d12f2611..51b6b14579 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -168,9 +168,10 @@ namespace osu.Game.Overlays.BeatmapSet if (BeatmapSet != null) { - Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Concat(BeatmapSet.Converts) .Where(b => b.Ruleset.MatchesOnlineID(ruleset.Value)) - .OrderBy(b => b.StarRating) + .OrderBy(b => !b.Convert) + .ThenBy(b => b.StarRating) .Select(b => new DifficultySelectorButton(b) { State = DifficultySelectorState.NotSelected, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index f802807c3c..76e2f256b0 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -68,11 +68,12 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { int beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.MatchesOnlineID(Value)) ?? 0; + int osuBeatmaps = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.OnlineID == 0) ?? 0; count.Text = beatmapsCount.ToString(); countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0); - Enabled.Value = beatmapsCount > 0; + Enabled.Value = beatmapsCount > 0 || osuBeatmaps > 0; }, true); } } From 85c1932851bf71202805c9cbcfe133d32ee3088b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 15 Jan 2023 12:46:41 -0800 Subject: [PATCH 2/8] Mark `Converts` as nullable --- osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index d39ed1e1ed..d98715a42d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -126,7 +126,7 @@ namespace osu.Game.Online.API.Requests.Responses public APIBeatmap[] Beatmaps { get; set; } = Array.Empty(); [JsonProperty(@"converts")] - public APIBeatmap[] Converts { get; set; } = Array.Empty(); + public APIBeatmap[]? Converts { get; set; } private BeatmapMetadata metadata => new BeatmapMetadata { diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 51b6b14579..0ee7dfc9bd 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -168,7 +168,7 @@ namespace osu.Game.Overlays.BeatmapSet if (BeatmapSet != null) { - Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Concat(BeatmapSet.Converts) + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Concat(BeatmapSet.Converts ?? Array.Empty()) .Where(b => b.Ruleset.MatchesOnlineID(ruleset.Value)) .OrderBy(b => !b.Convert) .ThenBy(b => b.StarRating) From b733f46c6fed49d930da4e0cf20d5949c5914ddd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 15 Jan 2023 14:15:36 -0800 Subject: [PATCH 3/8] Apply NRT to `BeatmapPicker` --- .../TestSceneStartupBeatmapDisplay.cs | 4 +--- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 22 +++++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs index 0c165bc40e..25cef8440a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; @@ -50,7 +48,7 @@ namespace osu.Game.Tests.Visual.Navigation public void TestBeatmapLink() { AddUntilStep("Beatmap overlay displayed", () => Game.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Visible); - AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType().FirstOrDefault()?.Beatmap.Value.OnlineID == requested_beatmap_id); + AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType().FirstOrDefault()?.Beatmap.Value?.OnlineID == requested_beatmap_id); } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 0ee7dfc9bd..76fc1bbf53 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework; @@ -38,10 +36,10 @@ namespace osu.Game.Overlays.BeatmapSet public readonly DifficultiesContainer Difficulties; - public readonly Bindable Beatmap = new Bindable(); - private APIBeatmapSet beatmapSet; + public readonly Bindable Beatmap = new Bindable(); + private APIBeatmapSet? beatmapSet; - public APIBeatmapSet BeatmapSet + public APIBeatmapSet? BeatmapSet { get => beatmapSet; set @@ -142,7 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet } [Resolved] - private IBindable ruleset { get; set; } + private IBindable ruleset { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -200,9 +198,9 @@ namespace osu.Game.Overlays.BeatmapSet updateDifficultyButtons(); } - private void showBeatmap(IBeatmapInfo beatmapInfo) + private void showBeatmap(IBeatmapInfo? beatmapInfo) { - version.Text = beatmapInfo?.DifficultyName; + version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } private void updateDifficultyButtons() @@ -212,7 +210,7 @@ namespace osu.Game.Overlays.BeatmapSet public partial class DifficultiesContainer : FillFlowContainer { - public Action OnLostHover; + public Action? OnLostHover; protected override void OnHoverLost(HoverLostEvent e) { @@ -233,9 +231,9 @@ namespace osu.Game.Overlays.BeatmapSet public readonly APIBeatmap Beatmap; - public Action OnHovered; - public Action OnClicked; - public event Action StateChanged; + public Action? OnHovered; + public Action? OnClicked; + public event Action? StateChanged; private DifficultySelectorState state; From ae49e724e43ebe449f1229c1efbed7157d00ba23 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 15 Jan 2023 14:17:46 -0800 Subject: [PATCH 4/8] Move converted beatmap icons logic locally --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 4 ---- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 41db2399ac..1665ec52fa 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -117,9 +116,6 @@ namespace osu.Game.Beatmaps.Drawables private Drawable getRulesetIcon() { - if ((beatmap as APIBeatmap)?.Convert == true) - return rulesets.GetRuleset(0)!.CreateInstance().CreateIcon(); - int? onlineID = ruleset.OnlineID; if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 76fc1bbf53..585e0dd1a2 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -170,7 +170,7 @@ namespace osu.Game.Overlays.BeatmapSet .Where(b => b.Ruleset.MatchesOnlineID(ruleset.Value)) .OrderBy(b => !b.Convert) .ThenBy(b => b.StarRating) - .Select(b => new DifficultySelectorButton(b) + .Select(b => new DifficultySelectorButton(b, b.Convert ? new RulesetInfo { OnlineID = 0 } : null) { State = DifficultySelectorState.NotSelected, OnHovered = beatmap => @@ -254,7 +254,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - public DifficultySelectorButton(APIBeatmap beatmapInfo) + public DifficultySelectorButton(APIBeatmap beatmapInfo, IRulesetInfo? ruleset) { Beatmap = beatmapInfo; Size = new Vector2(size); @@ -273,7 +273,7 @@ namespace osu.Game.Overlays.BeatmapSet Alpha = 0.5f } }, - icon = new DifficultyIcon(beatmapInfo) + icon = new DifficultyIcon(beatmapInfo, ruleset) { ShowTooltip = false, Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) }, From 6207a96a29f93733fbd1569d26f0ce02b78ae8f5 Mon Sep 17 00:00:00 2001 From: StanR Date: Mon, 16 Jan 2023 23:24:09 +0300 Subject: [PATCH 5/8] Refactor `LevelBadge` to use `LevelInfo` --- .../Profile/Header/CentreHeaderContainer.cs | 15 ++++++++++++--- .../Profile/Header/Components/LevelBadge.cs | 10 +++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 7721342ba8..fbd8f1e0c6 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; using osuTK; @@ -15,6 +16,8 @@ namespace osu.Game.Overlays.Profile.Header { public readonly Bindable User = new Bindable(); + private LevelBadge levelBadge = null!; + public CentreHeaderContainer() { Height = 60; @@ -62,12 +65,11 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, Children = new Drawable[] { - new LevelBadge + levelBadge = new LevelBadge { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Size = new Vector2(40), - User = { BindTarget = User } + Size = new Vector2(40) }, new Container { @@ -85,6 +87,13 @@ namespace osu.Game.Overlays.Profile.Header } } }; + + User.BindValueChanged(user => updateDisplay(user.NewValue?.User)); + } + + private void updateDisplay(APIUser? user) + { + levelBadge.LevelInfo.Value = user?.Statistics?.Level; } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index 78c5231736..a0c17ccf93 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -11,14 +11,14 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; +using osu.Game.Users; namespace osu.Game.Overlays.Profile.Header.Components { public partial class LevelBadge : CompositeDrawable, IHasTooltip { - public readonly Bindable User = new Bindable(); + public readonly Bindable LevelInfo = new Bindable(); public LocalisableString TooltipText { get; private set; } @@ -48,12 +48,12 @@ namespace osu.Game.Overlays.Profile.Header.Components } }; - User.BindValueChanged(user => updateLevel(user.NewValue?.User)); + LevelInfo.BindValueChanged(user => updateLevel(user.NewValue)); } - private void updateLevel(APIUser? user) + private void updateLevel(UserStatistics.LevelInfo? levelInfo) { - string level = user?.Statistics?.Level.Current.ToString() ?? "0"; + string level = levelInfo?.Current.ToString() ?? "0"; levelText.Text = level; TooltipText = UsersStrings.ShowStatsLevel(level); } From c5d09c0e2c82ff4ae5c7259d6459994972ff3ca2 Mon Sep 17 00:00:00 2001 From: StanR Date: Mon, 16 Jan 2023 23:36:50 +0300 Subject: [PATCH 6/8] Rename variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index a0c17ccf93..251cd1bae5 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } }; - LevelInfo.BindValueChanged(user => updateLevel(user.NewValue)); + LevelInfo.BindValueChanged(level => updateLevel(level.NewValue)); } private void updateLevel(UserStatistics.LevelInfo? levelInfo) From 3f75506552e9285534cfa47b69aa81cb41633df0 Mon Sep 17 00:00:00 2001 From: StanR Date: Mon, 16 Jan 2023 23:42:07 +0300 Subject: [PATCH 7/8] Move binding to `LoadComplete` --- osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index 251cd1bae5..b75ffcaf98 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -47,8 +47,11 @@ namespace osu.Game.Overlays.Profile.Header.Components Font = OsuFont.GetFont(size: 20) } }; + } - LevelInfo.BindValueChanged(level => updateLevel(level.NewValue)); + protected override void LoadComplete() + { + LevelInfo.BindValueChanged(level => updateLevel(level.NewValue), true); } private void updateLevel(UserStatistics.LevelInfo? levelInfo) From f79037cefb206f9e57a3dd450d51ec6f7af0c343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 16 Jan 2023 21:47:31 +0100 Subject: [PATCH 8/8] Move to `LoadComplete()` better --- osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs | 7 ++++++- osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index fbd8f1e0c6..0dab4d582d 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -87,8 +87,13 @@ namespace osu.Game.Overlays.Profile.Header } } }; + } - User.BindValueChanged(user => updateDisplay(user.NewValue?.User)); + protected override void LoadComplete() + { + base.LoadComplete(); + + User.BindValueChanged(user => updateDisplay(user.NewValue?.User), true); } private void updateDisplay(APIUser? user) diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index b75ffcaf98..00bb8cbc75 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -51,6 +51,8 @@ namespace osu.Game.Overlays.Profile.Header.Components protected override void LoadComplete() { + base.LoadComplete(); + LevelInfo.BindValueChanged(level => updateLevel(level.NewValue), true); }