From c907751a5cf4e53c7910212e9ff0643a3f9c36f5 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 16:57:18 +0100 Subject: [PATCH 01/87] Set up test scene and basic LeaderBoardScoreV2.cs shape --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 26 +++++++++++ .../Online/Leaderboards/LeaderBoardScoreV2.cs | 43 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs create mode 100644 osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs new file mode 100644 index 0000000000..2c631e943d --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -0,0 +1,26 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Leaderboards; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public partial class TestSceneLeaderboardScoreV2 : OsuTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Child = new Container + { + Width = 900, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Y, + Child = new LeaderBoardScoreV2() + }; + } + } +} diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs new file mode 100644 index 0000000000..07184b8474 --- /dev/null +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -0,0 +1,43 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Online.Leaderboards +{ + public partial class LeaderBoardScoreV2 : OsuClickableContainer + { + private const int HEIGHT = 60; + private const int corner_radius = 10; + + private static readonly Vector2 shear = new Vector2(0.15f, 0); + + private Container content = null!; + + [BackgroundDependencyLoader] + private void load() + { + Shear = shear; + RelativeSizeAxes = Axes.X; + Height = HEIGHT; + Child = content = new Container + { + Masking = true, + CornerRadius = corner_radius, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + } + } + }; + } + } +} From b7584b4a02471c5d8894f30189da61075b8e46ec Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 17:15:37 +0100 Subject: [PATCH 02/87] Add grid container with sections, add background colours and hover logic --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 10 ++- .../Online/Leaderboards/LeaderBoardScoreV2.cs | 78 ++++++++++++++++++- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 2c631e943d..377bc79605 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Leaderboards; +using osuTK; namespace osu.Game.Tests.Visual.SongSelect { @@ -13,13 +14,18 @@ namespace osu.Game.Tests.Visual.SongSelect [BackgroundDependencyLoader] private void load() { - Child = new Container + Child = new FillFlowContainer { Width = 900, Anchor = Anchor.Centre, Origin = Anchor.Centre, + Spacing = new Vector2(0, 10), AutoSizeAxes = Axes.Y, - Child = new LeaderBoardScoreV2() + Children = new Drawable[] + { + new LeaderBoardScoreV2(), + new LeaderBoardScoreV2(true) + } }; } } diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index 07184b8474..7a56657365 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -5,23 +5,43 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; +using osu.Game.Overlays; using osuTK; namespace osu.Game.Online.Leaderboards { public partial class LeaderBoardScoreV2 : OsuClickableContainer { + private readonly bool isPersonalBest; private const int HEIGHT = 60; private const int corner_radius = 10; + private const int transition_duration = 200; + + private Colour4 foregroundColour; + private Colour4 backgroundColour; private static readonly Vector2 shear = new Vector2(0.15f, 0); + [Cached] + private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + private Container content = null!; + private Box background = null!; + private Box foreground = null!; + + public LeaderBoardScoreV2(bool isPersonalBest = false) + { + this.isPersonalBest = isPersonalBest; + } [BackgroundDependencyLoader] private void load() { + foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; + backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; + Shear = shear; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -32,12 +52,68 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, + Colour = backgroundColour + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 65), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 176) + }, + Content = new[] + { + new[] + { + Empty(), + createCentreContent(), + Empty(), + } + } } } }; } + + private Container createCentreContent() => + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Masking = true, + CornerRadius = corner_radius, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + foreground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = foregroundColour + } + } + }; + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint); + background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); + } } } From 9ea151539670ad5bb8175026c8fcaeba6059e695 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 17:35:27 +0100 Subject: [PATCH 03/87] setup up rank and score logic flow --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 60 ++++++++++++++++++- .../Online/Leaderboards/LeaderBoardScoreV2.cs | 45 +++++++++++++- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 377bc79605..13eaf5417d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -4,7 +4,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Scoring; +using osu.Game.Users; using osuTK; namespace osu.Game.Tests.Visual.SongSelect @@ -14,6 +20,56 @@ namespace osu.Game.Tests.Visual.SongSelect [BackgroundDependencyLoader] private void load() { + var scores = new[] + { + new ScoreInfo + { + Position = 999, + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + Ruleset = new OsuRuleset().RulesetInfo, + User = new APIUser + { + Id = 6602580, + Username = @"waaiiru", + CountryCode = CountryCode.ES, + }, + }, + new ScoreInfo + { + Position = 110000, + Rank = ScoreRank.X, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Ruleset = new OsuRuleset().RulesetInfo, + User = new APIUser + { + Id = 4608074, + Username = @"Skycries", + CountryCode = CountryCode.BR, + }, + }, + new ScoreInfo + { + Position = 22333, + Rank = ScoreRank.S, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Ruleset = new OsuRuleset().RulesetInfo, + User = new APIUser + { + Id = 1541390, + Username = @"Toukai", + CountryCode = CountryCode.CA, + }, + } + }; + Child = new FillFlowContainer { Width = 900, @@ -23,8 +79,8 @@ namespace osu.Game.Tests.Visual.SongSelect AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new LeaderBoardScoreV2(), - new LeaderBoardScoreV2(true) + new LeaderBoardScoreV2(scores[0], 1), + new LeaderBoardScoreV2(scores[2], 3, true) } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index 7a56657365..d526172861 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -4,21 +4,32 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays; +using osu.Game.Scoring; +using osu.Game.Utils; using osuTK; namespace osu.Game.Online.Leaderboards { public partial class LeaderBoardScoreV2 : OsuClickableContainer { - private readonly bool isPersonalBest; + private readonly ScoreInfo score; + private const int HEIGHT = 60; private const int corner_radius = 10; private const int transition_duration = 200; + private readonly int? rank; + + private readonly bool isPersonalBest; + private Colour4 foregroundColour; private Colour4 backgroundColour; @@ -31,8 +42,10 @@ namespace osu.Game.Online.Leaderboards private Box background = null!; private Box foreground = null!; - public LeaderBoardScoreV2(bool isPersonalBest = false) + public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false) { + this.score = score; + this.rank = rank; this.isPersonalBest = isPersonalBest; } @@ -70,7 +83,14 @@ namespace osu.Game.Online.Leaderboards { new[] { - Empty(), + new RankLabel(rank) + { + Shear = -shear, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 35 + }, createCentreContent(), Empty(), } @@ -115,5 +135,24 @@ namespace osu.Game.Online.Leaderboards foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint); background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); } + + private partial class RankLabel : Container, IHasTooltip + { + public RankLabel(int? rank) + { + if (rank >= 1000) + TooltipText = $"#{rank:N0}"; + + Child = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true), + Text = rank == null ? "-" : rank.Value.FormatRank().Insert(0, "#") + }; + } + + public LocalisableString TooltipText { get; } + } } } From 9178e3fd7dba9d8a2fde74ecbd8c691b9f646f47 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 18:03:38 +0100 Subject: [PATCH 04/87] Add right side content --- .../Online/Leaderboards/LeaderBoardScoreV2.cs | 128 +++++++++++++++++- osu.Game/Rulesets/UI/ModSwitchTiny.cs | 16 +-- 2 files changed, 132 insertions(+), 12 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index d526172861..ed8536a2bf 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -1,24 +1,34 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Framework.Platform; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using osu.Game.Screens.Select; using osu.Game.Utils; using osuTK; namespace osu.Game.Online.Leaderboards { - public partial class LeaderBoardScoreV2 : OsuClickableContainer + public partial class LeaderBoardScoreV2 : OsuClickableContainer, IHasContextMenu { private readonly ScoreInfo score; @@ -38,10 +48,25 @@ namespace osu.Game.Online.Leaderboards [Cached] private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Resolved] + private SongSelect? songSelect { get; set; } + + [Resolved] + private IDialogOverlay? dialogOverlay { get; set; } + + [Resolved] + private Storage storage { get; set; } = null!; + private Container content = null!; private Box background = null!; private Box foreground = null!; + protected Container RankContainer { get; private set; } = null!; + private FillFlowContainer modsContainer = null!; + + private OsuSpriteText scoreText = null!; + private Drawable scoreRank = null!; + public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false) { this.score = score; @@ -50,7 +75,7 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load() + private void load(ScoreManager scoreManager) { foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; @@ -81,7 +106,7 @@ namespace osu.Game.Online.Leaderboards }, Content = new[] { - new[] + new Drawable[] { new RankLabel(rank) { @@ -92,12 +117,15 @@ namespace osu.Game.Online.Leaderboards Width = 35 }, createCentreContent(), - Empty(), + createRightSideContent(scoreManager) } } } } }; + + modsContainer.Spacing = new Vector2(modsContainer.Children.Count > 5 ? -20 : 2, 0); + modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 }; } private Container createCentreContent() => @@ -118,6 +146,63 @@ namespace osu.Game.Online.Leaderboards } }; + private FillFlowContainer createRightSideContent(ScoreManager scoreManager) => + new FillFlowContainer + { + Padding = new MarginPadding { Left = 11, Right = 15 }, + Y = -5, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Vertical, + Spacing = new Vector2(13, 0f), + Children = new Drawable[] + { + new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + scoreText = new OsuSpriteText + { + Shear = -shear, + Current = scoreManager.GetBindableTotalScoreString(score), + + //Does not match figma, adjusted to allow 8 digits to fit comfortably + Font = OsuFont.GetFont(size: 28, weight: FontWeight.SemiBold, fixedWidth: false), + }, + RankContainer = new Container + { + BypassAutoSizeAxes = Axes.Both, + Y = 2, + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Children = new[] + { + scoreRank = new UpdateableRank(score.Rank) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(32) + } + } + } + } + }, + modsContainer = new FillFlowContainer + { + Shear = -shear, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) + } + } + }; + protected override bool OnHover(HoverEvent e) { updateState(); @@ -154,5 +239,40 @@ namespace osu.Game.Online.Leaderboards public LocalisableString TooltipText { get; } } + + private partial class ColouredModSwitchTiny : ModSwitchTiny + { + [Resolved] + private OsuColour colours { get; set; } = null!; + + public ColouredModSwitchTiny(IMod mod) + : base(mod) + { + } + + protected override void UpdateState() + { + AcronymText.Colour = Colour4.FromHex("#555555"); + Background.Colour = colours.Yellow; + } + } + + public MenuItem[] ContextMenuItems + { + get + { + List items = new List(); + + if (score.Mods.Length > 0 && modsContainer.Any(s => s.IsHovered) && songSelect != null) + items.Add(new OsuMenuItem("Use these mods", MenuItemType.Highlighted, () => songSelect.Mods.Value = score.Mods)); + + if (score.Files.Count <= 0) return items.ToArray(); + + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage).Export(score))); + items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(score)))); + + return items.ToArray(); + } + } } } diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index a5cf75bd07..df7722761d 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -24,8 +24,8 @@ namespace osu.Game.Rulesets.UI private readonly IMod mod; - private readonly Box background; - private readonly OsuSpriteText acronymText; + protected Box Background; + protected OsuSpriteText AcronymText; private Color4 activeForegroundColour; private Color4 inactiveForegroundColour; @@ -44,11 +44,11 @@ namespace osu.Game.Rulesets.UI Masking = true, Children = new Drawable[] { - background = new Box + Background = new Box { RelativeSizeAxes = Axes.Both }, - acronymText = new OsuSpriteText + AcronymText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -78,14 +78,14 @@ namespace osu.Game.Rulesets.UI { base.LoadComplete(); - Active.BindValueChanged(_ => updateState(), true); + Active.BindValueChanged(_ => UpdateState(), true); FinishTransforms(true); } - private void updateState() + protected virtual void UpdateState() { - acronymText.FadeColour(Active.Value ? activeForegroundColour : inactiveForegroundColour, 200, Easing.OutQuint); - background.FadeColour(Active.Value ? activeBackgroundColour : inactiveBackgroundColour, 200, Easing.OutQuint); + AcronymText.FadeColour(Active.Value ? activeForegroundColour : inactiveForegroundColour, 200, Easing.OutQuint); + Background.FadeColour(Active.Value ? activeBackgroundColour : inactiveBackgroundColour, 200, Easing.OutQuint); } } } From cfbf6672e51bba0bad7f23d0d245aeba7c9a9a09 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 18:12:59 +0100 Subject: [PATCH 05/87] Add flag and user name --- .../Online/Leaderboards/LeaderBoardScoreV2.cs | 94 ++++++++++++++++++- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index ed8536a2bf..f5c002446a 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.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; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -13,16 +14,19 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Select; +using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; @@ -61,7 +65,14 @@ namespace osu.Game.Online.Leaderboards private Box background = null!; private Box foreground = null!; + private Drawable avatar = null!; + private ClickableAvatar innerAvatar = null!; + + private OsuSpriteText nameLabel = null!; + protected Container RankContainer { get; private set; } = null!; + + private FillFlowContainer flagBadgeAndDateContainer = null!; private FillFlowContainer modsContainer = null!; private OsuSpriteText scoreText = null!; @@ -77,6 +88,8 @@ namespace osu.Game.Online.Leaderboards [BackgroundDependencyLoader] private void load(ScoreManager scoreManager) { + var user = score.User; + foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; @@ -116,7 +129,7 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Y, Width = 35 }, - createCentreContent(), + createCentreContent(user), createRightSideContent(scoreManager) } } @@ -124,11 +137,13 @@ namespace osu.Game.Online.Leaderboards } }; + innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); + modsContainer.Spacing = new Vector2(modsContainer.Children.Count > 5 ? -20 : 2, 0); modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 }; } - private Container createCentreContent() => + private Container createCentreContent(APIUser user) => new Container { Anchor = Anchor.CentreLeft, @@ -136,13 +151,63 @@ namespace osu.Game.Online.Leaderboards Masking = true, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Children = new[] { foreground = new Box { RelativeSizeAxes = Axes.Both, Colour = foregroundColour - } + }, + avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(HEIGHT) + }, + new FillFlowContainer + { + Position = new Vector2(HEIGHT + 9, 9), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + flagBadgeAndDateContainer = new FillFlowContainer + { + Shear = -shear, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + Size = new Vector2(87, 16), + Masking = true, + Children = new Drawable[] + { + new UpdateableFlag(user.CountryCode) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(24, 16), + }, + new DateLabel(score.Date) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + } + }, + nameLabel = new OsuSpriteText + { + Shear = -shear, + Text = user.Username, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) + } + } + }, } }; @@ -221,6 +286,17 @@ namespace osu.Game.Online.Leaderboards background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); } + private partial class DateLabel : DrawableDate + { + public DateLabel(DateTimeOffset date) + : base(date) + { + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Medium, italics: true); + } + + protected override string Format() => Date.ToShortRelativeTime(TimeSpan.FromSeconds(30)); + } + private partial class RankLabel : Container, IHasTooltip { public RankLabel(int? rank) @@ -240,6 +316,16 @@ namespace osu.Game.Online.Leaderboards public LocalisableString TooltipText { get; } } + private partial class MaskedWrapper : DelayedLoadWrapper + { + public MaskedWrapper(Drawable content, double timeBeforeLoad = 500) + : base(content, timeBeforeLoad) + { + CornerRadius = corner_radius; + Masking = true; + } + } + private partial class ColouredModSwitchTiny : ModSwitchTiny { [Resolved] From 6b889c2c534fa61f3e0e09bcdcefe1e373b99da9 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 18:21:19 +0100 Subject: [PATCH 06/87] add score component label and animate component --- .../Online/Leaderboards/LeaderBoardScoreV2.cs | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index f5c002446a..d9a47914a3 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -19,16 +20,19 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; +using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Online.Leaderboards { @@ -69,6 +73,7 @@ namespace osu.Game.Online.Leaderboards private ClickableAvatar innerAvatar = null!; private OsuSpriteText nameLabel = null!; + private List statisticsLabels = null!; protected Container RankContainer { get; private set; } = null!; @@ -93,6 +98,8 @@ namespace osu.Game.Online.Leaderboards foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; + statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)).ToList(); + Shear = shear; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -268,6 +275,50 @@ namespace osu.Game.Online.Leaderboards } }; + protected (CaseTransformableString, LocalisableString DisplayAccuracy)[] GetStatistics(ScoreInfo model) => new[] + { + (EditorSetupStrings.ComboColourPrefix.ToUpper(), model.MaxCombo.ToString().Insert(model.MaxCombo.ToString().Length, "x")), + (BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper(), model.DisplayAccuracy), + (getResultNames(score).ToUpper(), getResults(score).ToUpper()) + }; + + public override void Show() + { + foreach (var d in new[] { avatar, nameLabel, scoreText, scoreRank, flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels)) + d.FadeOut(); + + Alpha = 0; + + content.MoveToY(75); + avatar.MoveToX(75); + nameLabel.MoveToX(150); + + this.FadeIn(200); + content.MoveToY(0, 800, Easing.OutQuint); + + using (BeginDelayedSequence(100)) + { + avatar.FadeIn(300, Easing.OutQuint); + nameLabel.FadeIn(350, Easing.OutQuint); + + avatar.MoveToX(0, 300, Easing.OutQuint); + nameLabel.MoveToX(0, 350, Easing.OutQuint); + + using (BeginDelayedSequence(250)) + { + scoreText.FadeIn(200); + scoreRank.FadeIn(200); + + using (BeginDelayedSequence(50)) + { + var drawables = new Drawable[] { flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels).ToArray(); + for (int i = 0; i < drawables.Length; i++) + drawables[i].FadeIn(100 + i * 50); + } + } + } + } + protected override bool OnHover(HoverEvent e) { updateState(); @@ -297,6 +348,51 @@ namespace osu.Game.Online.Leaderboards protected override string Format() => Date.ToShortRelativeTime(TimeSpan.FromSeconds(30)); } + private partial class ScoreComponentLabel : Container + { + private readonly (LocalisableString Name, LocalisableString Value) statisticInfo; + private readonly ScoreInfo score; + + private FillFlowContainer content = null!; + public override bool Contains(Vector2 screenSpacePos) => content.Contains(screenSpacePos); + + public ScoreComponentLabel((LocalisableString Name, LocalisableString Value) statisticInfo, ScoreInfo score) + { + this.statisticInfo = statisticInfo; + this.score = score; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, OverlayColourProvider colourProvider) + { + AutoSizeAxes = Axes.Both; + OsuSpriteText value; + Child = content = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Right = 25 }, + Children = new Drawable[] + { + new OsuSpriteText + { + Colour = colourProvider.Content2, + Text = statisticInfo.Name, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + }, + value = new OsuSpriteText + { + Text = statisticInfo.Value, + Font = OsuFont.GetFont(size: 19, weight: FontWeight.Medium), + } + } + }; + + if (score.Combo == score.MaxCombo && statisticInfo.Name == EditorSetupStrings.ComboColourPrefix.ToUpper()) + value.Colour = colours.Lime1; + } + } + private partial class RankLabel : Container, IHasTooltip { public RankLabel(int? rank) @@ -360,5 +456,55 @@ namespace osu.Game.Online.Leaderboards return items.ToArray(); } } + + private LocalisableString getResults(ScoreInfo score) + { + string resultString = score.GetStatisticsForDisplay().Where(s => s.Result.IsBasic()).Aggregate(string.Empty, (current, result) => + current.Insert(current.Length, $"{result.Count}/")); + + return resultString.Remove(resultString.Length - 1); + } + + private LocalisableString getResultNames(ScoreInfo score) + { + string resultName = string.Empty; + + foreach (var hitResult in score.GetStatisticsForDisplay().Where(s => s.Result.IsBasic())) + { + switch (hitResult.Result) + { + case HitResult.Perfect: + appendToString("320/"); + break; + + case HitResult.Great: + appendToString("300/"); + break; + + case HitResult.Good: + appendToString("200/"); + break; + + case HitResult.Ok: + appendToString("100/"); + break; + + case HitResult.Meh: + appendToString("50/"); + break; + + case HitResult.Miss: + appendToString("X"); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + + void appendToString(string appendedString) => resultName = resultName.Insert(resultName.Length, appendedString); + + return resultName.Remove(resultName.Length); + } } } From 5a68b3062a5cbee236f2c875dca3b30974dc76c4 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 18:23:13 +0100 Subject: [PATCH 07/87] add statistics to main content --- osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index d9a47914a3..ccf48f4f74 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -215,6 +215,15 @@ namespace osu.Game.Online.Leaderboards } } }, + new FillFlowContainer + { + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels + } } }; From 83b10d61f493ec4029d1967890220eef0d8b44ad Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 19:03:17 +0100 Subject: [PATCH 08/87] Adjust widths in statistic labels --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 21 ++------------ .../Online/Leaderboards/LeaderBoardScoreV2.cs | 28 ++++++++++++++----- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 13eaf5417d..9a6f52a487 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -39,26 +39,11 @@ namespace osu.Game.Tests.Visual.SongSelect }, }, new ScoreInfo - { - Position = 110000, - Rank = ScoreRank.X, - Accuracy = 1, - MaxCombo = 244, - TotalScore = 1707827, - Ruleset = new OsuRuleset().RulesetInfo, - User = new APIUser - { - Id = 4608074, - Username = @"Skycries", - CountryCode = CountryCode.BR, - }, - }, - new ScoreInfo { Position = 22333, Rank = ScoreRank.S, - Accuracy = 1, - MaxCombo = 244, + Accuracy = 0.1f, + MaxCombo = 2404, TotalScore = 1707827, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -80,7 +65,7 @@ namespace osu.Game.Tests.Visual.SongSelect Children = new Drawable[] { new LeaderBoardScoreV2(scores[0], 1), - new LeaderBoardScoreV2(scores[2], 3, true) + new LeaderBoardScoreV2(scores[1], null, true) } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index ccf48f4f74..a9d86d75d7 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -40,7 +40,7 @@ namespace osu.Game.Online.Leaderboards { private readonly ScoreInfo score; - private const int HEIGHT = 60; + private const int height = 60; private const int corner_radius = 10; private const int transition_duration = 200; @@ -102,7 +102,7 @@ namespace osu.Game.Online.Leaderboards Shear = shear; RelativeSizeAxes = Axes.X; - Height = HEIGHT; + Height = height; Child = content = new Container { Masking = true, @@ -176,11 +176,11 @@ namespace osu.Game.Online.Leaderboards }) { RelativeSizeAxes = Axes.None, - Size = new Vector2(HEIGHT) + Size = new Vector2(height) }, new FillFlowContainer { - Position = new Vector2(HEIGHT + 9, 9), + Position = new Vector2(height + 9, 9), AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] @@ -217,6 +217,7 @@ namespace osu.Game.Online.Leaderboards }, new FillFlowContainer { + Spacing = new Vector2(5, 0), Shear = -shear, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -346,6 +347,8 @@ namespace osu.Game.Online.Leaderboards background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); } + #region Subclasses + private partial class DateLabel : DrawableDate { public DateLabel(DateTimeOffset date) @@ -374,13 +377,12 @@ namespace osu.Game.Online.Leaderboards [BackgroundDependencyLoader] private void load(OsuColour colours, OverlayColourProvider colourProvider) { - AutoSizeAxes = Axes.Both; + AutoSizeAxes = Axes.Y; OsuSpriteText value; Child = content = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Right = 25 }, Children = new Drawable[] { new OsuSpriteText @@ -397,8 +399,18 @@ namespace osu.Game.Online.Leaderboards } }; - if (score.Combo == score.MaxCombo && statisticInfo.Name == EditorSetupStrings.ComboColourPrefix.ToUpper()) + if (statisticInfo.Name == EditorSetupStrings.ComboColourPrefix.ToUpper()) + { + Width = 45; + + if (score.Combo != score.MaxCombo) return; + value.Colour = colours.Lime1; + + return; + } + + Width = statisticInfo.Name == BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper() ? 60 : 120; } } @@ -448,6 +460,8 @@ namespace osu.Game.Online.Leaderboards } } + #endregion + public MenuItem[] ContextMenuItems { get From 6c30ba25bc0b58a7870284f36fbe5d76cbe46b32 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 19:16:35 +0100 Subject: [PATCH 09/87] Add shading to mod pills --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 3 ++- osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 9a6f52a487..f9c3248791 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.SongSelect Accuracy = 1, MaxCombo = 244, TotalScore = 1707827, - Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), new OsuModAlternate(), new OsuModFlashlight(), new OsuModFreezeFrame() }, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -44,6 +44,7 @@ namespace osu.Game.Tests.Visual.SongSelect Rank = ScoreRank.S, Accuracy = 0.1f, MaxCombo = 2404, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), new OsuModAlternate(), new OsuModFlashlight(), new OsuModFreezeFrame(), new OsuModClassic() }, TotalScore = 1707827, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index a9d86d75d7..396fa7708b 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -451,6 +452,15 @@ namespace osu.Game.Online.Leaderboards public ColouredModSwitchTiny(IMod mod) : base(mod) { + Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Roundness = 15, + Type = EdgeEffectType.Shadow, + Colour = Colour4.Black.Opacity(0.15f), + Radius = 3, + Offset = new Vector2(-2, 0) + }; } protected override void UpdateState() From 3ccecc2cb5ebc1ee6cea13d4f6ccea9d44bdf2d6 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 19:24:03 +0100 Subject: [PATCH 10/87] Add back tooltip --- osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index 396fa7708b..08986f200e 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -37,7 +37,7 @@ using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Online.Leaderboards { - public partial class LeaderBoardScoreV2 : OsuClickableContainer, IHasContextMenu + public partial class LeaderBoardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { private readonly ScoreInfo score; @@ -77,13 +77,15 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels = null!; protected Container RankContainer { get; private set; } = null!; - private FillFlowContainer flagBadgeAndDateContainer = null!; private FillFlowContainer modsContainer = null!; private OsuSpriteText scoreText = null!; private Drawable scoreRank = null!; + public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); + public virtual ScoreInfo TooltipContent => score; + public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false) { this.score = score; From 1df049294701844bd880400ac465bc26a073fe3d Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 19:30:50 +0100 Subject: [PATCH 11/87] Add tooltip to new mod pills --- osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index 08986f200e..22c5db1a99 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -446,14 +446,17 @@ namespace osu.Game.Online.Leaderboards } } - private partial class ColouredModSwitchTiny : ModSwitchTiny + private partial class ColouredModSwitchTiny : ModSwitchTiny, IHasTooltip { + private readonly IMod mod; + [Resolved] private OsuColour colours { get; set; } = null!; public ColouredModSwitchTiny(IMod mod) : base(mod) { + this.mod = mod; Masking = true; EdgeEffect = new EdgeEffectParameters { @@ -470,6 +473,8 @@ namespace osu.Game.Online.Leaderboards AcronymText.Colour = Colour4.FromHex("#555555"); Background.Colour = colours.Yellow; } + + public virtual LocalisableString TooltipText => (mod as Mod)?.IconTooltip ?? mod.Name; } #endregion From 7c550e534005bd12811e90c5c38a124a2050a24d Mon Sep 17 00:00:00 2001 From: MK56 <74463310+mk56-spn@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:37:06 +0100 Subject: [PATCH 12/87] fix capitalisation issue in class name Co-authored-by: Joseph Madamba --- osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs index 22c5db1a99..6c16b8a9da 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs @@ -37,7 +37,7 @@ using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Online.Leaderboards { - public partial class LeaderBoardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip + public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { private readonly ScoreInfo score; From d73ce1ddb24b197b83a25e111d9afab63651bd2c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 22:51:46 +0100 Subject: [PATCH 13/87] Actually fix issue with naming of LeaderboardScoreV2.cs class --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 4 ++-- .../{LeaderBoardScoreV2.cs => LeaderboardScoreV2.cs} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Online/Leaderboards/{LeaderBoardScoreV2.cs => LeaderboardScoreV2.cs} (99%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index f9c3248791..4db2012733 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -65,8 +65,8 @@ namespace osu.Game.Tests.Visual.SongSelect AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new LeaderBoardScoreV2(scores[0], 1), - new LeaderBoardScoreV2(scores[1], null, true) + new LeaderboardScoreV2(scores[0], 1), + new LeaderboardScoreV2(scores[1], null, true) } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs similarity index 99% rename from osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs rename to osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 6c16b8a9da..0532d6e51b 100644 --- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -86,7 +86,7 @@ namespace osu.Game.Online.Leaderboards public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => score; - public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false) + public LeaderboardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false) { this.score = score; this.rank = rank; From c44891d42775d56022a5cf0616f516aa3662758d Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 17 Jan 2023 20:13:50 +0100 Subject: [PATCH 14/87] clean up linQ result formatting. Replace numbers with hitresult displaynames. Make adjustments to statistics to allow them to work with autosizing --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 2 +- .../Online/Leaderboards/LeaderboardScoreV2.cs | 76 +++++-------------- 2 files changed, 20 insertions(+), 58 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 4db2012733..04846d7f19 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.SongSelect Position = 22333, Rank = ScoreRank.S, Accuracy = 0.1f, - MaxCombo = 2404, + MaxCombo = 32040, Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), new OsuModAlternate(), new OsuModFlashlight(), new OsuModFreezeFrame(), new OsuModClassic() }, TotalScore = 1707827, Ruleset = new OsuRuleset().RulesetInfo, diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 0532d6e51b..093037e6d1 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -21,7 +21,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; @@ -33,7 +32,6 @@ using osu.Game.Screens.Select; using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; -using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Online.Leaderboards { @@ -220,7 +218,8 @@ namespace osu.Game.Online.Leaderboards }, new FillFlowContainer { - Spacing = new Vector2(5, 0), + Margin = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25, 0), Shear = -shear, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -290,7 +289,7 @@ namespace osu.Game.Online.Leaderboards protected (CaseTransformableString, LocalisableString DisplayAccuracy)[] GetStatistics(ScoreInfo model) => new[] { - (EditorSetupStrings.ComboColourPrefix.ToUpper(), model.MaxCombo.ToString().Insert(model.MaxCombo.ToString().Length, "x")), + (BeatmapsetsStrings.ShowScoreboardHeadersCombo.ToUpper(), model.MaxCombo.ToString().Insert(model.MaxCombo.ToString().Length, "x")), (BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper(), model.DisplayAccuracy), (getResultNames(score).ToUpper(), getResults(score).ToUpper()) }; @@ -380,7 +379,7 @@ namespace osu.Game.Online.Leaderboards [BackgroundDependencyLoader] private void load(OsuColour colours, OverlayColourProvider colourProvider) { - AutoSizeAxes = Axes.Y; + AutoSizeAxes = Axes.Both; OsuSpriteText value; Child = content = new FillFlowContainer { @@ -396,24 +395,17 @@ namespace osu.Game.Online.Leaderboards }, value = new OsuSpriteText { + // We don't want the value setting the horizontal size, since it leads to wonky accuracy container length, + // since the accuracy is sometimes longer than its name. + BypassAutoSizeAxes = Axes.X, Text = statisticInfo.Value, Font = OsuFont.GetFont(size: 19, weight: FontWeight.Medium), } } }; - if (statisticInfo.Name == EditorSetupStrings.ComboColourPrefix.ToUpper()) - { - Width = 45; - - if (score.Combo != score.MaxCombo) return; - + if (score.Combo != score.MaxCombo && statisticInfo.Name == BeatmapsetsStrings.ShowScoreboardHeadersCombo) value.Colour = colours.Lime1; - - return; - } - - Width = statisticInfo.Name == BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper() ? 60 : 120; } } @@ -446,7 +438,7 @@ namespace osu.Game.Online.Leaderboards } } - private partial class ColouredModSwitchTiny : ModSwitchTiny, IHasTooltip + private sealed partial class ColouredModSwitchTiny : ModSwitchTiny, IHasTooltip { private readonly IMod mod; @@ -474,7 +466,7 @@ namespace osu.Game.Online.Leaderboards Background.Colour = colours.Yellow; } - public virtual LocalisableString TooltipText => (mod as Mod)?.IconTooltip ?? mod.Name; + public LocalisableString TooltipText => (mod as Mod)?.IconTooltip ?? mod.Name; } #endregion @@ -499,52 +491,22 @@ namespace osu.Game.Online.Leaderboards private LocalisableString getResults(ScoreInfo score) { - string resultString = score.GetStatisticsForDisplay().Where(s => s.Result.IsBasic()).Aggregate(string.Empty, (current, result) => - current.Insert(current.Length, $"{result.Count}/")); + string resultString = score.GetStatisticsForDisplay() + .Where(s => s.Result.IsBasic()) + .Aggregate(string.Empty, (current, result) => + current.Insert(current.Length, $"{result.Count}/")); return resultString.Remove(resultString.Length - 1); } private LocalisableString getResultNames(ScoreInfo score) { - string resultName = string.Empty; + string resultName = score.GetStatisticsForDisplay() + .Where(s => s.Result.IsBasic()) + .Aggregate(string.Empty, (current, hitResult) => + current.Insert(current.Length, $"{hitResult.DisplayName.ToString().ToUpperInvariant()}/")); - foreach (var hitResult in score.GetStatisticsForDisplay().Where(s => s.Result.IsBasic())) - { - switch (hitResult.Result) - { - case HitResult.Perfect: - appendToString("320/"); - break; - - case HitResult.Great: - appendToString("300/"); - break; - - case HitResult.Good: - appendToString("200/"); - break; - - case HitResult.Ok: - appendToString("100/"); - break; - - case HitResult.Meh: - appendToString("50/"); - break; - - case HitResult.Miss: - appendToString("X"); - break; - - default: - throw new ArgumentOutOfRangeException(); - } - } - - void appendToString(string appendedString) => resultName = resultName.Insert(resultName.Length, appendedString); - - return resultName.Remove(resultName.Length); + return resultName.Remove(resultName.Length - 1); } } } From 4623c04f4676961f09dbbb5378d9db030bbb972c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 23 Jan 2023 11:35:42 +0100 Subject: [PATCH 15/87] Add mania score to leaderboard test scene --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 04846d7f19..0823da2248 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -53,7 +54,23 @@ namespace osu.Game.Tests.Visual.SongSelect Username = @"Toukai", CountryCode = CountryCode.CA, }, - } + }, + + new ScoreInfo + { + Position = 110000, + Rank = ScoreRank.X, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 17078279, + Ruleset = new ManiaRuleset().RulesetInfo, + User = new APIUser + { + Id = 4608074, + Username = @"Skycries", + CountryCode = CountryCode.BR, + }, + }, }; Child = new FillFlowContainer @@ -66,7 +83,8 @@ namespace osu.Game.Tests.Visual.SongSelect Children = new Drawable[] { new LeaderboardScoreV2(scores[0], 1), - new LeaderboardScoreV2(scores[1], null, true) + new LeaderboardScoreV2(scores[1], null, true), + new LeaderboardScoreV2(scores[2], null, true) } }; } From 4060373e0399d3d0cd80639050fcbf06e03dc0ae Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Sat, 5 Aug 2023 21:15:31 +0800 Subject: [PATCH 16/87] add rank display element --- osu.Game/Screens/Play/HUD/RankDisplay.cs | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/RankDisplay.cs diff --git a/osu.Game/Screens/Play/HUD/RankDisplay.cs b/osu.Game/Screens/Play/HUD/RankDisplay.cs new file mode 100644 index 0000000000..be8841b647 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/RankDisplay.cs @@ -0,0 +1,46 @@ +// 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.Allocation; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; +using osu.Framework.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Extensions; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class RankDisplay : FontAdjustableSkinComponent + { + [Resolved] + private ScoreProcessor scoreProcessor { get; set; } = null!; + + private readonly OsuSpriteText text; + + public RankDisplay() + { + AutoSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + text.Text = scoreProcessor.Rank.Value.GetDescription(); + + scoreProcessor.Rank.BindValueChanged(v => text.Text = v.NewValue.GetDescription()); + } + + protected override void SetFont(FontUsage font) => text.Font = font.With(size: 40); + } +} From c67f6d949bca80561bf82456c1132f6a5dea8403 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Sun, 6 Aug 2023 18:15:14 +0800 Subject: [PATCH 17/87] tests --- .../Archives/modified-argon-20230806.osk | Bin 0 -> 1354 bytes osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk b/osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk new file mode 100644 index 0000000000000000000000000000000000000000..e7c035811d62df429b930fd41548457307cbf90a GIT binary patch literal 1354 zcmWIWW@Zs#U|`^2_)x_b{xqpXate^Q9xTGZP@J8ar42}OmnuF-Rk~{%W2L3)BpF`hq7LuxG?;EX_=A3@+2KLW50%z zCJT1*?Tu&XoUtI*VfhwjufoTAdrWT0Ma{Xkf@$w(9SMn5xn44g8x$8lRNOs3(qd74 z%Jfi^|ABpl0Vfx(=r4_R5}XqAe#WUcQ*y4{IN&>P(dHEU0JzIP0$qM&RRUiT(A6D4 z%nQUImuKdsz#gq{ny90<(fJCWZu^Z35nV4SU;s zezd&&{rb(l6CZWTX0CB?f8})STDef8DX&0-clIHVq~7&z*EpW3q-AL+#q+qH5nYgJ zvuyS;c?VC{_qW5o8TKyp>l6GXlhoQW^O(vvN!~iABF$+Be%qw2$$KZ^)3U@X{KluV zAFX*U)-Jnh)Sa;?@cZP{{EfZ~ue1iJ=uZv0$-0a&G2qsM8Pleh$E~n?aL_4X)&OEvgYy;j{w*|8v}ZGzaIeJgDh3p?^IJ1ESF zGT)sN8N0h{)!T)llX3-E3@0gAZY}Elo??03He!zw^Q84#%@-FfE%o^CtvPq`Y8$pg zSCYP5__pSq&1TE$)K6i#i}(ygYP2dW90ip;D#MOSo%?9AdF{Q|rrEbr7rkBBULB-& zWUaVTq;82zB2RwC37_z_-gepkxyRe&*4fsU&hx&LH~;#yyxk>lwrQuGF$|3tWc|ma zJAcbQfjiE2pAt&Fd|$~NUsC@#l0&fIso|-E!Q4_hJLh#pHne=1BslE-~E|J=o2m$7s89QqI{qdu7~e5_aE^w!dV5Of5&o z%suLV`NPbzhb#qp21+&!oeN@4YRUY)bbQ9XTUV_eL*D%;cl`0`ioSyG>dU2b`hNdm zU6LCeyZy1r?)PtUHsoIsS3e$8@YTvc?Y=pGep(76YbrMkWyk z+=U3xSO{nYQLrKfSr@hp4Ale7G`pa>;Mo~nD|+@qXboq?mD$kEKo1Cn86TO^gC)S5 Rl?^1%0)!udv@;8c2LR#77DE64 literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index 82d204f134..72581f5513 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -52,7 +52,9 @@ namespace osu.Game.Tests.Skins // Covers player avatar and flag. "Archives/modified-argon-20230305.osk", // Covers key counters - "Archives/modified-argon-pro-20230618.osk" + "Archives/modified-argon-pro-20230618.osk", + // Covers rank display + "Archives/modified-argon-20230806.osk" }; /// From 92bf363ecf499a8a4b6ca9b56b63dd6024c40877 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Sun, 6 Aug 2023 20:43:09 +0800 Subject: [PATCH 18/87] use Drawable Rank --- .../Screens/Play/HUD/DefaultRankDisplay.cs | 40 ++++++++++++++++ .../Screens/Play/HUD/GameplayRankDisplay.cs | 14 ++++++ osu.Game/Screens/Play/HUD/RankDisplay.cs | 46 ------------------- 3 files changed, 54 insertions(+), 46 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs create mode 100644 osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs delete mode 100644 osu.Game/Screens/Play/HUD/RankDisplay.cs diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs new file mode 100644 index 0000000000..a686b6d9fb --- /dev/null +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -0,0 +1,40 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Scoring; +using osuTK; + + +namespace osu.Game.Screens.Play.HUD +{ + public partial class DefaultRankDisplay : GameplayRankDisplay + { + [Resolved] + private ScoreProcessor scoreProcessor { get; set; } = null!; + + private UpdateableRank rank; + + public DefaultRankDisplay() + { + Size = new Vector2(70, 35); + + InternalChildren = new Drawable[] { + rank = new UpdateableRank(Scoring.ScoreRank.X) { + RelativeSizeAxes = Axes.Both + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + rank.Rank = scoreProcessor.Rank.Value; + + scoreProcessor.Rank.BindValueChanged(v => rank.Rank = v.NewValue); + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs b/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs new file mode 100644 index 0000000000..402a733abd --- /dev/null +++ b/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; +using osu.Framework.Graphics.Containers; + + +namespace osu.Game.Screens.Play.HUD +{ + public abstract partial class GameplayRankDisplay : Container, ISerialisableDrawable + { + public bool UsesFixedAnchor { get; set; } + } +} diff --git a/osu.Game/Screens/Play/HUD/RankDisplay.cs b/osu.Game/Screens/Play/HUD/RankDisplay.cs deleted file mode 100644 index be8841b647..0000000000 --- a/osu.Game/Screens/Play/HUD/RankDisplay.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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.Allocation; -using osu.Game.Rulesets.Scoring; -using osu.Game.Skinning; -using osu.Framework.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Extensions; - -namespace osu.Game.Screens.Play.HUD -{ - public partial class RankDisplay : FontAdjustableSkinComponent - { - [Resolved] - private ScoreProcessor scoreProcessor { get; set; } = null!; - - private readonly OsuSpriteText text; - - public RankDisplay() - { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - text = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - text.Text = scoreProcessor.Rank.Value.GetDescription(); - - scoreProcessor.Rank.BindValueChanged(v => text.Text = v.NewValue.GetDescription()); - } - - protected override void SetFont(FontUsage font) => text.Font = font.With(size: 40); - } -} From f3f7d1ba7c97ae6ca35092df6987fbed0b17b70a Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Mon, 7 Aug 2023 09:50:24 +0800 Subject: [PATCH 19/87] remove measly abstract --- osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs | 7 +++++-- osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs | 14 -------------- 2 files changed, 5 insertions(+), 16 deletions(-) delete mode 100644 osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs index a686b6d9fb..433acf678a 100644 --- a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -3,19 +3,22 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; using osuTK; namespace osu.Game.Screens.Play.HUD { - public partial class DefaultRankDisplay : GameplayRankDisplay + public partial class DefaultRankDisplay : Container, ISerialisableDrawable { [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; + public bool UsesFixedAnchor { get; set; } - private UpdateableRank rank; + private readonly UpdateableRank rank; public DefaultRankDisplay() { diff --git a/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs b/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs deleted file mode 100644 index 402a733abd..0000000000 --- a/osu.Game/Screens/Play/HUD/GameplayRankDisplay.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Skinning; -using osu.Framework.Graphics.Containers; - - -namespace osu.Game.Screens.Play.HUD -{ - public abstract partial class GameplayRankDisplay : Container, ISerialisableDrawable - { - public bool UsesFixedAnchor { get; set; } - } -} From eb3d3b51e204fef93fdd80e59218e8fb261ae275 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Mon, 7 Aug 2023 09:50:44 +0800 Subject: [PATCH 20/87] add legacy rank display --- osu.Game/Skinning/LegacyRankDisplay.cs | 47 ++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 osu.Game/Skinning/LegacyRankDisplay.cs diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs new file mode 100644 index 0000000000..0ae3b45107 --- /dev/null +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -0,0 +1,47 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Skinning +{ + public partial class LegacyRankDisplay : CompositeDrawable, ISerialisableDrawable + { + public bool UsesFixedAnchor { get; set; } + + [Resolved] + private ScoreProcessor scoreProcessor { get; set; } = null!; + + [Resolved] + private ISkinSource source { get; set; } = null!; + + private readonly Sprite rank; + + public LegacyRankDisplay() + { + AutoSizeAxes = Axes.Both; + + AddInternal(rank = new Sprite()); + } + + protected override void LoadComplete() + { + + var skin = source.FindProvider(s => getTexture(s, "A") != null); + + rank.Texture = getTexture(skin, scoreProcessor.Rank.Value.ToString()); + + scoreProcessor.Rank.BindValueChanged(v => rank.Texture = getTexture(skin, v.NewValue.ToString())); + } + + private static Texture getTexture(ISkin skin, string name) => skin?.GetTexture($"ranking-{name}"); + } +} \ No newline at end of file From 9bdff29dd72c24b7b48292d7f7312363a16a1e2e Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Mon, 7 Aug 2023 09:50:54 +0800 Subject: [PATCH 21/87] add visual test --- .../Gameplay/TestSceneSkinnableRankDisplay.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs new file mode 100644 index 0000000000..dc8b3d994b --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs @@ -0,0 +1,37 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play.HUD; +using osu.Game.Skinning; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public partial class TestSceneSkinnableRankDisplay : SkinnableHUDComponentTestScene + { + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + + protected override Drawable CreateDefaultImplementation() => new DefaultRankDisplay(); + + protected override Drawable CreateLegacyImplementation() => new LegacyRankDisplay(); + + [Test] + public void TestChangingRank() + { + AddStep("Set rank to SS Hidden", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.XH); + AddStep("Set rank to SS", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.X); + AddStep("Set rank to S Hidden", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.SH); + AddStep("Set rank to S", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.S); + AddStep("Set rank to A", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.A); + AddStep("Set rank to B", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.B); + AddStep("Set rank to C", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.C); + AddStep("Set rank to D", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.D); + AddStep("Set rank to F", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.F); + } + } +} \ No newline at end of file From bd67e933105435ee161d8b639cd7221fec88e003 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Mon, 7 Aug 2023 11:16:51 +0800 Subject: [PATCH 22/87] fix code format --- osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs | 10 ++++++---- osu.Game/Skinning/LegacyRankDisplay.cs | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs index 433acf678a..09ab7d156c 100644 --- a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -9,13 +9,13 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osuTK; - namespace osu.Game.Screens.Play.HUD { public partial class DefaultRankDisplay : Container, ISerialisableDrawable { [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; + public bool UsesFixedAnchor { get; set; } private readonly UpdateableRank rank; @@ -24,11 +24,13 @@ namespace osu.Game.Screens.Play.HUD { Size = new Vector2(70, 35); - InternalChildren = new Drawable[] { - rank = new UpdateableRank(Scoring.ScoreRank.X) { + InternalChildren = new Drawable[] + { + rank = new UpdateableRank(Scoring.ScoreRank.X) + { RelativeSizeAxes = Axes.Both }, - }; + }; } protected override void LoadComplete() diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 0ae3b45107..83d4299360 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Scoring; namespace osu.Game.Skinning @@ -34,7 +33,6 @@ namespace osu.Game.Skinning protected override void LoadComplete() { - var skin = source.FindProvider(s => getTexture(s, "A") != null); rank.Texture = getTexture(skin, scoreProcessor.Rank.Value.ToString()); From 07b4f6115b8d35fbb9a03a6399846e5bbeef9db9 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Mon, 7 Aug 2023 20:26:32 +0800 Subject: [PATCH 23/87] use small --- osu.Game/Skinning/LegacyRankDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 83d4299360..cd121deb8c 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -40,6 +40,6 @@ namespace osu.Game.Skinning scoreProcessor.Rank.BindValueChanged(v => rank.Texture = getTexture(skin, v.NewValue.ToString())); } - private static Texture getTexture(ISkin skin, string name) => skin?.GetTexture($"ranking-{name}"); + private static Texture getTexture(ISkin skin, string name) => skin?.GetTexture($"ranking-{name}-small"); } } \ No newline at end of file From fed338a42b12a248b902f2ea1389f06fcec0ec70 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Wed, 9 Aug 2023 07:34:30 +0800 Subject: [PATCH 24/87] improve code --- osu.Game/Skinning/LegacyRankDisplay.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index cd121deb8c..b663f52097 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -33,13 +31,7 @@ namespace osu.Game.Skinning protected override void LoadComplete() { - var skin = source.FindProvider(s => getTexture(s, "A") != null); - - rank.Texture = getTexture(skin, scoreProcessor.Rank.Value.ToString()); - - scoreProcessor.Rank.BindValueChanged(v => rank.Texture = getTexture(skin, v.NewValue.ToString())); + scoreProcessor.Rank.BindValueChanged(v => rank.Texture = source.GetTexture($"ranking-{v.NewValue}-small"), true); } - - private static Texture getTexture(ISkin skin, string name) => skin?.GetTexture($"ranking-{name}-small"); } } \ No newline at end of file From 94613b42e4622a80d724f0e2d700f68f2986c7d9 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Wed, 9 Aug 2023 08:33:50 +0800 Subject: [PATCH 25/87] update tests --- .../Archives/modified-classic-20230809.osk | Bin 0 -> 1603 bytes .../Archives/modified-default-20230809.osk | Bin 0 -> 2141 bytes osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 6 ++++-- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Resources/Archives/modified-classic-20230809.osk create mode 100644 osu.Game.Tests/Resources/Archives/modified-default-20230809.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-classic-20230809.osk b/osu.Game.Tests/Resources/Archives/modified-classic-20230809.osk new file mode 100644 index 0000000000000000000000000000000000000000..b200ab126188d5d056f8d0b11ba37ef9fbc715cf GIT binary patch literal 1603 zcmWIWW@Zs#U|`^2xZ}VX-n-?LnWvYTmwC3|n(vT-fJ^oKq!&#r zDodP7LP|mc6uVUKHMH*S&T$t^U;Mx$rm=s)Bc>^fE30PhjL%Q){5tXCs_(a~Ef)ly z)RDAR4VZ2kP{vzX&lq`H>^HYbDf11zeFfs@q&{<0dz}wrUHe%_MB=G;mZegGn)gh# zwB0EWJ?hfK{FDBPna&F;;_X^+ZEN3KfukiEVzG8vbCQ+SFUIx!yu9#6-Qyq3J+D`- zTODb7_wSqvh5!^FElG=;+y?Z?G9c!K`Y1CmEnhFII6u#{cO%y!0}yzAT>)Sz5C*M&Em(6e<%On^HgA>a-zz4UF-dFCojJbiDOSv zdzYFltCwtZTkfp(MIkfKl==Fo4qn7Dvsn}9P#qxV2jbxTy!7DIoYdqJu#;Cm3knD* z()7~t_c`VH^^EuF@J&H0*t!^9FBgBBEL7a^=S9Q<2igBCI$uzK?Vjf zpsBuznRy}_J{A+TOZ!HTI`PLNh zWQqH$t6L|&J)m{uzn%J&N!t>IS8NeI7=KlPsPWM!U+}m@oe5)HgK+ z?{v~GHl6M%`dt%fZ(Y1++uXD34n|o8O@F~Xmr2TRhJcUA3u_UR`Cp%!Oshrnpf*&+qITO+5 zI;;3kKdaUuHM8miVi#(gpNB|UJ&&wfYkWqt-K?xxoZX z(K^rN|FqNJZ$F80D%ZarIB)u@b(`*Li~Z8z5@8)i2 z7pF-r2lYy;m&r8CYERc@Sa|V3n5dPdy_@=(njo)L@(I-|+~ikAIepvvsp^TY>6bfZ zyc>UK@y?d~qvy`*<2YlAG2=?f%{59ntdaW@RBy%!%|`z5bNl*8=kyv14`%R_t}mfkw^%Ji_e-JG-o^K+#0zOBCfAtoc3_x|!L zIkhZ@^BM|-e%z~4?=;~0YtVI=w{()g(YiS*_o5c;RIEF?pW*oLyFtIcKD+B1e$dcM zNk-*$`m}l7HTK_P=5LXYja!%d)qIoGv4c@-cDDX`-m_(H+T`%7TQA+7CiBJgtgh?R zrg>i_FIS20dCODbbu{I+aKicGS<#V@p76axIMkWyk+yx-e zSO{nYQLy3=T^D*G1J%R8(0B=|3tr@)YemoQ2(8V)G8irMqiaUb)da3BBx literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Resources/Archives/modified-default-20230809.osk b/osu.Game.Tests/Resources/Archives/modified-default-20230809.osk new file mode 100644 index 0000000000000000000000000000000000000000..a46c20d2b83309aeadcc6a563d504a7db203258b GIT binary patch literal 2141 zcmZ`)2{ha37XMpft$mrG)U+6}L^8EaJ6ijiR>V3zc#XBOB-TMtl13E?+Nz?KVv3ep zYfx&NDiV8JS`td_<)LberIYscy&m3s-*@i$&UerG-Shpvdw=&LtvEQv0RZ3u)bx2B zX*@;jL#$f?=!*vcf_*VqCq)X7Xj4jkBIfpkn`LHK&5qG64&<6xQ57e;|UG1b_;1UR{^{9)8^NC!S zPJUFf(IFY63y+zjuXx$lp^8?iXVY^jJCF0)r`C^ye5#aWBR)LKsqg-XE30qM4n5$K zbafv;H@?k`Iei|!t`}L^rx#tjDTqA8+b<>FGM&X&j12$;zVXIjy>L*UU>r6lrHZc| zCT_BIwd1rczrXoOx4_U;D0ERlmi+>)aG75LA~@CJJ3w}!L$~OYx!zo@eR%C9poi(n z5fM;=$slXU=lRF$WtGQ9Cfa-BpCR&5h7cRtQx`PKyq22wX20!ELuxdQ8qS<23l4Wo z=ty^;n;+AezE%`_=Kh20_}$a*i&GR^$mS%?Ro`mz1zt>R^@z-20yfie+)Q==AV>j# zB#XcWGzM#KZ)}9~55QqPu_3`@6+!lCIeqqJ^^$Nny}t6!?T1j_Ha zQ1Q@l#Pm-NyBnXQFIr$Mi33ley_}0iGZQW=eFuz&u;z)Hvi)3zI*+b*{3nw3g@&KC z9m|5j6?)1ve(+W8{Gob%M+@BDjD#=|Ua?$NobUKHq%sR{C&?|gW&D8%>+n;4dU8hE zgLdgrU0I&Igv6e3VMnoNC?!Z`GS%pjB3ivPPf&`|(zfS}Ae{J^R<%E@LTpCb$?#jR z&2Hzg`Hh(RldHy5EN4xp!gbRlrOBK5VvJV-`L2BPhm1=4ljg)+@L>F-TF(3QS zfR3s&^$BH<^92f)m6L5PrXm?K@fvxCctFjp?Qd3L|2t27iu=aZdfoE+!4t zWed|OH|#Vn{}GqzE#tV>bRFBbUJ;VkdaOPfJR`ioODU#{rw<0_fn@lVP*MU3WNb-+ z5w#?D?(Lw;Odo;{juB~Kvk)yoB~cuC2gzNKF7t(*sh%Y*S<~yS4%J%ddm|)mY~p-YaGuIvQ-E8WS^r3_wM2P} zbAMn?B8QNkOeCRE5hXkAJ`$=|@oTf1;ypUt_lg+L0ahA`Jd4ldh4Y7rjb}CGjfiD`^ zi<=~`Vi=jz8BrMSi&3=cs?^`FQTB#|cFW zwXhvl%NdvU*&3GAQ@8*?h@}==9M;>`)6dgAxFS-@y38-Ohkwo!reSa`>3zayfT!p+JVZ@F0?qW;^)sKl7jwckvTRQHoe8^lU~8YGmLbvA9RV?7f?_VU`W8EBa2s3#!GwB{-5RuD z@wID%49OEN#34kYMeJC=nJtZC4->geDWIF3z8CBeb*hwy(HTEYhS(fv24)9oT|k?j6kWDo%m}X> zxT)-bYOs&jTP=388h#~MBZtp7h(Y_-k1zj*EYH^vBnL7^QZ@z~$IqU;dcR-)x4==+ z@y)Zngc0nD;*6xvN*gs!yvRl~JaHj$%@;(OE}bYe+xskC1n+{x4}oyAVnmB z^LoF36Mivp-gSG`=qmNO`7KTAkggn9s?Kh6E&j#Yk{RXWqo{KG(HODUg-ngZ`8|He z4X?z?D}-f&EJOOCBfK!4ejZ=bTRMwEB7-27YSsv<#YT@6&9NF)!j;HovYuo`$ewqS zuShSI1dvv2?Bc-xAC0WA|5}7E$G->VQPk1F@(sgk)Z5=s{~0q!p+{T#cW48vbpLmQ tKN{m`p?{At$N67ne-wQ57r%o$S-Ls=r${Rh%Lf1;)`qg4C&m5c_BT%1iFW`1 literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index 72581f5513..7fa10559dc 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -53,8 +53,10 @@ namespace osu.Game.Tests.Skins "Archives/modified-argon-20230305.osk", // Covers key counters "Archives/modified-argon-pro-20230618.osk", - // Covers rank display - "Archives/modified-argon-20230806.osk" + // Covers default rank display + "Archives/modified-default-20230809.osk", + // Covers legacy rank display + "Archives/modified-classic-20230809.osk" }; /// From 2c3d5dc21a31b4d65d618fbe8dedf714135f32a2 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Wed, 9 Aug 2023 08:44:01 +0800 Subject: [PATCH 26/87] remove unnecesary directive --- osu.Game/Skinning/LegacyRankDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index b663f52097..38ece4e5e4 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Scoring; namespace osu.Game.Skinning From 56eaf48892e23dbb5245cbe78e742be3e0faedd1 Mon Sep 17 00:00:00 2001 From: nanashi-1 Date: Wed, 9 Aug 2023 11:29:52 +0800 Subject: [PATCH 27/87] remove unnecessary archive --- .../Archives/modified-argon-20230806.osk | Bin 1354 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk b/osu.Game.Tests/Resources/Archives/modified-argon-20230806.osk deleted file mode 100644 index e7c035811d62df429b930fd41548457307cbf90a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1354 zcmWIWW@Zs#U|`^2_)x_b{xqpXate^Q9xTGZP@J8ar42}OmnuF-Rk~{%W2L3)BpF`hq7LuxG?;EX_=A3@+2KLW50%z zCJT1*?Tu&XoUtI*VfhwjufoTAdrWT0Ma{Xkf@$w(9SMn5xn44g8x$8lRNOs3(qd74 z%Jfi^|ABpl0Vfx(=r4_R5}XqAe#WUcQ*y4{IN&>P(dHEU0JzIP0$qM&RRUiT(A6D4 z%nQUImuKdsz#gq{ny90<(fJCWZu^Z35nV4SU;s zezd&&{rb(l6CZWTX0CB?f8})STDef8DX&0-clIHVq~7&z*EpW3q-AL+#q+qH5nYgJ zvuyS;c?VC{_qW5o8TKyp>l6GXlhoQW^O(vvN!~iABF$+Be%qw2$$KZ^)3U@X{KluV zAFX*U)-Jnh)Sa;?@cZP{{EfZ~ue1iJ=uZv0$-0a&G2qsM8Pleh$E~n?aL_4X)&OEvgYy;j{w*|8v}ZGzaIeJgDh3p?^IJ1ESF zGT)sN8N0h{)!T)llX3-E3@0gAZY}Elo??03He!zw^Q84#%@-FfE%o^CtvPq`Y8$pg zSCYP5__pSq&1TE$)K6i#i}(ygYP2dW90ip;D#MOSo%?9AdF{Q|rrEbr7rkBBULB-& zWUaVTq;82zB2RwC37_z_-gepkxyRe&*4fsU&hx&LH~;#yyxk>lwrQuGF$|3tWc|ma zJAcbQfjiE2pAt&Fd|$~NUsC@#l0&fIso|-E!Q4_hJLh#pHne=1BslE-~E|J=o2m$7s89QqI{qdu7~e5_aE^w!dV5Of5&o z%suLV`NPbzhb#qp21+&!oeN@4YRUY)bbQ9XTUV_eL*D%;cl`0`ioSyG>dU2b`hNdm zU6LCeyZy1r?)PtUHsoIsS3e$8@YTvc?Y=pGep(76YbrMkWyk z+=U3xSO{nYQLrKfSr@hp4Ale7G`pa>;Mo~nD|+@qXboq?mD$kEKo1Cn86TO^gC)S5 Rl?^1%0)!udv@;8c2LR#77DE64 From 6ed1685223bcf1c2811a04233b7e70631048a85c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 11:07:49 -0700 Subject: [PATCH 28/87] Fix/update score exporting method --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 093037e6d1..8930ee9914 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -14,8 +14,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; -using osu.Framework.Platform; -using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -62,7 +60,7 @@ namespace osu.Game.Online.Leaderboards private IDialogOverlay? dialogOverlay { get; set; } [Resolved] - private Storage storage { get; set; } = null!; + private ScoreManager scoreManager { get; set; } = null!; private Container content = null!; private Box background = null!; @@ -92,7 +90,7 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load(ScoreManager scoreManager) + private void load() { var user = score.User; @@ -138,7 +136,7 @@ namespace osu.Game.Online.Leaderboards Width = 35 }, createCentreContent(user), - createRightSideContent(scoreManager) + createRightSideContent() } } } @@ -230,7 +228,7 @@ namespace osu.Game.Online.Leaderboards } }; - private FillFlowContainer createRightSideContent(ScoreManager scoreManager) => + private FillFlowContainer createRightSideContent() => new FillFlowContainer { Padding = new MarginPadding { Left = 11, Right = 15 }, @@ -482,7 +480,7 @@ namespace osu.Game.Online.Leaderboards if (score.Files.Count <= 0) return items.ToArray(); - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage).Export(score))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(score))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(score)))); return items.ToArray(); From 9f9f7eb01bc682b9c74b5b0a6014cd61c5c9a339 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 11:15:46 -0700 Subject: [PATCH 29/87] Nuke hit results display --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 8930ee9914..18945e373f 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -23,7 +23,6 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Select; @@ -289,7 +288,6 @@ namespace osu.Game.Online.Leaderboards { (BeatmapsetsStrings.ShowScoreboardHeadersCombo.ToUpper(), model.MaxCombo.ToString().Insert(model.MaxCombo.ToString().Length, "x")), (BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper(), model.DisplayAccuracy), - (getResultNames(score).ToUpper(), getResults(score).ToUpper()) }; public override void Show() @@ -486,25 +484,5 @@ namespace osu.Game.Online.Leaderboards return items.ToArray(); } } - - private LocalisableString getResults(ScoreInfo score) - { - string resultString = score.GetStatisticsForDisplay() - .Where(s => s.Result.IsBasic()) - .Aggregate(string.Empty, (current, result) => - current.Insert(current.Length, $"{result.Count}/")); - - return resultString.Remove(resultString.Length - 1); - } - - private LocalisableString getResultNames(ScoreInfo score) - { - string resultName = score.GetStatisticsForDisplay() - .Where(s => s.Result.IsBasic()) - .Aggregate(string.Empty, (current, hitResult) => - current.Insert(current.Length, $"{hitResult.DisplayName.ToString().ToUpperInvariant()}/")); - - return resultName.Remove(resultName.Length - 1); - } } } From 228731493eb0f519a80216ac156be83f887275dd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 15:39:40 -0700 Subject: [PATCH 30/87] Add relative width slider to test --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 0823da2248..1ea461be53 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -18,6 +18,8 @@ namespace osu.Game.Tests.Visual.SongSelect { public partial class TestSceneLeaderboardScoreV2 : OsuTestScene { + private FillFlowContainer fillFlow = null!; + [BackgroundDependencyLoader] private void load() { @@ -73,12 +75,12 @@ namespace osu.Game.Tests.Visual.SongSelect }, }; - Child = new FillFlowContainer + Child = fillFlow = new FillFlowContainer { - Width = 900, Anchor = Anchor.Centre, Origin = Anchor.Centre, Spacing = new Vector2(0, 10), + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Children = new Drawable[] { @@ -87,6 +89,11 @@ namespace osu.Game.Tests.Visual.SongSelect new LeaderboardScoreV2(scores[2], null, true) } }; + + AddSliderStep("change relative width", 0, 1f, 0.6f, v => + { + fillFlow.Width = v; + }); } } } From 2bd28e67186995d28c8ad9d2c7260706986f9c3c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 16:21:53 -0700 Subject: [PATCH 31/87] Move drawable init properties to constructor --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 18945e373f..362eb9ea82 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -86,6 +86,10 @@ namespace osu.Game.Online.Leaderboards this.score = score; this.rank = rank; this.isPersonalBest = isPersonalBest; + + Shear = shear; + RelativeSizeAxes = Axes.X; + Height = height; } [BackgroundDependencyLoader] @@ -98,9 +102,6 @@ namespace osu.Game.Online.Leaderboards statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)).ToList(); - Shear = shear; - RelativeSizeAxes = Axes.X; - Height = height; Child = content = new Container { Masking = true, From f7f390195a7744e2b2ee024a7d970c80e9cf6421 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 16:34:06 -0700 Subject: [PATCH 32/87] Add user covers to centre content --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 8 +++++--- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 1ea461be53..2a6203f2d8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -39,6 +39,7 @@ namespace osu.Game.Tests.Visual.SongSelect Id = 6602580, Username = @"waaiiru", CountryCode = CountryCode.ES, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", }, }, new ScoreInfo @@ -55,6 +56,7 @@ namespace osu.Game.Tests.Visual.SongSelect Id = 1541390, Username = @"Toukai", CountryCode = CountryCode.CA, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", }, }, @@ -68,8 +70,7 @@ namespace osu.Game.Tests.Visual.SongSelect Ruleset = new ManiaRuleset().RulesetInfo, User = new APIUser { - Id = 4608074, - Username = @"Skycries", + Username = @"No cover", CountryCode = CountryCode.BR, }, }, @@ -86,7 +87,8 @@ namespace osu.Game.Tests.Visual.SongSelect { new LeaderboardScoreV2(scores[0], 1), new LeaderboardScoreV2(scores[1], null, true), - new LeaderboardScoreV2(scores[2], null, true) + new LeaderboardScoreV2(scores[2], null, true), + new LeaderboardScoreV2(scores[2], null), } }; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 362eb9ea82..22efe3b88c 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; @@ -26,6 +27,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Select; +using osu.Game.Users; using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; @@ -164,6 +166,12 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, Colour = foregroundColour }, + new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + User = score.User, + Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), + }, avatar = new MaskedWrapper( innerAvatar = new ClickableAvatar(user) { From 236352a1760fae7ff9e2aed4fa29836edbc32cc2 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 17:00:51 -0700 Subject: [PATCH 33/87] Add shadow to centre content Done this way instead of edge effect because of 1px/dimming issues. --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 141 ++++++++++-------- 1 file changed, 80 insertions(+), 61 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 22efe3b88c..89ad39c98c 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -48,6 +48,7 @@ namespace osu.Game.Online.Leaderboards private Colour4 foregroundColour; private Colour4 backgroundColour; + private Colour4 shadowColour; private static readonly Vector2 shear = new Vector2(0.15f, 0); @@ -101,6 +102,7 @@ namespace osu.Game.Online.Leaderboards foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; + shadowColour = isPersonalBest ? colourProvider.Background3 : colourProvider.Background6; statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)).ToList(); @@ -154,86 +156,103 @@ namespace osu.Game.Online.Leaderboards private Container createCentreContent(APIUser user) => new Container { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, Masking = true, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { - foreground = new Box + new Box { RelativeSizeAxes = Axes.Both, - Colour = foregroundColour + Colour = shadowColour, }, - new UserCoverBackground + new Container { RelativeSizeAxes = Axes.Both, - User = score.User, - Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), - }, - avatar = new MaskedWrapper( - innerAvatar = new ClickableAvatar(user) + Padding = new MarginPadding { Right = 5 }, + Child = new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, + Masking = true, + CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, - }) - { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) - }, - new FillFlowContainer - { - Position = new Vector2(height + 9, 9), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - flagBadgeAndDateContainer = new FillFlowContainer + Children = new[] { - Shear = -shear, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - Size = new Vector2(87, 16), - Masking = true, - Children = new Drawable[] + foreground = new Box { - new UpdateableFlag(user.CountryCode) + RelativeSizeAxes = Axes.Both, + Colour = foregroundColour + }, + new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + User = score.User, + Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), + }, + avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(24, 16), - }, - new DateLabel(score.Date) + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, + new FillFlowContainer + { + Position = new Vector2(height + 9, 9), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + flagBadgeAndDateContainer = new FillFlowContainer + { + Shear = -shear, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + Size = new Vector2(87, 16), + Masking = true, + Children = new Drawable[] + { + new UpdateableFlag(user.CountryCode) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(24, 16), + }, + new DateLabel(score.Date) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + } + }, + nameLabel = new OsuSpriteText + { + Shear = -shear, + Text = user.Username, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) + } } + }, + new FillFlowContainer + { + Margin = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25, 0), + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels } - }, - nameLabel = new OsuSpriteText - { - Shear = -shear, - Text = user.Username, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) } - } + }, }, - new FillFlowContainer - { - Margin = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25, 0), - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = statisticsLabels - } - } + }, }; private FillFlowContainer createRightSideContent() => From 5bea5415be1cdc1aec3f6a5dd6fc2b6d38a4dc78 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 19:55:00 -0700 Subject: [PATCH 34/87] Remove weird yellow background override on mods To who's reading, don't follow figma designs all the time. In most cases, follow what other places are doing. --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 89ad39c98c..f67f7c05a2 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -466,13 +466,11 @@ namespace osu.Game.Online.Leaderboards { private readonly IMod mod; - [Resolved] - private OsuColour colours { get; set; } = null!; - public ColouredModSwitchTiny(IMod mod) : base(mod) { this.mod = mod; + Active.Value = true; Masking = true; EdgeEffect = new EdgeEffectParameters { @@ -484,12 +482,6 @@ namespace osu.Game.Online.Leaderboards }; } - protected override void UpdateState() - { - AcronymText.Colour = Colour4.FromHex("#555555"); - Background.Colour = colours.Yellow; - } - public LocalisableString TooltipText => (mod as Mod)?.IconTooltip ?? mod.Name; } From c0b8b3509f9507592e6ecc06e408c54710a0f64b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 22 Sep 2023 19:56:33 -0700 Subject: [PATCH 35/87] Populate dates and add show animation on test --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 2a6203f2d8..1663116e12 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.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; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -41,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect CountryCode = CountryCode.ES, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", }, + Date = DateTimeOffset.Now.AddYears(-2), }, new ScoreInfo { @@ -58,6 +60,7 @@ namespace osu.Game.Tests.Visual.SongSelect CountryCode = CountryCode.CA, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", }, + Date = DateTimeOffset.Now.AddMonths(-6), }, new ScoreInfo @@ -73,6 +76,7 @@ namespace osu.Game.Tests.Visual.SongSelect Username = @"No cover", CountryCode = CountryCode.BR, }, + Date = DateTimeOffset.Now, }, }; @@ -92,6 +96,9 @@ namespace osu.Game.Tests.Visual.SongSelect } }; + foreach (var score in fillFlow.Children) + score.Show(); + AddSliderStep("change relative width", 0, 1f, 0.6f, v => { fillFlow.Width = v; From dad03778b7aaa05a5250d7ca014e4d3203f0c092 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 23 Sep 2023 19:40:57 -0700 Subject: [PATCH 36/87] Fix leaderboard score caching colour provider --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 4 ++++ osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 1663116e12..200faa33ec 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Overlays; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -19,6 +20,9 @@ namespace osu.Game.Tests.Visual.SongSelect { public partial class TestSceneLeaderboardScoreV2 : OsuTestScene { + [Cached] + private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + private FillFlowContainer fillFlow = null!; [BackgroundDependencyLoader] diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index f67f7c05a2..bcb0796ffd 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -52,8 +52,8 @@ namespace osu.Game.Online.Leaderboards private static readonly Vector2 shear = new Vector2(0.15f, 0); - [Cached] - private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; [Resolved] private SongSelect? songSelect { get; set; } From 668e083ddc6292df0ebf4df775dd7860d42461c4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 26 Sep 2023 12:05:54 -0700 Subject: [PATCH 37/87] Use `AutoSizeAxes` instead of hardcoded `Size` --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index bcb0796ffd..0039cce532 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -213,7 +213,7 @@ namespace osu.Game.Online.Leaderboards Shear = -shear, Direction = FillDirection.Horizontal, Spacing = new Vector2(5f, 0f), - Size = new Vector2(87, 16), + AutoSizeAxes = Axes.Both, Masking = true, Children = new Drawable[] { From 39b008b070e83900dcc54042f5b76a47f11eb754 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 14:58:22 -0700 Subject: [PATCH 38/87] Move test scores to a method and add `TestResources.CreateTestScoreInfo()` --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 200faa33ec..fed5519887 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; +using osu.Game.Tests.Resources; using osu.Game.Users; using osuTK; @@ -27,6 +28,29 @@ namespace osu.Game.Tests.Visual.SongSelect [BackgroundDependencyLoader] private void load() + { + Child = fillFlow = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(0, 10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + + foreach (var scoreInfo in getTestScores()) + fillFlow.Add(new LeaderboardScoreV2(scoreInfo, scoreInfo.Position, scoreInfo.User.Id == 2)); + + foreach (var score in fillFlow.Children) + score.Show(); + + AddSliderStep("change relative width", 0, 1f, 0.6f, v => + { + fillFlow.Width = v; + }); + } + + private static ScoreInfo[] getTestScores() { var scores = new[] { @@ -66,7 +90,6 @@ namespace osu.Game.Tests.Visual.SongSelect }, Date = DateTimeOffset.Now.AddMonths(-6), }, - new ScoreInfo { Position = 110000, @@ -82,31 +105,10 @@ namespace osu.Game.Tests.Visual.SongSelect }, Date = DateTimeOffset.Now, }, + TestResources.CreateTestScoreInfo(), }; - Child = fillFlow = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Spacing = new Vector2(0, 10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new LeaderboardScoreV2(scores[0], 1), - new LeaderboardScoreV2(scores[1], null, true), - new LeaderboardScoreV2(scores[2], null, true), - new LeaderboardScoreV2(scores[2], null), - } - }; - - foreach (var score in fillFlow.Children) - score.Show(); - - AddSliderStep("change relative width", 0, 1f, 0.6f, v => - { - fillFlow.Width = v; - }); + return scores; } } } From 43c8d51d02a4b504d6019cb077dab94107e8dd19 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 15:05:34 -0700 Subject: [PATCH 39/87] Add draw width statistic to test --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index fed5519887..bc254f25de 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; @@ -25,17 +26,22 @@ namespace osu.Game.Tests.Visual.SongSelect private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); private FillFlowContainer fillFlow = null!; + private OsuSpriteText drawWidthText = null!; [BackgroundDependencyLoader] private void load() { - Child = fillFlow = new FillFlowContainer + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Spacing = new Vector2(0, 10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + fillFlow = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(0, 10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + drawWidthText = new OsuSpriteText(), }; foreach (var scoreInfo in getTestScores()) @@ -50,6 +56,13 @@ namespace osu.Game.Tests.Visual.SongSelect }); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + drawWidthText.Text = $"DrawWidth: {fillFlow.DrawWidth}"; + } + private static ScoreInfo[] getTestScores() { var scores = new[] From 6087c12d85214ba3f6e25d3cf38316753a7f2144 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 17:53:37 -0700 Subject: [PATCH 40/87] Use grid container for centre content --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 120 ++++++++++-------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 0039cce532..c92549e9c5 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -175,7 +175,7 @@ namespace osu.Game.Online.Leaderboards Masking = true, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { foreground = new Box { @@ -188,66 +188,82 @@ namespace osu.Game.Online.Leaderboards User = score.User, Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), }, - avatar = new MaskedWrapper( - innerAvatar = new ClickableAvatar(user) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, - RelativeSizeAxes = Axes.Both, - }) + new GridContainer { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) - }, - new FillFlowContainer - { - Position = new Vector2(height + 9, 9), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - flagBadgeAndDateContainer = new FillFlowContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new[] { - Shear = -shear, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - AutoSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] + avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) { - new UpdateableFlag(user.CountryCode) + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, + new FillFlowContainer + { + Position = new Vector2(9), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(24, 16), - }, - new DateLabel(score.Date) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + flagBadgeAndDateContainer = new FillFlowContainer + { + Shear = -shear, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + AutoSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new UpdateableFlag(user.CountryCode) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(24, 16), + }, + new DateLabel(score.Date) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + } + }, + nameLabel = new OsuSpriteText + { + Shear = -shear, + Text = user.Username, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) + } } + }, + new FillFlowContainer + { + Margin = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25, 0), + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels } - }, - nameLabel = new OsuSpriteText - { - Shear = -shear, - Text = user.Username, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) } } - }, - new FillFlowContainer - { - Margin = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25, 0), - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = statisticsLabels } } }, From bb3f426b935cd67e1cefa0bcb5f984545b0156ff Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 18:02:59 -0700 Subject: [PATCH 41/87] Truncate name label and clean up positioning code Also adds a test score with a long username. --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 16 ++++++++++++++++ .../Online/Leaderboards/LeaderboardScoreV2.cs | 14 +++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index bc254f25de..1b1ece3eff 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -118,6 +118,22 @@ namespace osu.Game.Tests.Visual.SongSelect }, Date = DateTimeOffset.Now, }, + new ScoreInfo + { + Position = 110000, + Rank = ScoreRank.A, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Ruleset = new ManiaRuleset().RulesetInfo, + User = new APIUser + { + Id = 226597, + Username = @"WWWWWWWWWWWWWWWWWWWW", + CountryCode = CountryCode.US, + }, + Date = DateTimeOffset.Now, + }, TestResources.CreateTestScoreInfo(), }; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index c92549e9c5..a6df3bee76 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -216,16 +216,19 @@ namespace osu.Game.Online.Leaderboards }, new FillFlowContainer { - Position = new Vector2(9), - AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = corner_radius }, Children = new Drawable[] { flagBadgeAndDateContainer = new FillFlowContainer { Shear = -shear, Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), + Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, Masking = true, Children = new Drawable[] @@ -243,8 +246,9 @@ namespace osu.Game.Online.Leaderboards } } }, - nameLabel = new OsuSpriteText + nameLabel = new TruncatingSpriteText { + RelativeSizeAxes = Axes.X, Shear = -shear, Text = user.Username, Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) @@ -254,7 +258,7 @@ namespace osu.Game.Online.Leaderboards new FillFlowContainer { Margin = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25, 0), + Spacing = new Vector2(25), Shear = -shear, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, From 837437ac5758807220f963d785b3db816d728f07 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 18:15:05 -0700 Subject: [PATCH 42/87] Rename `createRightSideContent()` to `createRightContent()` --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index a6df3bee76..e364d411e3 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -140,7 +140,7 @@ namespace osu.Game.Online.Leaderboards Width = 35 }, createCentreContent(user), - createRightSideContent() + createRightContent() } } } @@ -275,7 +275,7 @@ namespace osu.Game.Online.Leaderboards }, }; - private FillFlowContainer createRightSideContent() => + private FillFlowContainer createRightContent() => new FillFlowContainer { Padding = new MarginPadding { Left = 11, Right = 15 }, From e0c6c1bc668272e08c7a5ce1b5e4c74acee13761 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 18:20:19 -0700 Subject: [PATCH 43/87] Fix rank label tooltip area --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index e364d411e3..60bac3e713 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -131,14 +131,7 @@ namespace osu.Game.Online.Leaderboards { new Drawable[] { - new RankLabel(rank) - { - Shear = -shear, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 35 - }, + new RankLabel(rank) { Shear = -shear }, createCentreContent(user), createRightContent() } @@ -457,13 +450,15 @@ namespace osu.Game.Online.Leaderboards { public RankLabel(int? rank) { + AutoSizeAxes = Axes.Both; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + if (rank >= 1000) TooltipText = $"#{rank:N0}"; Child = new OsuSpriteText { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true), Text = rank == null ? "-" : rank.Value.FormatRank().Insert(0, "#") }; From 3ad5a7c66190aaf0a80e775bf4761767604d862f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 18:29:18 -0700 Subject: [PATCH 44/87] Reduce indents of private container methods --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 314 +++++++++--------- 1 file changed, 156 insertions(+), 158 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 60bac3e713..c96b860b29 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -146,184 +146,182 @@ namespace osu.Game.Online.Leaderboards modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 }; } - private Container createCentreContent(APIUser user) => - new Container + private Container createCentreContent(APIUser user) => new Container + { + Masking = true, + CornerRadius = corner_radius, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Masking = true, - CornerRadius = corner_radius, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Box { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = shadowColour, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new Container - { - Masking = true, - CornerRadius = corner_radius, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - foreground = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = foregroundColour - }, - new UserCoverBackground - { - RelativeSizeAxes = Axes.Both, - User = score.User, - Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new[] - { - avatar = new MaskedWrapper( - innerAvatar = new ClickableAvatar(user) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, - RelativeSizeAxes = Axes.Both, - }) - { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = corner_radius }, - Children = new Drawable[] - { - flagBadgeAndDateContainer = new FillFlowContainer - { - Shear = -shear, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - new UpdateableFlag(user.CountryCode) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(24, 16), - }, - new DateLabel(score.Date) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - } - } - }, - nameLabel = new TruncatingSpriteText - { - RelativeSizeAxes = Axes.X, - Shear = -shear, - Text = user.Username, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) - } - } - }, - new FillFlowContainer - { - Margin = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25), - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = statisticsLabels - } - } - } - } - } - }, - }, + RelativeSizeAxes = Axes.Both, + Colour = shadowColour, }, - }; - - private FillFlowContainer createRightContent() => - new FillFlowContainer - { - Padding = new MarginPadding { Left = 11, Right = 15 }, - Y = -5, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Vertical, - Spacing = new Vector2(13, 0f), - Children = new Drawable[] + new Container { - new Container + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new Container { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, + Masking = true, + CornerRadius = corner_radius, + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - scoreText = new OsuSpriteText + foreground = new Box { - Shear = -shear, - Current = scoreManager.GetBindableTotalScoreString(score), - - //Does not match figma, adjusted to allow 8 digits to fit comfortably - Font = OsuFont.GetFont(size: 28, weight: FontWeight.SemiBold, fixedWidth: false), + RelativeSizeAxes = Axes.Both, + Colour = foregroundColour }, - RankContainer = new Container + new UserCoverBackground { - BypassAutoSizeAxes = Axes.Both, - Y = 2, - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Children = new[] + RelativeSizeAxes = Axes.Both, + User = score.User, + Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - scoreRank = new UpdateableRank(score.Rank) + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(32) + avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = corner_radius }, + Children = new Drawable[] + { + flagBadgeAndDateContainer = new FillFlowContainer + { + Shear = -shear, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new UpdateableFlag(user.CountryCode) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(24, 16), + }, + new DateLabel(score.Date) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + } + }, + nameLabel = new TruncatingSpriteText + { + RelativeSizeAxes = Axes.X, + Shear = -shear, + Text = user.Username, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) + } + } + }, + new FillFlowContainer + { + Margin = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25), + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels + } } } } } }, - modsContainer = new FillFlowContainer + }, + }, + }; + + private FillFlowContainer createRightContent() => new FillFlowContainer + { + Padding = new MarginPadding { Left = 11, Right = 15 }, + Y = -5, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Vertical, + Spacing = new Vector2(13, 0f), + Children = new Drawable[] + { + new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] { - Shear = -shear, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) + scoreText = new OsuSpriteText + { + Shear = -shear, + Current = scoreManager.GetBindableTotalScoreString(score), + + //Does not match figma, adjusted to allow 8 digits to fit comfortably + Font = OsuFont.GetFont(size: 28, weight: FontWeight.SemiBold, fixedWidth: false), + }, + RankContainer = new Container + { + BypassAutoSizeAxes = Axes.Both, + Y = 2, + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Children = new[] + { + scoreRank = new UpdateableRank(score.Rank) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(32) + } + } + } } + }, + modsContainer = new FillFlowContainer + { + Shear = -shear, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) } - }; + } + }; protected (CaseTransformableString, LocalisableString DisplayAccuracy)[] GetStatistics(ScoreInfo model) => new[] { From 3c1d15d9b7e67bf0f24290873330d5d4dd06f7de Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 18:44:20 -0700 Subject: [PATCH 45/87] Fix user cover having shear --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index c96b860b29..8e3affbe20 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -178,6 +178,9 @@ namespace osu.Game.Online.Leaderboards { RelativeSizeAxes = Axes.Both, User = score.User, + Shear = -shear, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), }, new GridContainer From e049a072f8b5bf708377e80fafc032903ea74817 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 19:17:50 -0700 Subject: [PATCH 46/87] Update right content to latest design - Add more scenarios to test - Future-proof mods display to not overflow --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 23 ++- osu.Game/Graphics/OsuColour.cs | 21 ++ osu.Game/Online/Leaderboards/DrawableRank.cs | 4 +- .../Online/Leaderboards/LeaderboardScoreV2.cs | 181 ++++++++++++++---- 4 files changed, 180 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 1b1ece3eff..f0d07c8526 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -70,11 +71,10 @@ namespace osu.Game.Tests.Visual.SongSelect new ScoreInfo { Position = 999, - Rank = ScoreRank.XH, + Rank = ScoreRank.X, Accuracy = 1, MaxCombo = 244, TotalScore = 1707827, - Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), new OsuModAlternate(), new OsuModFlashlight(), new OsuModFreezeFrame() }, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -91,7 +91,6 @@ namespace osu.Game.Tests.Visual.SongSelect Rank = ScoreRank.S, Accuracy = 0.1f, MaxCombo = 32040, - Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), new OsuModAlternate(), new OsuModFlashlight(), new OsuModFreezeFrame(), new OsuModClassic() }, TotalScore = 1707827, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -106,7 +105,7 @@ namespace osu.Game.Tests.Visual.SongSelect new ScoreInfo { Position = 110000, - Rank = ScoreRank.X, + Rank = ScoreRank.A, Accuracy = 1, MaxCombo = 244, TotalScore = 17078279, @@ -124,7 +123,7 @@ namespace osu.Game.Tests.Visual.SongSelect Rank = ScoreRank.A, Accuracy = 1, MaxCombo = 244, - TotalScore = 1707827, + TotalScore = 1234567890, Ruleset = new ManiaRuleset().RulesetInfo, User = new APIUser { @@ -137,6 +136,20 @@ namespace osu.Game.Tests.Visual.SongSelect TestResources.CreateTestScoreInfo(), }; + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED; i++) + scores[0].Mods = scores[0].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED + 1; i++) + scores[1].Mods = scores[1].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED; i++) + scores[2].Mods = scores[2].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED + 1; i++) + scores[3].Mods = scores[3].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + + scores[4].Mods = scores[4].BeatmapInfo!.Ruleset.CreateInstance().CreateAllMods().ToArray(); + return scores; } } diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 1b21f79c0a..d1b232b26d 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Game.Beatmaps; using osu.Game.Online.Rooms; @@ -68,6 +69,26 @@ namespace osu.Game.Graphics } } + /// + /// Retrieves the colour for the total score depending on . + /// + public static ColourInfo TotalScoreColourFor(ScoreRank rank) + { + switch (rank) + { + case ScoreRank.XH: + case ScoreRank.X: + return ColourInfo.GradientVertical(Colour4.FromHex(@"A4DEFF"), Colour4.FromHex(@"F0AADD")); + + case ScoreRank.SH: + case ScoreRank.S: + return ColourInfo.GradientVertical(Colour4.FromHex(@"FFFFFF"), Colour4.FromHex(@"F7E65D")); + + default: + return Colour4.White; + } + } + /// /// Retrieves the colour for a . /// diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 5177f35478..e4691efc04 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -57,7 +57,7 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.Centre, Spacing = new Vector2(-3, 0), Padding = new MarginPadding { Top = 5 }, - Colour = getRankNameColour(), + Colour = GetRankNameColour(rank), Font = OsuFont.Numeric.With(size: 25), Text = GetRankName(rank), ShadowColour = Color4.Black.Opacity(0.3f), @@ -74,7 +74,7 @@ namespace osu.Game.Online.Leaderboards /// /// Retrieves the grade text colour. /// - private ColourInfo getRankNameColour() + public static ColourInfo GetRankNameColour(ScoreRank rank) { switch (rank) { diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 8e3affbe20..5f15f9dd62 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -17,6 +18,7 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Extensions; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -31,11 +33,25 @@ using osu.Game.Users; using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; +using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { + /// + /// The maximum number of mods when contracted until the mods display width exceeds the . + /// + public const int MAX_MODS_CONTRACTED = 13; + + /// + /// The maximum number of mods when expanded until the mods display width exceeds the . + /// + public const int MAX_MODS_EXPANDED = 4; + + private const float right_content_min_width = 180; + private const float grade_width = 40; + private readonly ScoreInfo score; private const int height = 60; @@ -49,6 +65,7 @@ namespace osu.Game.Online.Leaderboards private Colour4 foregroundColour; private Colour4 backgroundColour; private Colour4 shadowColour; + private ColourInfo totalScoreBackgroundGradient; private static readonly Vector2 shear = new Vector2(0.15f, 0); @@ -77,9 +94,11 @@ namespace osu.Game.Online.Leaderboards protected Container RankContainer { get; private set; } = null!; private FillFlowContainer flagBadgeAndDateContainer = null!; private FillFlowContainer modsContainer = null!; + private OsuSpriteText modsCounter = null!; private OsuSpriteText scoreText = null!; private Drawable scoreRank = null!; + private Box totalScoreBackground = null!; public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => score; @@ -103,6 +122,7 @@ namespace osu.Game.Online.Leaderboards foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; shadowColour = isPersonalBest ? colourProvider.Background3 : colourProvider.Background6; + totalScoreBackgroundGradient = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), backgroundColour); statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)).ToList(); @@ -125,7 +145,7 @@ namespace osu.Game.Online.Leaderboards { new Dimension(GridSizeMode.Absolute, 65), new Dimension(), - new Dimension(GridSizeMode.Absolute, 176) + new Dimension(GridSizeMode.AutoSize, minSize: right_content_min_width), // use min size to account for classic scoring }, Content = new[] { @@ -142,12 +162,13 @@ namespace osu.Game.Online.Leaderboards innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); - modsContainer.Spacing = new Vector2(modsContainer.Children.Count > 5 ? -20 : 2, 0); + modsContainer.Spacing = new Vector2(modsContainer.Children.Count > MAX_MODS_EXPANDED ? -20 : 2, 0); modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 }; } private Container createCentreContent(APIUser user) => new Container { + Name = @"Centre container", Masking = true, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, @@ -270,58 +291,130 @@ namespace osu.Game.Online.Leaderboards }, }; - private FillFlowContainer createRightContent() => new FillFlowContainer + private Container createRightContent() => new Container { - Padding = new MarginPadding { Left = 11, Right = 15 }, - Y = -5, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Vertical, - Spacing = new Vector2(13, 0f), + Name = @"Right content", + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, Children = new Drawable[] { new Container { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = grade_width }, + Child = new Box { - scoreText = new OsuSpriteText + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank)), + }, + }, + new Box + { + RelativeSizeAxes = Axes.Y, + Width = grade_width, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = OsuColour.ForRank(score.Rank), + }, + new TrianglesV2 + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Masking = true, + SpawnRatio = 2, + Velocity = 0.7f, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Darken(0.2f)), + }, + RankContainer = new Container + { + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + Width = grade_width, + Child = scoreRank = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(-2), + Colour = DrawableRank.GetRankNameColour(score.Rank), + Font = OsuFont.Numeric.With(size: 16), + Text = DrawableRank.GetRankName(score.Rank), + ShadowColour = Color4.Black.Opacity(0.3f), + ShadowOffset = new Vector2(0, 0.08f), + Shadow = true, + UseFullGlyphHeight = false, + }, + }, + new Container + { + AutoSizeAxes = Axes.X, + // makeshift inner border + Height = height - 4, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding { Right = grade_width }, + Child = new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + CornerRadius = corner_radius, + Children = new Drawable[] { - Shear = -shear, - Current = scoreManager.GetBindableTotalScoreString(score), - - //Does not match figma, adjusted to allow 8 digits to fit comfortably - Font = OsuFont.GetFont(size: 28, weight: FontWeight.SemiBold, fixedWidth: false), - }, - RankContainer = new Container - { - BypassAutoSizeAxes = Axes.Both, - Y = 2, - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Children = new[] + totalScoreBackground = new Box { - scoreRank = new UpdateableRank(score.Rank) + RelativeSizeAxes = Axes.Both, + Colour = totalScoreBackgroundGradient, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Opacity(0.5f)), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = corner_radius }, + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(32) + scoreText = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + UseFullGlyphHeight = false, + Shear = -shear, + Current = scoreManager.GetBindableTotalScoreString(score), + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), + Colour = OsuColour.TotalScoreColourFor(score.Rank), + }, + modsContainer = new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -shear, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) + }, + modsCounter = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -shear, + Text = $"{score.Mods.Length} mods", + Alpha = 0, + } } } } } - }, - modsContainer = new FillFlowContainer - { - Shear = -shear, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) } } }; @@ -361,7 +454,8 @@ namespace osu.Game.Online.Leaderboards using (BeginDelayedSequence(50)) { - var drawables = new Drawable[] { flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels).ToArray(); + Drawable modsDrawable = score.Mods.Length > MAX_MODS_CONTRACTED ? modsCounter : modsContainer; + var drawables = new[] { flagBadgeAndDateContainer, modsDrawable }.Concat(statisticsLabels).ToArray(); for (int i = 0; i < drawables.Length; i++) drawables[i].FadeIn(100 + i * 50); } @@ -383,8 +477,11 @@ namespace osu.Game.Online.Leaderboards private void updateState() { + var lightenedGradient = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0).Lighten(0.2f), backgroundColour.Lighten(0.2f)); + foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint); background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); + totalScoreBackground.FadeColour(IsHovered ? lightenedGradient : totalScoreBackgroundGradient, transition_duration, Easing.OutQuint); } #region Subclasses From e4f1eab6adc1cac96c5d09436a395ad3976cae6a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 20:24:17 -0700 Subject: [PATCH 47/87] Add experimental collapse content logic based on width --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 5f15f9dd62..c77424902f 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Layout; using osu.Framework.Localisation; using osu.Game.Extensions; using osu.Game.Graphics; @@ -51,6 +52,7 @@ namespace osu.Game.Online.Leaderboards private const float right_content_min_width = 180; private const float grade_width = 40; + private const float username_min_width = 100; private readonly ScoreInfo score; @@ -100,6 +102,10 @@ namespace osu.Game.Online.Leaderboards private Drawable scoreRank = null!; private Box totalScoreBackground = null!; + private Container centreContent = null!; + private FillFlowContainer usernameAndFlagContainer = null!; + private FillFlowContainer statisticsContainer = null!; + public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => score; @@ -152,7 +158,7 @@ namespace osu.Game.Online.Leaderboards new Drawable[] { new RankLabel(rank) { Shear = -shear }, - createCentreContent(user), + centreContent = createCentreContent(user), createRightContent() } } @@ -215,22 +221,26 @@ namespace osu.Game.Online.Leaderboards }, Content = new[] { - new[] + new Drawable[] { - avatar = new MaskedWrapper( - innerAvatar = new ClickableAvatar(user) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, - RelativeSizeAxes = Axes.Both, - }) + new Container { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) + AutoSizeAxes = Axes.Both, + Child = avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, }, - new FillFlowContainer + usernameAndFlagContainer = new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -271,16 +281,22 @@ namespace osu.Game.Online.Leaderboards } } }, - new FillFlowContainer + new Container { - Margin = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25), - Shear = -shear, + AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = statisticsLabels + Child = statisticsContainer = new FillFlowContainer + { + Padding = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25), + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels + } } } } @@ -484,6 +500,42 @@ namespace osu.Game.Online.Leaderboards totalScoreBackground.FadeColour(IsHovered ? lightenedGradient : totalScoreBackgroundGradient, transition_duration, Easing.OutQuint); } + protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) + { + Scheduler.AddOnce(() => + { + // TODO: may not always invalidate as expected + + // when width decreases + // - hide statistics, then + // - hide avatar, then + // - hide user and flag and show avatar again + + if (centreContent.DrawWidth >= height + username_min_width || centreContent.DrawWidth < username_min_width) + avatar.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + else + avatar.FadeOut(transition_duration, Easing.OutQuint).MoveToX(-avatar.DrawWidth, transition_duration, Easing.OutQuint); + + if (centreContent.DrawWidth >= username_min_width) + { + usernameAndFlagContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + innerAvatar.ShowUsernameTooltip = false; + } + else + { + usernameAndFlagContainer.FadeOut(transition_duration, Easing.OutQuint).MoveToX(usernameAndFlagContainer.DrawWidth, transition_duration, Easing.OutQuint); + innerAvatar.ShowUsernameTooltip = true; + } + + if (centreContent.DrawWidth >= height + statisticsContainer.DrawWidth + username_min_width) + statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + else + statisticsContainer.FadeOut(transition_duration, Easing.OutQuint).MoveToX(statisticsContainer.DrawWidth, transition_duration, Easing.OutQuint); + }); + + return base.OnInvalidate(invalidation, source); + } + #region Subclasses private partial class DateLabel : DrawableDate From ba62498478bc0d84f10f3fb021662c4bebcd750f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 20:41:19 -0700 Subject: [PATCH 48/87] Add set up steps to reinit drawables with a different relative width --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index f0d07c8526..b09ba793b6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,16 +27,28 @@ namespace osu.Game.Tests.Visual.SongSelect [Cached] private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); - private FillFlowContainer fillFlow = null!; - private OsuSpriteText drawWidthText = null!; + private FillFlowContainer? fillFlow; + private OsuSpriteText? drawWidthText; + private float relativeWidth; [BackgroundDependencyLoader] private void load() + { + AddSliderStep("change relative width", 0, 1f, 0.6f, v => + { + relativeWidth = v; + if (fillFlow != null) fillFlow.Width = v; + }); + } + + [SetUp] + public void Setup() => Schedule(() => { Children = new Drawable[] { fillFlow = new FillFlowContainer { + Width = relativeWidth, Anchor = Anchor.Centre, Origin = Anchor.Centre, Spacing = new Vector2(0, 10), @@ -50,18 +63,13 @@ namespace osu.Game.Tests.Visual.SongSelect foreach (var score in fillFlow.Children) score.Show(); - - AddSliderStep("change relative width", 0, 1f, 0.6f, v => - { - fillFlow.Width = v; - }); - } + }); protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - drawWidthText.Text = $"DrawWidth: {fillFlow.DrawWidth}"; + if (drawWidthText != null) drawWidthText.Text = $"DrawWidth: {fillFlow?.DrawWidth}"; } private static ScoreInfo[] getTestScores() From f2aff628b23a5be4d5c69d44573f6754f6f3a8b9 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 22:14:04 -0700 Subject: [PATCH 49/87] Fix statistics container showing for a brief moment on lower widths --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index c77424902f..938dfefa4d 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -130,7 +130,11 @@ namespace osu.Game.Online.Leaderboards shadowColour = isPersonalBest ? colourProvider.Background3 : colourProvider.Background6; totalScoreBackgroundGradient = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), backgroundColour); - statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)).ToList(); + statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score) + { + // ensure statistics container is the correct width when invalidating + AlwaysPresent = true, + }).ToList(); Child = content = new Container { @@ -288,6 +292,7 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.CentreRight, Child = statisticsContainer = new FillFlowContainer { + Name = @"Statistics container", Padding = new MarginPadding { Right = 40 }, Spacing = new Vector2(25), Shear = -shear, @@ -295,7 +300,8 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Children = statisticsLabels + Children = statisticsLabels, + Alpha = 0, } } } From e32be36d929dd5cc614c65a4dd6178bba752cd0d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 10 Oct 2023 22:14:23 -0700 Subject: [PATCH 50/87] Move invalidation issue todo to tests --- osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 2 ++ osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index b09ba793b6..92370e7e58 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -34,6 +34,8 @@ namespace osu.Game.Tests.Visual.SongSelect [BackgroundDependencyLoader] private void load() { + // TODO: invalidation seems to be one-off when clicking slider to a certain value, so drag for now + // doesn't seem to happen in-game (when toggling window mode) AddSliderStep("change relative width", 0, 1f, 0.6f, v => { relativeWidth = v; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 938dfefa4d..bc9e6476a0 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -510,8 +510,6 @@ namespace osu.Game.Online.Leaderboards { Scheduler.AddOnce(() => { - // TODO: may not always invalidate as expected - // when width decreases // - hide statistics, then // - hide avatar, then From 42d41add41f705a877a63e9cbe84171a17eb6709 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 11 Oct 2023 09:40:59 -0700 Subject: [PATCH 51/87] Remove unused field --- osu.Game/Online/Leaderboards/DrawableRank.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index e4691efc04..d21c38090a 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -18,12 +18,8 @@ namespace osu.Game.Online.Leaderboards { public partial class DrawableRank : CompositeDrawable { - private readonly ScoreRank rank; - public DrawableRank(ScoreRank rank) { - this.rank = rank; - RelativeSizeAxes = Axes.Both; FillMode = FillMode.Fit; FillAspectRatio = 2; From f6741514aafb337ffbb707ab9ba36736e45c193f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 11 Oct 2023 09:39:15 -0700 Subject: [PATCH 52/87] Remove alternative total score display (colour gradient) for now For simplicity and a future consideration for when the skinning portion is implemented. --- osu.Game/Graphics/OsuColour.cs | 21 ------------------- .../Online/Leaderboards/LeaderboardScoreV2.cs | 1 - 2 files changed, 22 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index d1b232b26d..1b21f79c0a 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Game.Beatmaps; using osu.Game.Online.Rooms; @@ -69,26 +68,6 @@ namespace osu.Game.Graphics } } - /// - /// Retrieves the colour for the total score depending on . - /// - public static ColourInfo TotalScoreColourFor(ScoreRank rank) - { - switch (rank) - { - case ScoreRank.XH: - case ScoreRank.X: - return ColourInfo.GradientVertical(Colour4.FromHex(@"A4DEFF"), Colour4.FromHex(@"F0AADD")); - - case ScoreRank.SH: - case ScoreRank.S: - return ColourInfo.GradientVertical(Colour4.FromHex(@"FFFFFF"), Colour4.FromHex(@"F7E65D")); - - default: - return Colour4.White; - } - } - /// /// Retrieves the colour for a . /// diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index bc9e6476a0..76986de623 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -414,7 +414,6 @@ namespace osu.Game.Online.Leaderboards Shear = -shear, Current = scoreManager.GetBindableTotalScoreString(score), Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - Colour = OsuColour.TotalScoreColourFor(score.Rank), }, modsContainer = new FillFlowContainer { From 52be580f28d7d1aa90c6a2d213a79cdebde59f18 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 11 Oct 2023 09:40:34 -0700 Subject: [PATCH 53/87] Fix date not aligning with flag --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 76986de623..4e20b7f8f5 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -273,6 +273,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + UseFullGlyphHeight = false, } } }, From f17aa6d644eff49b5e144faa9e12178708957f99 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 11 Oct 2023 12:57:50 -0700 Subject: [PATCH 54/87] Revert changes to `ModSwitchTiny` --- osu.Game/Rulesets/UI/ModSwitchTiny.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index df7722761d..a5cf75bd07 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -24,8 +24,8 @@ namespace osu.Game.Rulesets.UI private readonly IMod mod; - protected Box Background; - protected OsuSpriteText AcronymText; + private readonly Box background; + private readonly OsuSpriteText acronymText; private Color4 activeForegroundColour; private Color4 inactiveForegroundColour; @@ -44,11 +44,11 @@ namespace osu.Game.Rulesets.UI Masking = true, Children = new Drawable[] { - Background = new Box + background = new Box { RelativeSizeAxes = Axes.Both }, - AcronymText = new OsuSpriteText + acronymText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -78,14 +78,14 @@ namespace osu.Game.Rulesets.UI { base.LoadComplete(); - Active.BindValueChanged(_ => UpdateState(), true); + Active.BindValueChanged(_ => updateState(), true); FinishTransforms(true); } - protected virtual void UpdateState() + private void updateState() { - AcronymText.FadeColour(Active.Value ? activeForegroundColour : inactiveForegroundColour, 200, Easing.OutQuint); - Background.FadeColour(Active.Value ? activeBackgroundColour : inactiveBackgroundColour, 200, Easing.OutQuint); + acronymText.FadeColour(Active.Value ? activeForegroundColour : inactiveForegroundColour, 200, Easing.OutQuint); + background.FadeColour(Active.Value ? activeBackgroundColour : inactiveBackgroundColour, 200, Easing.OutQuint); } } } From 418549b48d3855269e2858d25b7bf95fe8445bc9 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 11 Oct 2023 12:38:46 -0700 Subject: [PATCH 55/87] Modify some half time mods on test For use after support of extended info on `ModSwitchTiny`. --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 92370e7e58..c5f96d1568 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -146,14 +146,22 @@ namespace osu.Game.Tests.Visual.SongSelect TestResources.CreateTestScoreInfo(), }; + var halfTime = new OsuModHalfTime + { + SpeedChange = + { + Value = 0.99 + } + }; + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED; i++) - scores[0].Mods = scores[0].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + scores[0].Mods = scores[0].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : halfTime }).ToArray(); for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED + 1; i++) scores[1].Mods = scores[1].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED; i++) - scores[2].Mods = scores[2].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); + scores[2].Mods = scores[2].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : halfTime }).ToArray(); for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED + 1; i++) scores[3].Mods = scores[3].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); From 4c4621eb58c8bd23744bb03970c07cfdf841ee0a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 28 Apr 2024 23:12:48 -0700 Subject: [PATCH 56/87] Fix compile errors --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 4e20b7f8f5..d71ce2bdf9 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -346,7 +346,6 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Masking = true, SpawnRatio = 2, Velocity = 0.7f, Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Darken(0.2f)), @@ -521,15 +520,9 @@ namespace osu.Game.Online.Leaderboards avatar.FadeOut(transition_duration, Easing.OutQuint).MoveToX(-avatar.DrawWidth, transition_duration, Easing.OutQuint); if (centreContent.DrawWidth >= username_min_width) - { usernameAndFlagContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); - innerAvatar.ShowUsernameTooltip = false; - } else - { usernameAndFlagContainer.FadeOut(transition_duration, Easing.OutQuint).MoveToX(usernameAndFlagContainer.DrawWidth, transition_duration, Easing.OutQuint); - innerAvatar.ShowUsernameTooltip = true; - } if (centreContent.DrawWidth >= height + statisticsContainer.DrawWidth + username_min_width) statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); From 32df6991ad238df5a82aaa6a0e4d27dcd6b028bd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 28 Apr 2024 23:12:55 -0700 Subject: [PATCH 57/87] Remove dark border and update cover gradient --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 195 ++++++++---------- 1 file changed, 87 insertions(+), 108 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index d71ce2bdf9..80bf251631 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -66,7 +66,6 @@ namespace osu.Game.Online.Leaderboards private Colour4 foregroundColour; private Colour4 backgroundColour; - private Colour4 shadowColour; private ColourInfo totalScoreBackgroundGradient; private static readonly Vector2 shear = new Vector2(0.15f, 0); @@ -127,7 +126,6 @@ namespace osu.Game.Online.Leaderboards foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5; backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4; - shadowColour = isPersonalBest ? colourProvider.Background3 : colourProvider.Background6; totalScoreBackgroundGradient = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), backgroundColour); statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score) @@ -184,129 +182,110 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + foreground = new Box { RelativeSizeAxes = Axes.Both, - Colour = shadowColour, + Colour = foregroundColour }, - new Container + new UserCoverBackground { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new Container + User = score.User, + Shear = -shear, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.FromHex(@"222A27").Opacity(1)), + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - Masking = true, - CornerRadius = corner_radius, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - foreground = new Box + new Container { - RelativeSizeAxes = Axes.Both, - Colour = foregroundColour - }, - new UserCoverBackground - { - RelativeSizeAxes = Axes.Both, - User = score.User, - Shear = -shear, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.White.Opacity(0)), - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] + AutoSizeAxes = Axes.Both, + Child = avatar = new MaskedWrapper( + innerAvatar = new ClickableAvatar(user) { - new Container + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, + }, + usernameAndFlagContainer = new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = corner_radius }, + Children = new Drawable[] + { + flagBadgeAndDateContainer = new FillFlowContainer + { + Shear = -shear, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Child = avatar = new MaskedWrapper( - innerAvatar = new ClickableAvatar(user) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, - RelativeSizeAxes = Axes.Both, - }) + new UpdateableFlag(user.CountryCode) { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(24, 16), }, - }, - usernameAndFlagContainer = new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = corner_radius }, - Children = new Drawable[] + new DateLabel(score.Date) { - flagBadgeAndDateContainer = new FillFlowContainer - { - Shear = -shear, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - new UpdateableFlag(user.CountryCode) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(24, 16), - }, - new DateLabel(score.Date) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - UseFullGlyphHeight = false, - } - } - }, - nameLabel = new TruncatingSpriteText - { - RelativeSizeAxes = Axes.X, - Shear = -shear, - Text = user.Username, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) - } - } - }, - new Container - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Child = statisticsContainer = new FillFlowContainer - { - Name = @"Statistics container", - Padding = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25), - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = statisticsLabels, - Alpha = 0, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + UseFullGlyphHeight = false, } } + }, + nameLabel = new TruncatingSpriteText + { + RelativeSizeAxes = Axes.X, + Shear = -shear, + Text = user.Username, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) } } + }, + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Child = statisticsContainer = new FillFlowContainer + { + Name = @"Statistics container", + Padding = new MarginPadding { Right = 40 }, + Spacing = new Vector2(25), + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = statisticsLabels, + Alpha = 0, + } } } }, From 2d4f2245ee1dc33bb6f0410f7ce230de5f4b5a06 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 2 May 2024 23:00:04 -0700 Subject: [PATCH 58/87] Remove total score border gradient --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 80bf251631..b4f6379f06 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -353,8 +353,7 @@ namespace osu.Game.Online.Leaderboards new Container { AutoSizeAxes = Axes.X, - // makeshift inner border - Height = height - 4, + RelativeSizeAxes = Axes.Y, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Padding = new MarginPadding { Right = grade_width }, From d0c8b55a0a67723d58c47ffa20cc8985337da106 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 5 May 2024 22:26:00 -0700 Subject: [PATCH 59/87] Fix fluidity desync by not autosizing right (total score) content --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index b4f6379f06..a2331f1fdc 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -41,16 +41,16 @@ namespace osu.Game.Online.Leaderboards public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { /// - /// The maximum number of mods when contracted until the mods display width exceeds the . + /// The maximum number of mods when contracted until the mods display width exceeds the . /// public const int MAX_MODS_CONTRACTED = 13; /// - /// The maximum number of mods when expanded until the mods display width exceeds the . + /// The maximum number of mods when expanded until the mods display width exceeds the . /// public const int MAX_MODS_EXPANDED = 4; - private const float right_content_min_width = 180; + private const float right_content_width = 180; private const float grade_width = 40; private const float username_min_width = 100; @@ -153,7 +153,7 @@ namespace osu.Game.Online.Leaderboards { new Dimension(GridSizeMode.Absolute, 65), new Dimension(), - new Dimension(GridSizeMode.AutoSize, minSize: right_content_min_width), // use min size to account for classic scoring + new Dimension(GridSizeMode.Absolute, right_content_width), }, Content = new[] { From 8a474f7d2231706819056030f3db268b4321c5dd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 5 May 2024 22:27:21 -0700 Subject: [PATCH 60/87] Fix broken avatar masking when hiding --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index a2331f1fdc..bf5dc3572d 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -212,7 +212,9 @@ namespace osu.Game.Online.Leaderboards new Container { AutoSizeAxes = Axes.Both, - Child = avatar = new MaskedWrapper( + CornerRadius = corner_radius, + Masking = true, + Child = avatar = new DelayedLoadWrapper( innerAvatar = new ClickableAvatar(user) { Anchor = Anchor.Centre, @@ -592,16 +594,6 @@ namespace osu.Game.Online.Leaderboards public LocalisableString TooltipText { get; } } - private partial class MaskedWrapper : DelayedLoadWrapper - { - public MaskedWrapper(Drawable content, double timeBeforeLoad = 500) - : base(content, timeBeforeLoad) - { - CornerRadius = corner_radius; - Masking = true; - } - } - private sealed partial class ColouredModSwitchTiny : ModSwitchTiny, IHasTooltip { private readonly IMod mod; From e8967ff3c572a2f9ef62f37fa622d85cadbf2f7c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 9 May 2024 22:39:41 -0700 Subject: [PATCH 61/87] Lower username font size a bit --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index bf5dc3572d..dea134b4d6 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -266,7 +266,7 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.X, Shear = -shear, Text = user.Username, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold) + Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) } } }, From 736e15ab26e10134b29ccf773505f8964161d816 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 May 2024 22:21:50 -0700 Subject: [PATCH 62/87] Improve fluidity states --- .../Online/Leaderboards/LeaderboardScoreV2.cs | 116 ++++++++++++------ 1 file changed, 81 insertions(+), 35 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index dea134b4d6..d0a264a7e3 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -52,7 +52,11 @@ namespace osu.Game.Online.Leaderboards private const float right_content_width = 180; private const float grade_width = 40; - private const float username_min_width = 100; + private const float username_min_width = 125; + private const float statistics_regular_min_width = 175; + private const float statistics_compact_min_width = 100; + private const float rank_label_width = 65; + private const float rank_label_visibility_width_cutoff = rank_label_width + height + username_min_width + statistics_regular_min_width + right_content_width; private readonly ScoreInfo score; @@ -101,9 +105,9 @@ namespace osu.Game.Online.Leaderboards private Drawable scoreRank = null!; private Box totalScoreBackground = null!; - private Container centreContent = null!; - private FillFlowContainer usernameAndFlagContainer = null!; private FillFlowContainer statisticsContainer = null!; + private RankLabel rankLabel = null!; + private Container rankLabelOverlay = null!; public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => score; @@ -151,7 +155,7 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, ColumnDimensions = new[] { - new Dimension(GridSizeMode.Absolute, 65), + new Dimension(GridSizeMode.AutoSize), new Dimension(), new Dimension(GridSizeMode.Absolute, right_content_width), }, @@ -159,8 +163,17 @@ namespace osu.Game.Online.Leaderboards { new Drawable[] { - new RankLabel(rank) { Shear = -shear }, - centreContent = createCentreContent(user), + new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Child = rankLabel = new RankLabel(rank) + { + Width = rank_label_width, + RelativeSizeAxes = Axes.Y, + }, + }, + createCentreContent(user), createRightContent() } } @@ -214,21 +227,43 @@ namespace osu.Game.Online.Leaderboards AutoSizeAxes = Axes.Both, CornerRadius = corner_radius, Masking = true, - Child = avatar = new DelayedLoadWrapper( - innerAvatar = new ClickableAvatar(user) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.1f), - Shear = -shear, - RelativeSizeAxes = Axes.Both, - }) + Children = new[] { - RelativeSizeAxes = Axes.None, - Size = new Vector2(height) + avatar = new DelayedLoadWrapper( + innerAvatar = new ClickableAvatar(user) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.1f), + Shear = -shear, + RelativeSizeAxes = Axes.Both, + }) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(height) + }, + rankLabelOverlay = new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Black.Opacity(0.5f), + }, + new RankLabel(rank) + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + } + } }, }, - usernameAndFlagContainer = new FillFlowContainer + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -279,7 +314,7 @@ namespace osu.Game.Online.Leaderboards { Name = @"Statistics container", Padding = new MarginPadding { Right = 40 }, - Spacing = new Vector2(25), + Spacing = new Vector2(25, 0), Shear = -shear, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -287,6 +322,8 @@ namespace osu.Game.Online.Leaderboards Direction = FillDirection.Horizontal, Children = statisticsLabels, Alpha = 0, + LayoutEasing = Easing.OutQuint, + LayoutDuration = transition_duration, } } } @@ -483,6 +520,11 @@ namespace osu.Game.Online.Leaderboards foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint); background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint); totalScoreBackground.FadeColour(IsHovered ? lightenedGradient : totalScoreBackgroundGradient, transition_duration, Easing.OutQuint); + + if (DrawWidth < rank_label_visibility_width_cutoff && IsHovered) + rankLabelOverlay.FadeIn(transition_duration, Easing.OutQuint); + else + rankLabelOverlay.FadeOut(transition_duration, Easing.OutQuint); } protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) @@ -490,22 +532,27 @@ namespace osu.Game.Online.Leaderboards Scheduler.AddOnce(() => { // when width decreases - // - hide statistics, then - // - hide avatar, then - // - hide user and flag and show avatar again + // - hide rank and show rank overlay on avatar when hovered, then + // - compact statistics, then + // - hide statistics - if (centreContent.DrawWidth >= height + username_min_width || centreContent.DrawWidth < username_min_width) - avatar.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + if (DrawWidth >= rank_label_visibility_width_cutoff) + rankLabel.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); else - avatar.FadeOut(transition_duration, Easing.OutQuint).MoveToX(-avatar.DrawWidth, transition_duration, Easing.OutQuint); + rankLabel.FadeOut(transition_duration, Easing.OutQuint).MoveToX(-rankLabel.DrawWidth, transition_duration, Easing.OutQuint); - if (centreContent.DrawWidth >= username_min_width) - usernameAndFlagContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); - else - usernameAndFlagContainer.FadeOut(transition_duration, Easing.OutQuint).MoveToX(usernameAndFlagContainer.DrawWidth, transition_duration, Easing.OutQuint); - - if (centreContent.DrawWidth >= height + statisticsContainer.DrawWidth + username_min_width) + if (DrawWidth >= height + username_min_width + statistics_regular_min_width + right_content_width) + { statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + statisticsContainer.Direction = FillDirection.Horizontal; + statisticsContainer.ScaleTo(1, transition_duration, Easing.OutQuint); + } + else if (DrawWidth >= height + username_min_width + statistics_compact_min_width + right_content_width) + { + statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); + statisticsContainer.Direction = FillDirection.Vertical; + statisticsContainer.ScaleTo(0.8f, transition_duration, Easing.OutQuint); + } else statisticsContainer.FadeOut(transition_duration, Easing.OutQuint).MoveToX(statisticsContainer.DrawWidth, transition_duration, Easing.OutQuint); }); @@ -577,15 +624,14 @@ namespace osu.Game.Online.Leaderboards { public RankLabel(int? rank) { - AutoSizeAxes = Axes.Both; - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - if (rank >= 1000) TooltipText = $"#{rank:N0}"; Child = new OsuSpriteText { + Shear = -shear, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true), Text = rank == null ? "-" : rank.Value.FormatRank().Insert(0, "#") }; From 9b84d8ac2f7ffd662c190e18b096bf5add9a2bf3 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 May 2024 22:39:22 -0700 Subject: [PATCH 63/87] Apply missed changes from old leaderboard score See: - https://github.com/ppy/osu/commit/d11e56b8bb6ade5c4f6e47de5fa288a909f6bc66 - https://github.com/ppy/osu/commit/7d74d84e6c24e6938d27fae0d7322e113df4be94 - https://github.com/ppy/osu/commit/07f9f5c6d842d3c7c564f96576682b6fb54c50b4 --- osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index d0a264a7e3..b9ae3bb20e 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -439,7 +439,7 @@ namespace osu.Game.Online.Leaderboards Shear = -shear, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) + ChildrenEnumerable = score.Mods.AsOrdered().Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) }, modsCounter = new OsuSpriteText { @@ -671,12 +671,12 @@ namespace osu.Game.Online.Leaderboards { List items = new List(); - if (score.Mods.Length > 0 && modsContainer.Any(s => s.IsHovered) && songSelect != null) + if (score.Mods.Length > 0 && songSelect != null) items.Add(new OsuMenuItem("Use these mods", MenuItemType.Highlighted, () => songSelect.Mods.Value = score.Mods)); if (score.Files.Count <= 0) return items.ToArray(); - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(score))); + items.Add(new OsuMenuItem(Localisation.CommonStrings.Export, MenuItemType.Standard, () => scoreManager.Export(score))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(score)))); return items.ToArray(); From a2794922d53a5db8f2c2748c535d2fc441b6621f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 06:23:07 +0300 Subject: [PATCH 64/87] Add `TopLevelContent` layer for applying external transforms on footer buttons --- .../TestSceneScreenFooterButtonMods.cs | 15 +- osu.Game/Screens/Footer/ScreenFooterButton.cs | 143 ++++++++++-------- .../SelectV2/Footer/ScreenFooterButtonMods.cs | 8 +- 3 files changed, 99 insertions(+), 67 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs index df2109ace8..2e2baf6e96 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.SelectV2.Footer; @@ -26,12 +27,12 @@ namespace osu.Game.Tests.Visual.UserInterface public TestSceneScreenFooterButtonMods() { - Add(footerButtonMods = new TestScreenFooterButtonMods + Add(footerButtonMods = new TestScreenFooterButtonMods(new TestModSelectOverlay()) { Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, - X = -100, Action = () => { }, + X = -100, }); } @@ -112,9 +113,19 @@ namespace osu.Game.Tests.Visual.UserInterface return expectedValue == footerButtonMods.MultiplierText.Current.Value; } + private partial class TestModSelectOverlay : UserModSelectOverlay + { + protected override bool ShowPresets => true; + } + private partial class TestScreenFooterButtonMods : ScreenFooterButtonMods { public new OsuSpriteText MultiplierText => base.MultiplierText; + + public TestScreenFooterButtonMods(ModSelectOverlay overlay) + : base(overlay) + { + } } } } diff --git a/osu.Game/Screens/Footer/ScreenFooterButton.cs b/osu.Game/Screens/Footer/ScreenFooterButton.cs index 8fbd9f6cba..dda95d1d4c 100644 --- a/osu.Game/Screens/Footer/ScreenFooterButton.cs +++ b/osu.Game/Screens/Footer/ScreenFooterButton.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Footer set => icon.Icon = value; } - protected LocalisableString Text + public LocalisableString Text { set => text.Text = value; } @@ -69,87 +69,99 @@ namespace osu.Game.Screens.Footer private readonly Box glowBox; private readonly Box flashLayer; - public ScreenFooterButton() + public readonly Container TopLevelContent; + public readonly OverlayContainer? Overlay; + + public ScreenFooterButton(OverlayContainer? overlay = null) { + Overlay = overlay; + Size = new Vector2(BUTTON_WIDTH, BUTTON_HEIGHT); - Child = new Container + Child = TopLevelContent = new Container { - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Radius = 4, - // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. - Colour = Colour4.Black.Opacity(0.25f), - Offset = new Vector2(0, 2), - }, - Shear = BUTTON_SHEAR, - Masking = true, - CornerRadius = CORNER_RADIUS, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - backgroundBox = new Box - { - RelativeSizeAxes = Axes.Both - }, - glowBox = new Box - { - RelativeSizeAxes = Axes.Both - }, - // For elements that should not be sheared. new Container { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Shear = -BUTTON_SHEAR, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 4, + // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. + Colour = Colour4.Black.Opacity(0.25f), + Offset = new Vector2(0, 2), + }, + Shear = BUTTON_SHEAR, + Masking = true, + CornerRadius = CORNER_RADIUS, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - TextContainer = new Container + backgroundBox = new Box { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Y = 42, - AutoSizeAxes = Axes.Both, - Child = text = new OsuSpriteText + RelativeSizeAxes = Axes.Both + }, + glowBox = new Box + { + RelativeSizeAxes = Axes.Both + }, + // For elements that should not be sheared. + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Shear = -BUTTON_SHEAR, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - // figma design says the size is 16, but due to the issues with font sizes 19 matches better - Font = OsuFont.TorusAlternate.With(size: 19), - AlwaysPresent = true + TextContainer = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Y = 42, + AutoSizeAxes = Axes.Both, + Child = text = new OsuSpriteText + { + // figma design says the size is 16, but due to the issues with font sizes 19 matches better + Font = OsuFont.TorusAlternate.With(size: 19), + AlwaysPresent = true + } + }, + icon = new SpriteIcon + { + Y = 12, + Size = new Vector2(20), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, } }, - icon = new SpriteIcon + new Container { - Y = 12, - Size = new Vector2(20), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre + Shear = -BUTTON_SHEAR, + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre, + Y = -CORNER_RADIUS, + Size = new Vector2(120, 6), + Masking = true, + CornerRadius = 3, + Child = bar = new Box + { + RelativeSizeAxes = Axes.Both, + } }, - } - }, - new Container - { - Shear = -BUTTON_SHEAR, - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre, - Y = -CORNER_RADIUS, - Size = new Vector2(120, 6), - Masking = true, - CornerRadius = 3, - Child = bar = new Box - { - RelativeSizeAxes = Axes.Both, - } - }, - flashLayer = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Colour4.White.Opacity(0.9f), - Blending = BlendingParameters.Additive, - Alpha = 0, - }, - }, + flashLayer = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White.Opacity(0.9f), + Blending = BlendingParameters.Additive, + Alpha = 0, + }, + }, + } + } }; } @@ -157,6 +169,9 @@ namespace osu.Game.Screens.Footer { base.LoadComplete(); + if (Overlay != null) + OverlayState.BindTo(Overlay.State); + OverlayState.BindValueChanged(_ => updateDisplay()); Enabled.BindValueChanged(_ => updateDisplay(), true); diff --git a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs index f590a19164..4df4116de1 100644 --- a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs +++ b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Localisation; using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Footer; using osu.Game.Screens.Play.HUD; @@ -59,6 +60,11 @@ namespace osu.Game.Screens.SelectV2.Footer [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; + public ScreenFooterButtonMods(ModSelectOverlay overlay) + : base(overlay) + { + } + [BackgroundDependencyLoader] private void load() { @@ -66,7 +72,7 @@ namespace osu.Game.Screens.SelectV2.Footer Icon = FontAwesome.Solid.ExchangeAlt; AccentColour = colours.Lime1; - AddRange(new[] + TopLevelContent.AddRange(new[] { unrankedBadge = new UnrankedBadge(), modDisplayBar = new Container From d0e8632fbffef00b75cc227e1435c03ff348c467 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 06:24:58 +0300 Subject: [PATCH 65/87] Refactor `ScreenFooter` to prepare for global usage and add transitions --- osu.Game/Screens/Footer/ScreenFooter.cs | 162 +++++++++++++++++++----- 1 file changed, 130 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index 4a10a4cdab..d299bf7362 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.cs @@ -2,54 +2,33 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Game.Overlays; using osuTK; namespace osu.Game.Screens.Footer { - public partial class ScreenFooter : InputBlockingContainer + public partial class ScreenFooter : OverlayContainer { - private const int height = 60; private const int padding = 60; + private const float delay_per_button = 30; + + public const int HEIGHT = 60; private readonly List overlays = new List(); - /// The button to be added. - /// The to be toggled by this button. - public void AddButton(ScreenFooterButton button, OverlayContainer? overlay = null) - { - if (overlay != null) - { - overlays.Add(overlay); - button.Action = () => showOverlay(overlay); - button.OverlayState.BindTo(overlay.State); - } - - buttons.Add(button); - } - - private void showOverlay(OverlayContainer overlay) - { - foreach (var o in overlays) - { - if (o == overlay) - o.ToggleVisibility(); - else - o.Hide(); - } - } - - private FillFlowContainer buttons = null!; + private FillFlowContainer buttonsFlow = null!; + private Container removedButtonsContainer = null!; public ScreenFooter() { RelativeSizeAxes = Axes.X; - Height = height; + Height = HEIGHT; Anchor = Anchor.BottomLeft; Origin = Anchor.BottomLeft; } @@ -64,9 +43,10 @@ namespace osu.Game.Screens.Footer RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background5 }, - buttons = new FillFlowContainer + buttonsFlow = new FillFlowContainer { - Position = new Vector2(ScreenBackButton.BUTTON_WIDTH + padding, 10), + Margin = new MarginPadding { Left = 12f + ScreenBackButton.BUTTON_WIDTH + padding }, + Y = 10f, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Direction = FillDirection.Horizontal, @@ -80,7 +60,125 @@ namespace osu.Game.Screens.Footer Origin = Anchor.BottomLeft, Action = () => { }, }, + removedButtonsContainer = new Container + { + Margin = new MarginPadding { Left = 12f + ScreenBackButton.BUTTON_WIDTH + padding }, + Y = 10f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + }, }; } + + protected override void PopIn() + { + this.MoveToY(0, 400, Easing.OutQuint) + .FadeIn(400, Easing.OutQuint); + } + + protected override void PopOut() + { + this.MoveToY(HEIGHT, 400, Easing.OutQuint) + .FadeOut(400, Easing.OutQuint); + } + + public void SetButtons(IReadOnlyList buttons) + { + overlays.Clear(); + + var oldButtons = buttonsFlow.ToArray(); + + for (int i = 0; i < oldButtons.Length; i++) + { + var oldButton = oldButtons[i]; + + buttonsFlow.Remove(oldButton, false); + removedButtonsContainer.Add(oldButton); + + if (buttons.Count > 0) + fadeButtonToLeft(oldButton, i, oldButtons.Length); + else + fadeButtonToBottom(oldButton, i, oldButtons.Length); + + Scheduler.AddDelayed(() => oldButton.Expire(), oldButton.TopLevelContent.LatestTransformEndTime - Time.Current); + } + + for (int i = 0; i < buttons.Count; i++) + { + var newButton = buttons[i]; + + if (newButton.Overlay != null) + { + newButton.Action = () => showOverlay(newButton.Overlay); + overlays.Add(newButton.Overlay); + } + + Debug.Assert(!newButton.IsLoaded); + buttonsFlow.Add(newButton); + + int index = i; + + // ensure transforms are added after LoadComplete to not be aborted by the FinishTransforms call. + newButton.OnLoadComplete += _ => + { + if (oldButtons.Length > 0) + fadeButtonFromRight(newButton, index, buttons.Count, 240); + else + fadeButtonFromBottom(newButton, index); + }; + } + } + + private void fadeButtonFromRight(ScreenFooterButton button, int index, int count, float startDelay) + { + button.TopLevelContent + .MoveToX(-300f) + .FadeOut(); + + button.TopLevelContent + .Delay(startDelay + (count - index) * delay_per_button) + .MoveToX(0f, 240, Easing.OutCubic) + .FadeIn(240, Easing.OutCubic); + } + + private void fadeButtonFromBottom(ScreenFooterButton button, int index) + { + button.TopLevelContent + .MoveToY(100f) + .FadeOut(); + + button.TopLevelContent + .Delay(index * delay_per_button) + .MoveToY(0f, 240, Easing.OutCubic) + .FadeIn(240, Easing.OutCubic); + } + + private void fadeButtonToLeft(ScreenFooterButton button, int index, int count) + { + button.TopLevelContent + .Delay((count - index) * delay_per_button) + .FadeOut(240, Easing.InOutCubic) + .MoveToX(300f, 360, Easing.InOutCubic); + } + + private void fadeButtonToBottom(ScreenFooterButton button, int index, int count) + { + button.TopLevelContent + .Delay((count - index) * delay_per_button) + .FadeOut(240, Easing.InOutCubic) + .MoveToY(100f, 240, Easing.InOutCubic); + } + + private void showOverlay(OverlayContainer overlay) + { + foreach (var o in overlays) + { + if (o == overlay) + o.ToggleVisibility(); + else + o.Hide(); + } + } } } From 95840672cb945b5f7a3ca3039b0dea8138d7ddcc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 06:26:59 +0300 Subject: [PATCH 66/87] Clean up screen footer test scene --- .../UserInterface/TestSceneScreenFooter.cs | 180 ++++-------------- 1 file changed, 39 insertions(+), 141 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs index 162609df70..01b3aa5787 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs @@ -2,34 +2,22 @@ // 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.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Testing; using osu.Game.Overlays; using osu.Game.Overlays.Mods; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Footer; using osu.Game.Screens.SelectV2.Footer; -using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { public partial class TestSceneScreenFooter : OsuManualInputManagerTestScene { - private ScreenFooterButtonRandom randomButton = null!; - private ScreenFooterButtonMods modsButton = null!; - - private bool nextRandomCalled; - private bool previousRandomCalled; - - private DummyOverlay overlay = null!; + private ScreenFooter screenFooter = null!; + private TestModSelectOverlay overlay = null!; [Cached] private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); @@ -37,160 +25,70 @@ namespace osu.Game.Tests.Visual.UserInterface [SetUp] public void SetUp() => Schedule(() => { - nextRandomCalled = false; - previousRandomCalled = false; - - ScreenFooter footer; - Children = new Drawable[] { + overlay = new TestModSelectOverlay + { + Padding = new MarginPadding + { + Bottom = ScreenFooter.HEIGHT + } + }, new PopoverContainer { RelativeSizeAxes = Axes.Both, - Child = footer = new ScreenFooter(), + Child = screenFooter = new ScreenFooter(), }, - overlay = new DummyOverlay() }; - footer.AddButton(modsButton = new ScreenFooterButtonMods { Current = SelectedMods }, overlay); - footer.AddButton(randomButton = new ScreenFooterButtonRandom + screenFooter.SetButtons(new ScreenFooterButton[] { - NextRandom = () => nextRandomCalled = true, - PreviousRandom = () => previousRandomCalled = true + new ScreenFooterButtonMods(overlay) { Current = SelectedMods }, + new ScreenFooterButtonRandom(), + new ScreenFooterButtonOptions(), }); - footer.AddButton(new ScreenFooterButtonOptions()); - - overlay.Hide(); }); [SetUpSteps] public void SetUpSteps() { - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddStep("set beatmap", () => Beatmap.Value = CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo))); + AddStep("show footer", () => screenFooter.Show()); } + /// + /// Transition when moving from a screen with no buttons to a screen with buttons. + /// [Test] - public void TestMods() + public void TestButtonsIn() { - AddStep("one mod", () => SelectedMods.Value = new List { new OsuModHidden() }); - AddStep("two mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock() }); - AddStep("three mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime() }); - AddStep("four mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic() }); - AddStep("five mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() }); - - AddStep("modified", () => SelectedMods.Value = new List { new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); - AddStep("modified + one", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); - AddStep("modified + two", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); - AddStep("modified + three", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); - AddStep("modified + four", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDifficultyAdjust(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddWaitStep("wait", 3); - AddStep("one mod", () => SelectedMods.Value = new List { new OsuModHidden() }); - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddWaitStep("wait", 3); - AddStep("five mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() }); } + /// + /// Transition when moving from a screen with buttons to a screen with no buttons. + /// [Test] - public void TestShowOptions() + public void TestButtonsOut() { - AddStep("enable options", () => + AddStep("clear buttons", () => screenFooter.SetButtons(Array.Empty())); + } + + /// + /// Transition when moving from a screen with buttons to a screen with buttons. + /// + [Test] + public void TestReplaceButtons() + { + AddStep("replace buttons", () => screenFooter.SetButtons(new[] { - var optionsButton = this.ChildrenOfType().Last(); - - optionsButton.Enabled.Value = true; - optionsButton.TriggerClick(); - }); + new ScreenFooterButton { Text = "One", Action = () => { } }, + new ScreenFooterButton { Text = "Two", Action = () => { } }, + new ScreenFooterButton { Text = "Three", Action = () => { } }, + })); } - [Test] - public void TestState() + private partial class TestModSelectOverlay : UserModSelectOverlay { - AddToggleStep("set options enabled state", state => this.ChildrenOfType().Last().Enabled.Value = state); - } - - [Test] - public void TestFooterRandom() - { - AddStep("press F2", () => InputManager.Key(Key.F2)); - AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); - } - - [Test] - public void TestFooterRandomViaMouse() - { - AddStep("click button", () => - { - InputManager.MoveMouseTo(randomButton); - InputManager.Click(MouseButton.Left); - }); - AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); - } - - [Test] - public void TestFooterRewind() - { - AddStep("press Shift+F2", () => - { - InputManager.PressKey(Key.LShift); - InputManager.PressKey(Key.F2); - InputManager.ReleaseKey(Key.F2); - InputManager.ReleaseKey(Key.LShift); - }); - AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); - } - - [Test] - public void TestFooterRewindViaShiftMouseLeft() - { - AddStep("shift + click button", () => - { - InputManager.PressKey(Key.LShift); - InputManager.MoveMouseTo(randomButton); - InputManager.Click(MouseButton.Left); - InputManager.ReleaseKey(Key.LShift); - }); - AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); - } - - [Test] - public void TestFooterRewindViaMouseRight() - { - AddStep("right click button", () => - { - InputManager.MoveMouseTo(randomButton); - InputManager.Click(MouseButton.Right); - }); - AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); - } - - [Test] - public void TestOverlayPresent() - { - AddStep("Press F1", () => - { - InputManager.MoveMouseTo(modsButton); - InputManager.Click(MouseButton.Left); - }); - AddAssert("Overlay visible", () => overlay.State.Value == Visibility.Visible); - AddStep("Hide", () => overlay.Hide()); - } - - private partial class DummyOverlay : ShearedOverlayContainer - { - public DummyOverlay() - : base(OverlayColourScheme.Green) - { - } - - [BackgroundDependencyLoader] - private void load() - { - Header.Title = "An overlay"; - } + protected override bool ShowPresets => true; } } } From 921be3ca014d2b7cbc04cd554de89ed5174df0d8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 06:59:58 +0300 Subject: [PATCH 67/87] Add back receptor, logo tracking, and own colour provider to screen footer --- osu.Game/Graphics/UserInterface/BackButton.cs | 33 ++-------- osu.Game/Screens/Footer/BackButtonV2.cs | 64 +++++++++++++++++++ osu.Game/Screens/Footer/ScreenFooter.cs | 62 ++++++++++++++++-- 3 files changed, 126 insertions(+), 33 deletions(-) create mode 100644 osu.Game/Screens/Footer/BackButtonV2.cs diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index cd9a357ea4..29bac8fbae 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -7,19 +7,18 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Game.Input.Bindings; +using osu.Game.Screens.Footer; namespace osu.Game.Graphics.UserInterface { + // todo: remove this once all screens migrate to display the new game footer and back button. public partial class BackButton : VisibilityContainer { public Action Action; private readonly TwoLayerButton button; - public BackButton(Receptor receptor = null) + public BackButton(ScreenFooter.BackReceptor receptor = null) { Size = TwoLayerButton.SIZE_EXTENDED; @@ -35,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface if (receptor == null) { // if a receptor wasn't provided, create our own locally. - Add(receptor = new Receptor()); + Add(receptor = new ScreenFooter.BackReceptor()); } receptor.OnBackPressed = () => button.TriggerClick(); @@ -59,29 +58,5 @@ namespace osu.Game.Graphics.UserInterface button.MoveToX(-TwoLayerButton.SIZE_EXTENDED.X / 2, 400, Easing.OutQuint); button.FadeOut(400, Easing.OutQuint); } - - public partial class Receptor : Drawable, IKeyBindingHandler - { - public Action OnBackPressed; - - public bool OnPressed(KeyBindingPressEvent e) - { - if (e.Repeat) - return false; - - switch (e.Action) - { - case GlobalAction.Back: - OnBackPressed?.Invoke(); - return true; - } - - return false; - } - - public void OnReleased(KeyBindingReleaseEvent e) - { - } - } } } diff --git a/osu.Game/Screens/Footer/BackButtonV2.cs b/osu.Game/Screens/Footer/BackButtonV2.cs new file mode 100644 index 0000000000..08daa339c2 --- /dev/null +++ b/osu.Game/Screens/Footer/BackButtonV2.cs @@ -0,0 +1,64 @@ +// 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.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Footer +{ + public partial class BackButtonV2 : ShearedButton + { + // todo: see https://github.com/ppy/osu-framework/issues/3271 + private const float torus_scale_factor = 1.2f; + + public const float BUTTON_WIDTH = 240; + + public BackButtonV2() + : base(BUTTON_WIDTH, 70) + { + } + + [BackgroundDependencyLoader] + private void load() + { + ButtonContent.Child = new FillFlowContainer + { + X = -10f, + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20f, 0f), + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20f), + Icon = FontAwesome.Solid.ChevronLeft, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.TorusAlternate.With(size: 20 * torus_scale_factor), + Text = CommonStrings.Back, + UseFullGlyphHeight = false, + } + } + }; + + DarkerColour = Color4Extensions.FromHex("#DE31AE"); + LighterColour = Color4Extensions.FromHex("#FF86DD"); + TextColour = Color4.White; + } + } +} diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index d299bf7362..69d5a2616c 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.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; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,7 +9,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; using osu.Game.Overlays; +using osu.Game.Screens.Menu; using osuTK; namespace osu.Game.Screens.Footer @@ -22,19 +28,31 @@ namespace osu.Game.Screens.Footer private readonly List overlays = new List(); + private BackButtonV2 backButton = null!; private FillFlowContainer buttonsFlow = null!; private Container removedButtonsContainer = null!; + private LogoTrackingContainer logoTrackingContainer = null!; - public ScreenFooter() + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + + public Action? OnBack; + + public ScreenFooter(BackReceptor? receptor = null) { RelativeSizeAxes = Axes.X; Height = HEIGHT; Anchor = Anchor.BottomLeft; Origin = Anchor.BottomLeft; + + if (receptor == null) + Add(receptor = new BackReceptor()); + + receptor.OnBackPressed = () => backButton.TriggerClick(); } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load() { InternalChildren = new Drawable[] { @@ -53,12 +71,12 @@ namespace osu.Game.Screens.Footer Spacing = new Vector2(7, 0), AutoSizeAxes = Axes.Both }, - new ScreenBackButton + backButton = new BackButtonV2 { Margin = new MarginPadding { Bottom = 10f, Left = 12f }, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Action = () => { }, + Action = () => OnBack?.Invoke(), }, removedButtonsContainer = new Container { @@ -68,9 +86,21 @@ namespace osu.Game.Screens.Footer Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, }, + (logoTrackingContainer = new LogoTrackingContainer + { + RelativeSizeAxes = Axes.Both, + }).WithChild(logoTrackingContainer.LogoFacade.With(f => + { + f.Anchor = Anchor.BottomRight; + f.Origin = Anchor.Centre; + f.Position = new Vector2(-76, -36); + })), }; } + public void StartTrackingLogo(OsuLogo logo, float duration = 0, Easing easing = Easing.None) => logoTrackingContainer.StartTracking(logo, duration, easing); + public void StopTrackingLogo() => logoTrackingContainer.StopTracking(); + protected override void PopIn() { this.MoveToY(0, 400, Easing.OutQuint) @@ -180,5 +210,29 @@ namespace osu.Game.Screens.Footer o.Hide(); } } + + public partial class BackReceptor : Drawable, IKeyBindingHandler + { + public Action? OnBackPressed; + + public bool OnPressed(KeyBindingPressEvent e) + { + if (e.Repeat) + return false; + + switch (e.Action) + { + case GlobalAction.Back: + OnBackPressed?.Invoke(); + return true; + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + } } } From 03220598b8734cb93d53d15cc054d89e2d4f04ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 07:20:55 +0300 Subject: [PATCH 68/87] Move screen footer to `OsuGame` --- .../UserInterface/TestSceneBackButton.cs | 3 +- .../UserInterface/TestSceneScreenFooter.cs | 9 ++-- .../TestSceneScreenFooterButtonMods.cs | 5 ++ osu.Game/OsuGame.cs | 46 +++++++++++++++---- osu.Game/Screens/IOsuScreen.cs | 17 ++++++- .../OnlinePlay/OnlinePlaySongSelect.cs | 4 +- osu.Game/Screens/OsuScreen.cs | 9 ++++ osu.Game/Screens/OsuScreenStack.cs | 6 +++ osu.Game/Screens/Select/SongSelect.cs | 28 +++++------ 9 files changed, 96 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 494268b158..7aaf616767 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Footer; using osuTK; using osuTK.Graphics; @@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface public TestSceneBackButton() { BackButton button; - BackButton.Receptor receptor = new BackButton.Receptor(); + ScreenFooter.BackReceptor receptor = new ScreenFooter.BackReceptor(); Child = new Container { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs index 01b3aa5787..dabb2e7f50 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooter.cs @@ -3,7 +3,6 @@ using System; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Testing; @@ -19,9 +18,6 @@ namespace osu.Game.Tests.Visual.UserInterface private ScreenFooter screenFooter = null!; private TestModSelectOverlay overlay = null!; - [Cached] - private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); - [SetUp] public void SetUp() => Schedule(() => { @@ -89,6 +85,11 @@ namespace osu.Game.Tests.Visual.UserInterface private partial class TestModSelectOverlay : UserModSelectOverlay { protected override bool ShowPresets => true; + + public TestModSelectOverlay() + : base(OverlayColourScheme.Aquamarine) + { + } } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs index 2e2baf6e96..ba53eb83c4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenFooterButtonMods.cs @@ -116,6 +116,11 @@ namespace osu.Game.Tests.Visual.UserInterface private partial class TestModSelectOverlay : UserModSelectOverlay { protected override bool ShowPresets => true; + + public TestModSelectOverlay() + : base(OverlayColourScheme.Aquamarine) + { + } } private partial class TestScreenFooterButtonMods : ScreenFooterButtonMods diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index af01a1b1ac..ee1d262f88 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -22,6 +22,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -58,6 +59,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Edit; +using osu.Game.Screens.Footer; using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.Play; @@ -153,6 +155,8 @@ namespace osu.Game private float toolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0); + private float screenFooterOffset => (ScreenFooter?.DrawHeight ?? 0) - (ScreenFooter?.Position.Y ?? 0); + private IdleTracker idleTracker; /// @@ -177,6 +181,7 @@ namespace osu.Game protected OsuScreenStack ScreenStack; protected BackButton BackButton; + protected ScreenFooter ScreenFooter; protected SettingsOverlay Settings; @@ -917,7 +922,7 @@ namespace osu.Game }; Container logoContainer; - BackButton.Receptor receptor; + ScreenFooter.BackReceptor backReceptor; dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); @@ -950,20 +955,28 @@ namespace osu.Game Origin = Anchor.Centre, Children = new Drawable[] { - receptor = new BackButton.Receptor(), + backReceptor = new ScreenFooter.BackReceptor(), ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - BackButton = new BackButton(receptor) + BackButton = new BackButton(backReceptor) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Action = () => + Action = () => ScreenFooter.OnBack?.Invoke(), + }, + new PopoverContainer + { + RelativeSizeAxes = Axes.Both, + Child = ScreenFooter = new ScreenFooter(backReceptor) { - if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen)) - return; + OnBack = () => + { + if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen)) + return; - if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowBackButton && !currentScreen.OnBackButton())) - ScreenStack.Exit(); - } + if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowBackButton && !currentScreen.OnBackButton())) + ScreenStack.Exit(); + } + }, }, logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } @@ -985,6 +998,8 @@ namespace osu.Game new ConfineMouseTracker() }); + dependencies.Cache(ScreenFooter); + ScreenStack.ScreenPushed += screenPushed; ScreenStack.ScreenExited += screenExited; @@ -1457,6 +1472,7 @@ namespace osu.Game ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; + ScreenStack.Padding = new MarginPadding { Bottom = screenFooterOffset }; float horizontalOffset = 0f; @@ -1529,6 +1545,18 @@ namespace osu.Game BackButton.Show(); else BackButton.Hide(); + + if (newOsuScreen.ShowFooter) + { + BackButton.Hide(); + ScreenFooter.SetButtons(newOsuScreen.CreateFooterButtons()); + ScreenFooter.Show(); + } + else + { + ScreenFooter.SetButtons(Array.Empty()); + ScreenFooter.Hide(); + } } skinEditor.SetTarget((OsuScreen)newScreen); diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 5b4e2d75f4..b80c1f87a4 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Screens.Footer; using osu.Game.Users; namespace osu.Game.Screens @@ -19,10 +21,18 @@ namespace osu.Game.Screens bool DisallowExternalBeatmapRulesetChanges { get; } /// - /// Whether the user can exit this this by pressing the back button. + /// Whether the user can exit this by pressing the back button. /// bool AllowBackButton { get; } + /// + /// Whether a footer (and a back button) should be displayed underneath the screen. + /// + /// + /// Temporarily, the back button is shown regardless of whether is true. + /// + bool ShowFooter { get; } + /// /// Whether a top-level component should be allowed to exit the current screen to, for example, /// complete an import. Note that this can be overridden by a user if they specifically request. @@ -63,6 +73,11 @@ namespace osu.Game.Screens Bindable Ruleset { get; } + /// + /// A list of footer buttons to be added to the game footer, or empty to display no buttons. + /// + IReadOnlyList CreateFooterButtons(); + /// /// Whether mod track adjustments should be applied on entering this screen. /// A value means that the parent screen's value of this setting will be used. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index 622ffddba6..a8dfece916 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -173,9 +173,9 @@ namespace osu.Game.Screens.OnlinePlay IsValidMod = IsValidMod }; - protected override IEnumerable<(FooterButton, OverlayContainer?)> CreateFooterButtons() + protected override IEnumerable<(FooterButton, OverlayContainer?)> CreateSongSelectFooterButtons() { - var baseButtons = base.CreateFooterButtons().ToList(); + var baseButtons = base.CreateSongSelectFooterButtons().ToList(); var freeModsButton = new FooterButtonFreeMods(freeModSelectOverlay) { Current = FreeMods }; baseButtons.Insert(baseButtons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (freeModsButton, freeModSelectOverlay)); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 2e8f85423d..695a074907 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -16,6 +16,7 @@ using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Footer; using osu.Game.Screens.Menu; using osu.Game.Users; @@ -38,6 +39,8 @@ namespace osu.Game.Screens public virtual bool AllowBackButton => true; + public virtual bool ShowFooter => false; + public virtual bool AllowExternalScreenChange => false; public virtual bool HideOverlaysOnEnter => false; @@ -141,6 +144,10 @@ namespace osu.Game.Screens [Resolved(canBeNull: true)] private OsuLogo logo { get; set; } + [Resolved(canBeNull: true)] + [CanBeNull] + protected ScreenFooter Footer { get; private set; } + protected OsuScreen() { Anchor = Anchor.Centre; @@ -298,6 +305,8 @@ namespace osu.Game.Screens /// protected virtual BackgroundScreen CreateBackground() => null; + public virtual IReadOnlyList CreateFooterButtons() => Array.Empty(); + public virtual bool OnBackButton() => false; } } diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index 7d1f6419ad..7103fd6466 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -17,6 +17,12 @@ namespace osu.Game.Screens protected float ParallaxAmount => parallaxContainer.ParallaxAmount; + public new MarginPadding Padding + { + get => base.Padding; + set => base.Padding = value; + } + public OsuScreenStack() { InternalChild = parallaxContainer = new ParallaxContainer diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6225534e95..4b0084c7c5 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -60,19 +60,19 @@ namespace osu.Game.Screens.Select /// protected virtual bool ControlGlobalMusic => true; - protected virtual bool ShowFooter => true; + protected virtual bool ShowSongSelectFooter => true; public override bool? ApplyModTrackAdjustments => true; /// - /// Can be null if is false. + /// Can be null if is false. /// protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } = null!; /// - /// Can be null if is false. + /// Can be null if is false. /// - protected Footer? Footer { get; private set; } + protected Footer? SongSelectFooter { get; private set; } /// /// Contains any panel which is triggered by a footer button. @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Both, BleedTop = FilterControl.HEIGHT, - BleedBottom = Footer.HEIGHT, + BleedBottom = Select.Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, FilterApplied = () => Scheduler.AddOnce(updateVisibleBeatmapCount), @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Top = FilterControl.HEIGHT, - Bottom = Footer.HEIGHT + Bottom = Select.Footer.HEIGHT }, Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } } } @@ -297,7 +297,7 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Bottom = Footer.HEIGHT, + Bottom = Select.Footer.HEIGHT, Top = WEDGE_HEIGHT + 70, Left = left_area_padding, Right = left_area_padding * 2, @@ -321,7 +321,7 @@ namespace osu.Game.Screens.Select }, }); - if (ShowFooter) + if (ShowSongSelectFooter) { AddRangeInternal(new Drawable[] { @@ -330,13 +330,13 @@ namespace osu.Game.Screens.Select Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Bottom = Footer.HEIGHT }, + Padding = new MarginPadding { Bottom = Select.Footer.HEIGHT }, Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), } }, - Footer = new Footer() + SongSelectFooter = new Footer() }); } @@ -344,10 +344,10 @@ namespace osu.Game.Screens.Select // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. LoadComponent(ModSelect = CreateModSelectOverlay()); - if (Footer != null) + if (SongSelectFooter != null) { - foreach (var (button, overlay) in CreateFooterButtons()) - Footer.AddButton(button, overlay); + foreach (var (button, overlay) in CreateSongSelectFooterButtons()) + SongSelectFooter.AddButton(button, overlay); BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show()); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => DeleteBeatmap(Beatmap.Value.BeatmapSetInfo)); @@ -381,7 +381,7 @@ namespace osu.Game.Screens.Select /// Creates the buttons to be displayed in the footer. /// /// A set of and an optional which the button opens when pressed. - protected virtual IEnumerable<(FooterButton, OverlayContainer?)> CreateFooterButtons() => new (FooterButton, OverlayContainer?)[] + protected virtual IEnumerable<(FooterButton, OverlayContainer?)> CreateSongSelectFooterButtons() => new (FooterButton, OverlayContainer?)[] { (new FooterButtonMods { Current = Mods }, ModSelect), (new FooterButtonRandom From 2b5818a4d7e7cc4940703885e28633a080e859b9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 07:21:32 +0300 Subject: [PATCH 69/87] Fix DI crash in beatmap options popover --- .../SelectV2/Footer/BeatmapOptionsPopover.cs | 22 +++++++++---------- .../Footer/ScreenFooterButtonOptions.cs | 6 ++++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/SelectV2/Footer/BeatmapOptionsPopover.cs b/osu.Game/Screens/SelectV2/Footer/BeatmapOptionsPopover.cs index f73be15a36..11a83f3438 100644 --- a/osu.Game/Screens/SelectV2/Footer/BeatmapOptionsPopover.cs +++ b/osu.Game/Screens/SelectV2/Footer/BeatmapOptionsPopover.cs @@ -20,7 +20,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays; -using osu.Game.Screens.Select; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -33,18 +32,22 @@ namespace osu.Game.Screens.SelectV2.Footer private FillFlowContainer buttonFlow = null!; private readonly ScreenFooterButtonOptions footerButton; + [Cached] + private readonly OverlayColourProvider colourProvider; + private WorkingBeatmap beatmapWhenOpening = null!; [Resolved] private IBindable beatmap { get; set; } = null!; - public BeatmapOptionsPopover(ScreenFooterButtonOptions footerButton) + public BeatmapOptionsPopover(ScreenFooterButtonOptions footerButton, OverlayColourProvider colourProvider) { this.footerButton = footerButton; + this.colourProvider = colourProvider; } [BackgroundDependencyLoader] - private void load(ManageCollectionsDialog? manageCollectionsDialog, SongSelect? songSelect, OsuColour colours, BeatmapManager? beatmapManager) + private void load(ManageCollectionsDialog? manageCollectionsDialog, OsuColour colours, BeatmapManager? beatmapManager) { Content.Padding = new MarginPadding(5); @@ -61,15 +64,15 @@ namespace osu.Game.Screens.SelectV2.Footer addButton(SongSelectStrings.ManageCollections, FontAwesome.Solid.Book, () => manageCollectionsDialog?.Show()); addHeader(SongSelectStrings.ForAllDifficulties, beatmapWhenOpening.BeatmapSetInfo.ToString()); - addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => songSelect?.DeleteBeatmap(beatmapWhenOpening.BeatmapSetInfo), colours.Red1); + addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => { }, colours.Red1); // songSelect?.DeleteBeatmap(beatmapWhenOpening.BeatmapSetInfo); addHeader(SongSelectStrings.ForSelectedDifficulty, beatmapWhenOpening.BeatmapInfo.DifficultyName); // TODO: make work, and make show "unplayed" or "played" based on status. addButton(SongSelectStrings.MarkAsPlayed, FontAwesome.Regular.TimesCircle, null); - addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => songSelect?.ClearScores(beatmapWhenOpening.BeatmapInfo), colours.Red1); + addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => { }, colours.Red1); // songSelect?.ClearScores(beatmapWhenOpening.BeatmapInfo); - if (songSelect != null && songSelect.AllowEditing) - addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => songSelect.Edit(beatmapWhenOpening.BeatmapInfo)); + // if (songSelect != null && songSelect.AllowEditing) + addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => { }); // songSelect.Edit(beatmapWhenOpening.BeatmapInfo); addButton(WebCommonStrings.ButtonsHide.ToSentence(), FontAwesome.Solid.Magic, () => beatmapManager?.Hide(beatmapWhenOpening.BeatmapInfo)); } @@ -83,9 +86,6 @@ namespace osu.Game.Screens.SelectV2.Footer beatmap.BindValueChanged(_ => Hide()); } - [Resolved] - private OverlayColourProvider overlayColourProvider { get; set; } = null!; - private void addHeader(LocalisableString text, string? context = null) { var textFlow = new OsuTextFlowContainer @@ -102,7 +102,7 @@ namespace osu.Game.Screens.SelectV2.Footer textFlow.NewLine(); textFlow.AddText(context, t => { - t.Colour = overlayColourProvider.Content2; + t.Colour = colourProvider.Content2; t.Font = t.Font.With(size: 13); }); } diff --git a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonOptions.cs b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonOptions.cs index 74fe3e3d11..72409b5566 100644 --- a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonOptions.cs +++ b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonOptions.cs @@ -8,12 +8,16 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Overlays; using osu.Game.Screens.Footer; namespace osu.Game.Screens.SelectV2.Footer { public partial class ScreenFooterButtonOptions : ScreenFooterButton, IHasPopover { + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + [BackgroundDependencyLoader] private void load(OsuColour colour) { @@ -25,6 +29,6 @@ namespace osu.Game.Screens.SelectV2.Footer Action = this.ShowPopover; } - public Popover GetPopover() => new BeatmapOptionsPopover(this); + public Popover GetPopover() => new BeatmapOptionsPopover(this, colourProvider); } } From 8b285f5b1e911fe8baec3ce2691e678d2a33d269 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 May 2024 07:21:41 +0300 Subject: [PATCH 70/87] Add dummy `SongSelectV2` screen to house new footer buttons (and new components going forward) --- .../SongSelect/TestSceneSongSelectV2.cs | 204 ++++++++++++++++++ .../TestSceneSongSelectV2Navigation.cs | 33 +++ osu.Game/Screens/SelectV2/SongSelectV2.cs | 145 +++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2Navigation.cs create mode 100644 osu.Game/Screens/SelectV2/SongSelectV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs new file mode 100644 index 0000000000..674eaa2ff8 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs @@ -0,0 +1,204 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Overlays.Mods; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens; +using osu.Game.Screens.Footer; +using osu.Game.Screens.Menu; +using osu.Game.Screens.SelectV2; +using osu.Game.Screens.SelectV2.Footer; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public partial class TestSceneSongSelectV2 : ScreenTestScene + { + [Cached] + private readonly ScreenFooter screenScreenFooter; + + [Cached] + private readonly OsuLogo logo; + + public TestSceneSongSelectV2() + { + Children = new Drawable[] + { + new PopoverContainer + { + RelativeSizeAxes = Axes.Both, + Child = screenScreenFooter = new ScreenFooter + { + OnBack = () => Stack.CurrentScreen.Exit(), + }, + }, + logo = new OsuLogo + { + Alpha = 0f, + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Stack.ScreenPushed += updateFooter; + Stack.ScreenExited += updateFooter; + } + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("load screen", () => Stack.Push(new SongSelectV2())); + AddUntilStep("wait for load", () => Stack.CurrentScreen is SongSelectV2 songSelect && songSelect.IsLoaded); + } + + #region Footer + + [Test] + public void TestMods() + { + AddStep("one mod", () => SelectedMods.Value = new List { new OsuModHidden() }); + AddStep("two mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock() }); + AddStep("three mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime() }); + AddStep("four mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic() }); + AddStep("five mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() }); + + AddStep("modified", () => SelectedMods.Value = new List { new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); + AddStep("modified + one", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); + AddStep("modified + two", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); + AddStep("modified + three", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); + AddStep("modified + four", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDifficultyAdjust(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } }); + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddWaitStep("wait", 3); + AddStep("one mod", () => SelectedMods.Value = new List { new OsuModHidden() }); + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddWaitStep("wait", 3); + AddStep("five mods", () => SelectedMods.Value = new List { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() }); + } + + [Test] + public void TestShowOptions() + { + AddStep("enable options", () => + { + var optionsButton = this.ChildrenOfType().Last(); + + optionsButton.Enabled.Value = true; + optionsButton.TriggerClick(); + }); + } + + [Test] + public void TestState() + { + AddToggleStep("set options enabled state", state => this.ChildrenOfType().Last().Enabled.Value = state); + } + + // add these test cases when functionality is implemented. + // [Test] + // public void TestFooterRandom() + // { + // AddStep("press F2", () => InputManager.Key(Key.F2)); + // AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); + // } + // + // [Test] + // public void TestFooterRandomViaMouse() + // { + // AddStep("click button", () => + // { + // InputManager.MoveMouseTo(randomButton); + // InputManager.Click(MouseButton.Left); + // }); + // AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); + // } + // + // [Test] + // public void TestFooterRewind() + // { + // AddStep("press Shift+F2", () => + // { + // InputManager.PressKey(Key.LShift); + // InputManager.PressKey(Key.F2); + // InputManager.ReleaseKey(Key.F2); + // InputManager.ReleaseKey(Key.LShift); + // }); + // AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); + // } + // + // [Test] + // public void TestFooterRewindViaShiftMouseLeft() + // { + // AddStep("shift + click button", () => + // { + // InputManager.PressKey(Key.LShift); + // InputManager.MoveMouseTo(randomButton); + // InputManager.Click(MouseButton.Left); + // InputManager.ReleaseKey(Key.LShift); + // }); + // AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); + // } + // + // [Test] + // public void TestFooterRewindViaMouseRight() + // { + // AddStep("right click button", () => + // { + // InputManager.MoveMouseTo(randomButton); + // InputManager.Click(MouseButton.Right); + // }); + // AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); + // } + + [Test] + public void TestOverlayPresent() + { + AddStep("Press F1", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("Overlay visible", () => this.ChildrenOfType().Single().State.Value == Visibility.Visible); + AddStep("Hide", () => this.ChildrenOfType().Single().Hide()); + } + + #endregion + + protected override void Update() + { + base.Update(); + Stack.Padding = new MarginPadding { Bottom = screenScreenFooter.DrawHeight - screenScreenFooter.Y }; + } + + private void updateFooter(IScreen? _, IScreen? newScreen) + { + if (newScreen is IOsuScreen osuScreen && osuScreen.ShowFooter) + { + screenScreenFooter.Show(); + screenScreenFooter.SetButtons(osuScreen.CreateFooterButtons()); + } + else + { + screenScreenFooter.Hide(); + screenScreenFooter.SetButtons(Array.Empty()); + } + } + } +} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2Navigation.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2Navigation.cs new file mode 100644 index 0000000000..ededb80228 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2Navigation.cs @@ -0,0 +1,33 @@ +// 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.Testing; +using osu.Game.Screens.Menu; +using osu.Game.Screens.SelectV2; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public partial class TestSceneSongSelectV2Navigation : OsuGameTestScene + { + public override void SetUpSteps() + { + base.SetUpSteps(); + AddStep("press enter", () => InputManager.Key(Key.Enter)); + AddWaitStep("wait", 5); + PushAndConfirm(() => new SongSelectV2()); + } + + [Test] + public void TestClickLogo() + { + AddStep("click", () => + { + InputManager.MoveMouseTo(Game.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + } + } +} diff --git a/osu.Game/Screens/SelectV2/SongSelectV2.cs b/osu.Game/Screens/SelectV2/SongSelectV2.cs new file mode 100644 index 0000000000..10ed7783c4 --- /dev/null +++ b/osu.Game/Screens/SelectV2/SongSelectV2.cs @@ -0,0 +1,145 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Screens; +using osu.Game.Overlays; +using osu.Game.Overlays.Mods; +using osu.Game.Screens.Footer; +using osu.Game.Screens.Menu; +using osu.Game.Screens.Play; +using osu.Game.Screens.SelectV2.Footer; + +namespace osu.Game.Screens.SelectV2 +{ + /// + /// This screen is intended to house all components introduced in the new song select design to add transitions and examine the overall look. + /// This will be gradually built upon and ultimately replace once everything is in place. + /// + public partial class SongSelectV2 : OsuScreen + { + private readonly ModSelectOverlay modSelectOverlay = new SoloModSelectOverlay(); + + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + + public override bool ShowFooter => true; + + [BackgroundDependencyLoader] + private void load() + { + AddRangeInternal(new Drawable[] + { + new PopoverContainer + { + RelativeSizeAxes = Axes.Both, + }, + modSelectOverlay, + }); + } + + public override IReadOnlyList CreateFooterButtons() => new ScreenFooterButton[] + { + new ScreenFooterButtonMods(modSelectOverlay) { Current = Mods }, + new ScreenFooterButtonRandom(), + new ScreenFooterButtonOptions(), + }; + + public override void OnEntering(ScreenTransitionEvent e) + { + this.FadeIn(); + base.OnEntering(e); + } + + public override void OnResuming(ScreenTransitionEvent e) + { + this.FadeIn(); + base.OnResuming(e); + } + + public override void OnSuspending(ScreenTransitionEvent e) + { + this.Delay(400).FadeOut(); + base.OnSuspending(e); + } + + public override bool OnExiting(ScreenExitEvent e) + { + this.Delay(400).FadeOut(); + return base.OnExiting(e); + } + + public override bool OnBackButton() + { + if (modSelectOverlay.State.Value == Visibility.Visible) + { + modSelectOverlay.Hide(); + return true; + } + + return false; + } + + protected override void LogoArriving(OsuLogo logo, bool resuming) + { + base.LogoArriving(logo, resuming); + + if (logo.Alpha > 0.8f) + Footer?.StartTrackingLogo(logo, 400, Easing.OutQuint); + else + { + logo.Hide(); + logo.ScaleTo(0.2f); + Footer?.StartTrackingLogo(logo); + } + + logo.FadeIn(240, Easing.OutQuint); + logo.ScaleTo(0.4f, 240, Easing.OutQuint); + + logo.Action = () => + { + this.Push(new PlayerLoaderV2(() => new SoloPlayer())); + return false; + }; + } + + protected override void LogoSuspending(OsuLogo logo) + { + base.LogoSuspending(logo); + Footer?.StopTrackingLogo(); + } + + protected override void LogoExiting(OsuLogo logo) + { + base.LogoExiting(logo); + Scheduler.AddDelayed(() => Footer?.StopTrackingLogo(), 120); + logo.ScaleTo(0.2f, 120, Easing.Out); + logo.FadeOut(120, Easing.Out); + } + + private partial class SoloModSelectOverlay : ModSelectOverlay + { + protected override bool ShowPresets => true; + + public SoloModSelectOverlay() + : base(OverlayColourScheme.Aquamarine) + { + } + } + + private partial class PlayerLoaderV2 : PlayerLoader + { + public override bool ShowFooter => true; + + public PlayerLoaderV2(Func createPlayer) + : base(createPlayer) + { + } + } + } +} From 0a391d5c4ebf9bd38d6cb3b6b8f7313169d75ed8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 18 May 2024 08:39:45 +0300 Subject: [PATCH 71/87] Remove duplicate back button class --- osu.Game/Screens/Footer/BackButtonV2.cs | 64 ------------------------- osu.Game/Screens/Footer/ScreenFooter.cs | 4 +- 2 files changed, 2 insertions(+), 66 deletions(-) delete mode 100644 osu.Game/Screens/Footer/BackButtonV2.cs diff --git a/osu.Game/Screens/Footer/BackButtonV2.cs b/osu.Game/Screens/Footer/BackButtonV2.cs deleted file mode 100644 index 08daa339c2..0000000000 --- a/osu.Game/Screens/Footer/BackButtonV2.cs +++ /dev/null @@ -1,64 +0,0 @@ -// 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.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Localisation; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Screens.Footer -{ - public partial class BackButtonV2 : ShearedButton - { - // todo: see https://github.com/ppy/osu-framework/issues/3271 - private const float torus_scale_factor = 1.2f; - - public const float BUTTON_WIDTH = 240; - - public BackButtonV2() - : base(BUTTON_WIDTH, 70) - { - } - - [BackgroundDependencyLoader] - private void load() - { - ButtonContent.Child = new FillFlowContainer - { - X = -10f, - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(20f, 0f), - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(20f), - Icon = FontAwesome.Solid.ChevronLeft, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.TorusAlternate.With(size: 20 * torus_scale_factor), - Text = CommonStrings.Back, - UseFullGlyphHeight = false, - } - } - }; - - DarkerColour = Color4Extensions.FromHex("#DE31AE"); - LighterColour = Color4Extensions.FromHex("#FF86DD"); - TextColour = Color4.White; - } - } -} diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index 69d5a2616c..9addda5deb 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Footer private readonly List overlays = new List(); - private BackButtonV2 backButton = null!; + private ScreenBackButton backButton = null!; private FillFlowContainer buttonsFlow = null!; private Container removedButtonsContainer = null!; private LogoTrackingContainer logoTrackingContainer = null!; @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Footer Spacing = new Vector2(7, 0), AutoSizeAxes = Axes.Both }, - backButton = new BackButtonV2 + backButton = new ScreenBackButton { Margin = new MarginPadding { Bottom = 10f, Left = 12f }, Anchor = Anchor.BottomLeft, From 1f012937833974b9da49e32d21621d3ee6729003 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 12:36:09 +0300 Subject: [PATCH 72/87] Make scores slanted in test scene --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index c5f96d1568..ffd07be8aa 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -53,15 +53,22 @@ namespace osu.Game.Tests.Visual.SongSelect Width = relativeWidth, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Spacing = new Vector2(0, 10), RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0f, 2f), }, drawWidthText = new OsuSpriteText(), }; + int i = 0; + foreach (var scoreInfo in getTestScores()) - fillFlow.Add(new LeaderboardScoreV2(scoreInfo, scoreInfo.Position, scoreInfo.User.Id == 2)); + { + fillFlow.Add(new LeaderboardScoreV2(scoreInfo, scoreInfo.Position, scoreInfo.User.Id == 2) + { + Margin = new MarginPadding { Right = 10f * i, Left = -10f * i++ }, + }); + } foreach (var score in fillFlow.Children) score.Show(); From 35af518fdb3b0099faa74b09fdbaa43a1892dd46 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 12:52:42 +0300 Subject: [PATCH 73/87] Remove expanded/contracted states and limit to 5 mods Also adjusts right content width to contain those 5 mods. Not sure how to handle the extra space in the score though...to be dealt with later. --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 9 +++---- .../Online/Leaderboards/LeaderboardScoreV2.cs | 27 ++++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index ffd07be8aa..86c3c9a7ac 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -161,16 +161,13 @@ namespace osu.Game.Tests.Visual.SongSelect } }; - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED; i++) - scores[0].Mods = scores[0].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : halfTime }).ToArray(); - - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_EXPANDED + 1; i++) + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS - 1; i++) scores[1].Mods = scores[1].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED; i++) + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS; i++) scores[2].Mods = scores[2].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : halfTime }).ToArray(); - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS_CONTRACTED + 1; i++) + for (int i = 0; i < LeaderboardScoreV2.MAX_MODS + 1; i++) scores[3].Mods = scores[3].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); scores[4].Mods = scores[4].BeatmapInfo!.Ruleset.CreateInstance().CreateAllMods().ToArray(); diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index b9ae3bb20e..5db86bd7d0 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -43,14 +43,9 @@ namespace osu.Game.Online.Leaderboards /// /// The maximum number of mods when contracted until the mods display width exceeds the . /// - public const int MAX_MODS_CONTRACTED = 13; + public const int MAX_MODS = 5; - /// - /// The maximum number of mods when expanded until the mods display width exceeds the . - /// - public const int MAX_MODS_EXPANDED = 4; - - private const float right_content_width = 180; + private const float right_content_width = 210; private const float grade_width = 40; private const float username_min_width = 125; private const float statistics_regular_min_width = 175; @@ -183,8 +178,17 @@ namespace osu.Game.Online.Leaderboards innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); - modsContainer.Spacing = new Vector2(modsContainer.Children.Count > MAX_MODS_EXPANDED ? -20 : 2, 0); - modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 }; + if (score.Mods.Length > MAX_MODS) + modsCounter.Text = $"{score.Mods.Length} mods"; + else if (score.Mods.Length > 0) + { + modsContainer.ChildrenEnumerable = score.Mods.AsOrdered().Select(mod => new ColouredModSwitchTiny(mod) + { + Scale = new Vector2(0.375f) + }); + } + + modsContainer.Padding = new MarginPadding { Top = score.Mods.Length > 0 ? 4 : 0 }; } private Container createCentreContent(APIUser user) => new Container @@ -439,14 +443,13 @@ namespace osu.Game.Online.Leaderboards Shear = -shear, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = score.Mods.AsOrdered().Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }) + Spacing = new Vector2(2f, 0f), }, modsCounter = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Shear = -shear, - Text = $"{score.Mods.Length} mods", Alpha = 0, } } @@ -492,7 +495,7 @@ namespace osu.Game.Online.Leaderboards using (BeginDelayedSequence(50)) { - Drawable modsDrawable = score.Mods.Length > MAX_MODS_CONTRACTED ? modsCounter : modsContainer; + Drawable modsDrawable = score.Mods.Length > MAX_MODS ? modsCounter : modsContainer; var drawables = new[] { flagBadgeAndDateContainer, modsDrawable }.Concat(statisticsLabels).ToArray(); for (int i = 0; i < drawables.Length; i++) drawables[i].FadeIn(100 + i * 50); From 59553780040dbf82c48b7bd675f0c64ba97194bd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 16:11:24 +0300 Subject: [PATCH 74/87] Replace "X mods" text with a pill indicator --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 12 +-- .../Online/Leaderboards/LeaderboardScoreV2.cs | 86 +++++++++++++------ osu.Game/Rulesets/UI/ModSwitchTiny.cs | 6 +- 3 files changed, 65 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 86c3c9a7ac..42407ad2b0 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -161,15 +161,9 @@ namespace osu.Game.Tests.Visual.SongSelect } }; - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS - 1; i++) - scores[1].Mods = scores[1].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); - - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS; i++) - scores[2].Mods = scores[2].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : halfTime }).ToArray(); - - for (int i = 0; i < LeaderboardScoreV2.MAX_MODS + 1; i++) - scores[3].Mods = scores[3].Mods.Concat(new Mod[] { i % 2 == 0 ? new OsuModHidden() : new OsuModHalfTime() }).ToArray(); - + scores[1].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight() }; + scores[2].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight(), new OsuModClassic() }; + scores[3].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight(), new OsuModClassic(), new OsuModDifficultyAdjust() }; scores[4].Mods = scores[4].BeatmapInfo!.Ruleset.CreateInstance().CreateAllMods().ToArray(); return scores; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index 5db86bd7d0..d1ec44327a 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Layout; using osu.Framework.Localisation; +using osu.Framework.Utils; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; @@ -93,8 +94,7 @@ namespace osu.Game.Online.Leaderboards protected Container RankContainer { get; private set; } = null!; private FillFlowContainer flagBadgeAndDateContainer = null!; - private FillFlowContainer modsContainer = null!; - private OsuSpriteText modsCounter = null!; + private FillFlowContainer modsContainer = null!; private OsuSpriteText scoreText = null!; private Drawable scoreRank = null!; @@ -178,17 +178,23 @@ namespace osu.Game.Online.Leaderboards innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); - if (score.Mods.Length > MAX_MODS) - modsCounter.Text = $"{score.Mods.Length} mods"; - else if (score.Mods.Length > 0) + if (score.Mods.Length > 0) { - modsContainer.ChildrenEnumerable = score.Mods.AsOrdered().Select(mod => new ColouredModSwitchTiny(mod) + modsContainer.Padding = new MarginPadding { Top = 4f }; + modsContainer.ChildrenEnumerable = score.Mods.AsOrdered().Take(Math.Min(MAX_MODS, score.Mods.Length)).Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }); - } - modsContainer.Padding = new MarginPadding { Top = score.Mods.Length > 0 ? 4 : 0 }; + if (score.Mods.Length > MAX_MODS) + { + modsContainer.Remove(modsContainer[^1], true); + modsContainer.Add(new MoreModSwitchTiny(score.Mods.Length - MAX_MODS + 1) + { + Scale = new Vector2(0.375f), + }); + } + } } private Container createCentreContent(APIUser user) => new Container @@ -436,7 +442,7 @@ namespace osu.Game.Online.Leaderboards Current = scoreManager.GetBindableTotalScoreString(score), Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), }, - modsContainer = new FillFlowContainer + modsContainer = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -445,13 +451,6 @@ namespace osu.Game.Online.Leaderboards Direction = FillDirection.Horizontal, Spacing = new Vector2(2f, 0f), }, - modsCounter = new OsuSpriteText - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -shear, - Alpha = 0, - } } } } @@ -495,8 +494,7 @@ namespace osu.Game.Online.Leaderboards using (BeginDelayedSequence(50)) { - Drawable modsDrawable = score.Mods.Length > MAX_MODS ? modsCounter : modsContainer; - var drawables = new[] { flagBadgeAndDateContainer, modsDrawable }.Concat(statisticsLabels).ToArray(); + var drawables = new Drawable[] { flagBadgeAndDateContainer, modsContainer }.Concat(statisticsLabels).ToArray(); for (int i = 0; i < drawables.Length; i++) drawables[i].FadeIn(100 + i * 50); } @@ -652,20 +650,54 @@ namespace osu.Game.Online.Leaderboards { this.mod = mod; Active.Value = true; - Masking = true; - EdgeEffect = new EdgeEffectParameters - { - Roundness = 15, - Type = EdgeEffectType.Shadow, - Colour = Colour4.Black.Opacity(0.15f), - Radius = 3, - Offset = new Vector2(-2, 0) - }; } public LocalisableString TooltipText => (mod as Mod)?.IconTooltip ?? mod.Name; } + private sealed partial class MoreModSwitchTiny : CompositeDrawable + { + private readonly int count; + + public MoreModSwitchTiny(int count) + { + this.count = count; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Size = new Vector2(ModSwitchTiny.WIDTH, ModSwitchTiny.DEFAULT_HEIGHT); + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f), + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Shadow = false, + Font = OsuFont.Numeric.With(size: 24, weight: FontWeight.Black), + Text = $"+{count}", + Colour = colours.Yellow, + Margin = new MarginPadding + { + Top = 4 + } + } + } + }; + } + } + #endregion public MenuItem[] ContextMenuItems diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index 4d50e702af..4a3bc9e31b 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.UI public BindableBool Active { get; } = new BindableBool(); public const float DEFAULT_HEIGHT = 30; - private const float width = 73; + public const float WIDTH = 73; protected readonly IMod Mod; private readonly bool showExtendedInformation; @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.UI Width = 100 + DEFAULT_HEIGHT / 2, RelativeSizeAxes = Axes.Y, Masking = true, - X = width, + X = WIDTH, Margin = new MarginPadding { Left = -DEFAULT_HEIGHT }, Children = new Drawable[] { @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.UI }, new CircularContainer { - Width = width, + Width = WIDTH, RelativeSizeAxes = Axes.Y, Masking = true, Children = new Drawable[] From d395c854187611eb16baa417fc76166ad99fbef9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 17:09:02 +0300 Subject: [PATCH 75/87] Adjust right content width based on scoring mode --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 37 +-- .../Online/Leaderboards/LeaderboardScoreV2.cs | 250 ++++++++++-------- 2 files changed, 164 insertions(+), 123 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 42407ad2b0..99554492fc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -7,6 +7,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; @@ -15,6 +17,7 @@ using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Tests.Resources; using osu.Game.Users; @@ -27,6 +30,9 @@ namespace osu.Game.Tests.Visual.SongSelect [Cached] private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Resolved] + private OsuConfigManager config { get; set; } = null!; + private FillFlowContainer? fillFlow; private OsuSpriteText? drawWidthText; private float relativeWidth; @@ -41,6 +47,7 @@ namespace osu.Game.Tests.Visual.SongSelect relativeWidth = v; if (fillFlow != null) fillFlow.Width = v; }); + AddToggleStep("toggle scoring mode", v => config.SetValue(OsuSetting.ScoreDisplayMode, v ? ScoringMode.Classic : ScoringMode.Standardised)); } [SetUp] @@ -91,7 +98,8 @@ namespace osu.Game.Tests.Visual.SongSelect Rank = ScoreRank.X, Accuracy = 1, MaxCombo = 244, - TotalScore = 1707827, + TotalScore = RNG.Next(1_800_000, 2_000_000), + MaximumStatistics = { { HitResult.Great, 3000 } }, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -108,7 +116,8 @@ namespace osu.Game.Tests.Visual.SongSelect Rank = ScoreRank.S, Accuracy = 0.1f, MaxCombo = 32040, - TotalScore = 1707827, + TotalScore = RNG.Next(1_200_000, 1_500_000), + MaximumStatistics = { { HitResult.Great, 3000 } }, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -119,13 +128,15 @@ namespace osu.Game.Tests.Visual.SongSelect }, Date = DateTimeOffset.Now.AddMonths(-6), }, + TestResources.CreateTestScoreInfo(), new ScoreInfo { Position = 110000, - Rank = ScoreRank.A, + Rank = ScoreRank.B, Accuracy = 1, MaxCombo = 244, - TotalScore = 17078279, + TotalScore = RNG.Next(1_000_000, 1_200_000), + MaximumStatistics = { { HitResult.Great, 3000 } }, Ruleset = new ManiaRuleset().RulesetInfo, User = new APIUser { @@ -137,10 +148,11 @@ namespace osu.Game.Tests.Visual.SongSelect new ScoreInfo { Position = 110000, - Rank = ScoreRank.A, + Rank = ScoreRank.D, Accuracy = 1, MaxCombo = 244, - TotalScore = 1234567890, + TotalScore = RNG.Next(500_000, 1_000_000), + MaximumStatistics = { { HitResult.Great, 3000 } }, Ruleset = new ManiaRuleset().RulesetInfo, User = new APIUser { @@ -150,21 +162,16 @@ namespace osu.Game.Tests.Visual.SongSelect }, Date = DateTimeOffset.Now, }, - TestResources.CreateTestScoreInfo(), }; - var halfTime = new OsuModHalfTime - { - SpeedChange = - { - Value = 0.99 - } - }; + scores[2].Rank = ScoreRank.A; + scores[2].TotalScore = RNG.Next(120_000, 400_000); + scores[2].MaximumStatistics[HitResult.Great] = 3000; scores[1].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight() }; scores[2].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight(), new OsuModClassic() }; scores[3].Mods = new Mod[] { new OsuModHidden(), new OsuModDoubleTime(), new OsuModHardRock(), new OsuModFlashlight(), new OsuModClassic(), new OsuModDifficultyAdjust() }; - scores[4].Mods = scores[4].BeatmapInfo!.Ruleset.CreateInstance().CreateAllMods().ToArray(); + scores[4].Mods = new ManiaRuleset().CreateAllMods().ToArray(); return scores; } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs index d1ec44327a..a9eb9ae2d1 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs @@ -5,19 +5,19 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Layout; using osu.Framework.Localisation; -using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; @@ -28,6 +28,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Select; @@ -41,18 +42,13 @@ namespace osu.Game.Online.Leaderboards { public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { - /// - /// The maximum number of mods when contracted until the mods display width exceeds the . - /// - public const int MAX_MODS = 5; - - private const float right_content_width = 210; + private const float expanded_right_content_width = 210; private const float grade_width = 40; private const float username_min_width = 125; private const float statistics_regular_min_width = 175; private const float statistics_compact_min_width = 100; private const float rank_label_width = 65; - private const float rank_label_visibility_width_cutoff = rank_label_width + height + username_min_width + statistics_regular_min_width + right_content_width; + private const float rank_label_visibility_width_cutoff = rank_label_width + height + username_min_width + statistics_regular_min_width + expanded_right_content_width; private readonly ScoreInfo score; @@ -92,6 +88,8 @@ namespace osu.Game.Online.Leaderboards private OsuSpriteText nameLabel = null!; private List statisticsLabels = null!; + private Container rightContent = null!; + protected Container RankContainer { get; private set; } = null!; private FillFlowContainer flagBadgeAndDateContainer = null!; private FillFlowContainer modsContainer = null!; @@ -152,7 +150,7 @@ namespace osu.Game.Online.Leaderboards { new Dimension(GridSizeMode.AutoSize), new Dimension(), - new Dimension(GridSizeMode.Absolute, right_content_width), + new Dimension(GridSizeMode.AutoSize), }, Content = new[] { @@ -177,19 +175,51 @@ namespace osu.Game.Online.Leaderboards }; innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); + } + + [Resolved] + private OsuConfigManager config { get; set; } = null!; + + private IBindable scoringMode { get; set; } = null!; + + protected override void LoadComplete() + { + base.LoadComplete(); + + scoringMode = config.GetBindable(OsuSetting.ScoreDisplayMode); + scoringMode.BindValueChanged(s => + { + switch (s.NewValue) + { + case ScoringMode.Standardised: + rightContent.Width = 180f; + break; + + case ScoringMode.Classic: + rightContent.Width = expanded_right_content_width; + break; + } + + updateModDisplay(); + }, true); + } + + private void updateModDisplay() + { + int maxMods = scoringMode.Value == ScoringMode.Standardised ? 4 : 5; if (score.Mods.Length > 0) { modsContainer.Padding = new MarginPadding { Top = 4f }; - modsContainer.ChildrenEnumerable = score.Mods.AsOrdered().Take(Math.Min(MAX_MODS, score.Mods.Length)).Select(mod => new ColouredModSwitchTiny(mod) + modsContainer.ChildrenEnumerable = score.Mods.AsOrdered().Take(Math.Min(maxMods, score.Mods.Length)).Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) }); - if (score.Mods.Length > MAX_MODS) + if (score.Mods.Length > maxMods) { modsContainer.Remove(modsContainer[^1], true); - modsContainer.Add(new MoreModSwitchTiny(score.Mods.Length - MAX_MODS + 1) + modsContainer.Add(new MoreModSwitchTiny(score.Mods.Length - maxMods + 1) { Scale = new Vector2(0.375f), }); @@ -342,121 +372,125 @@ namespace osu.Game.Online.Leaderboards }, }; - private Container createRightContent() => new Container + private Container createRightContent() => rightContent = new Container { Name = @"Right content", - AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Children = new Drawable[] + Child = new Container { - new Container + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = grade_width }, - Child = new Box + new Container { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank)), + Padding = new MarginPadding { Right = grade_width }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank)), + }, }, - }, - new Box - { - RelativeSizeAxes = Axes.Y, - Width = grade_width, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Colour = OsuColour.ForRank(score.Rank), - }, - new TrianglesV2 - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - SpawnRatio = 2, - Velocity = 0.7f, - Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Darken(0.2f)), - }, - RankContainer = new Container - { - Shear = -shear, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - Width = grade_width, - Child = scoreRank = new OsuSpriteText + new Box { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Spacing = new Vector2(-2), - Colour = DrawableRank.GetRankNameColour(score.Rank), - Font = OsuFont.Numeric.With(size: 16), - Text = DrawableRank.GetRankName(score.Rank), - ShadowColour = Color4.Black.Opacity(0.3f), - ShadowOffset = new Vector2(0, 0.08f), - Shadow = true, - UseFullGlyphHeight = false, + RelativeSizeAxes = Axes.Y, + Width = grade_width, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = OsuColour.ForRank(score.Rank), }, - }, - new Container - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Padding = new MarginPadding { Right = grade_width }, - Child = new Container + new TrianglesV2 + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + SpawnRatio = 2, + Velocity = 0.7f, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Darken(0.2f)), + }, + RankContainer = new Container + { + Shear = -shear, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + Width = grade_width, + Child = scoreRank = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(-2), + Colour = DrawableRank.GetRankNameColour(score.Rank), + Font = OsuFont.Numeric.With(size: 16), + Text = DrawableRank.GetRankName(score.Rank), + ShadowColour = Color4.Black.Opacity(0.3f), + ShadowOffset = new Vector2(0, 0.08f), + Shadow = true, + UseFullGlyphHeight = false, + }, + }, + new Container { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, - Masking = true, - CornerRadius = corner_radius, - Children = new Drawable[] + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding { Right = grade_width }, + Child = new Container { - totalScoreBackground = new Box + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Masking = true, + CornerRadius = corner_radius, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = totalScoreBackgroundGradient, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Opacity(0.5f)), - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = corner_radius }, - Children = new Drawable[] + totalScoreBackground = new Box { - scoreText = new OsuSpriteText + RelativeSizeAxes = Axes.Both, + Colour = totalScoreBackgroundGradient, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), OsuColour.ForRank(score.Rank).Opacity(0.5f)), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = corner_radius }, + Children = new Drawable[] { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - UseFullGlyphHeight = false, - Shear = -shear, - Current = scoreManager.GetBindableTotalScoreString(score), - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - }, - modsContainer = new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -shear, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2f, 0f), - }, + scoreText = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + UseFullGlyphHeight = false, + Shear = -shear, + Current = scoreManager.GetBindableTotalScoreString(score), + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), + }, + modsContainer = new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -shear, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2f, 0f), + }, + } } } } } } - } + }, }; protected (CaseTransformableString, LocalisableString DisplayAccuracy)[] GetStatistics(ScoreInfo model) => new[] @@ -542,13 +576,13 @@ namespace osu.Game.Online.Leaderboards else rankLabel.FadeOut(transition_duration, Easing.OutQuint).MoveToX(-rankLabel.DrawWidth, transition_duration, Easing.OutQuint); - if (DrawWidth >= height + username_min_width + statistics_regular_min_width + right_content_width) + if (DrawWidth >= height + username_min_width + statistics_regular_min_width + expanded_right_content_width) { statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); statisticsContainer.Direction = FillDirection.Horizontal; statisticsContainer.ScaleTo(1, transition_duration, Easing.OutQuint); } - else if (DrawWidth >= height + username_min_width + statistics_compact_min_width + right_content_width) + else if (DrawWidth >= height + username_min_width + statistics_compact_min_width + expanded_right_content_width) { statisticsContainer.FadeIn(transition_duration, Easing.OutQuint).MoveToX(0, transition_duration, Easing.OutQuint); statisticsContainer.Direction = FillDirection.Vertical; From 2c18c10ac888f6a590b569e6b4aac2b451d902c3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 17:18:51 +0300 Subject: [PATCH 76/87] Move to `SelectV2` namespace --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 2 +- .../SelectV2}/Leaderboards/LeaderboardScoreV2.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename osu.Game/{Online => Screens/SelectV2}/Leaderboards/LeaderboardScoreV2.cs (99%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index 99554492fc..ce0eeca6f4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -11,7 +11,6 @@ using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Leaderboards; using osu.Game.Overlays; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mods; @@ -19,6 +18,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.SelectV2.Leaderboards; using osu.Game.Tests.Resources; using osu.Game.Users; using osuTK; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs similarity index 99% rename from osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs rename to osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs index a9eb9ae2d1..47b5a692bf 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs @@ -25,6 +25,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; using osu.Game.Overlays; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; @@ -38,7 +39,7 @@ using osu.Game.Utils; using osuTK; using osuTK.Graphics; -namespace osu.Game.Online.Leaderboards +namespace osu.Game.Screens.SelectV2.Leaderboards { public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip { From 91fb5ed74975454f01ced0afaee80e5fe6cf9741 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 25 May 2024 17:28:03 +0300 Subject: [PATCH 77/87] Move toggle step to `SetUpSteps` --- .../Visual/SongSelect/TestSceneLeaderboardScoreV2.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index ce0eeca6f4..d3d388dba3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics.Sprites; @@ -47,7 +48,6 @@ namespace osu.Game.Tests.Visual.SongSelect relativeWidth = v; if (fillFlow != null) fillFlow.Width = v; }); - AddToggleStep("toggle scoring mode", v => config.SetValue(OsuSetting.ScoreDisplayMode, v ? ScoringMode.Classic : ScoringMode.Standardised)); } [SetUp] @@ -81,6 +81,12 @@ namespace osu.Game.Tests.Visual.SongSelect score.Show(); }); + [SetUpSteps] + public void SetUpSteps() + { + AddToggleStep("toggle scoring mode", v => config.SetValue(OsuSetting.ScoreDisplayMode, v ? ScoringMode.Classic : ScoringMode.Standardised)); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From 8e14c24ee3c6e3d8641b7af281423735f4a0252c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 May 2024 00:24:03 -0700 Subject: [PATCH 78/87] Follow slanted flow logic precedent in test See `ModSelectOverlay` components. --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 5 ++-- .../Leaderboards/LeaderboardScoreV2.cs | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index d3d388dba3..c8725fde08 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -63,17 +63,16 @@ namespace osu.Game.Tests.Visual.SongSelect RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 2f), + Shear = LeaderboardScoreV2.SHEAR }, drawWidthText = new OsuSpriteText(), }; - int i = 0; - foreach (var scoreInfo in getTestScores()) { fillFlow.Add(new LeaderboardScoreV2(scoreInfo, scoreInfo.Position, scoreInfo.User.Id == 2) { - Margin = new MarginPadding { Right = 10f * i, Left = -10f * i++ }, + Shear = Vector2.Zero, }); } diff --git a/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs index 47b5a692bf..0a558186dd 100644 --- a/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs @@ -65,7 +65,8 @@ namespace osu.Game.Screens.SelectV2.Leaderboards private Colour4 backgroundColour; private ColourInfo totalScoreBackgroundGradient; - private static readonly Vector2 shear = new Vector2(0.15f, 0); + // TODO: once https://github.com/ppy/osu/pull/28183 is merged, probably use OsuGame.SHEAR + public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; @@ -112,7 +113,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards this.rank = rank; this.isPersonalBest = isPersonalBest; - Shear = shear; + Shear = SHEAR; RelativeSizeAxes = Axes.X; Height = height; } @@ -245,7 +246,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { RelativeSizeAxes = Axes.Both, User = score.User, - Shear = -shear, + Shear = -SHEAR, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.FromHex(@"222A27").Opacity(1)), @@ -276,7 +277,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(1.1f), - Shear = -shear, + Shear = -SHEAR, RelativeSizeAxes = Axes.Both, }) { @@ -316,7 +317,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { flagBadgeAndDateContainer = new FillFlowContainer { - Shear = -shear, + Shear = -SHEAR, Direction = FillDirection.Horizontal, Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, @@ -340,7 +341,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards nameLabel = new TruncatingSpriteText { RelativeSizeAxes = Axes.X, - Shear = -shear, + Shear = -SHEAR, Text = user.Username, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) } @@ -356,7 +357,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Name = @"Statistics container", Padding = new MarginPadding { Right = 40 }, Spacing = new Vector2(25, 0), - Shear = -shear, + Shear = -SHEAR, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, @@ -414,7 +415,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards }, RankContainer = new Container { - Shear = -shear, + Shear = -SHEAR, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Y, @@ -472,7 +473,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Anchor = Anchor.TopRight, Origin = Anchor.TopRight, UseFullGlyphHeight = false, - Shear = -shear, + Shear = -SHEAR, Current = scoreManager.GetBindableTotalScoreString(score), Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), }, @@ -480,7 +481,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Shear = -shear, + Shear = -SHEAR, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(2f, 0f), @@ -665,7 +666,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Child = new OsuSpriteText { - Shear = -shear, + Shear = -SHEAR, Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true), From 629e7652c0e57639d64ade90ad10b12d64a650d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 7 Jun 2024 09:01:41 +0200 Subject: [PATCH 79/87] Implement flip operations in mania editor --- .../Edit/ManiaSelectionHandler.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 8fdbada04f..9ae2112b30 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -16,6 +17,16 @@ namespace osu.Game.Rulesets.Mania.Edit [Resolved] private HitObjectComposer composer { get; set; } = null!; + protected override void OnSelectionChanged() + { + base.OnSelectionChanged(); + + var selectedObjects = SelectedItems.OfType().ToArray(); + + SelectionBox.CanFlipX = canFlipX(selectedObjects); + SelectionBox.CanFlipY = canFlipY(selectedObjects); + } + public override bool HandleMovement(MoveSelectionEvent moveEvent) { var hitObjectBlueprint = (HitObjectSelectionBlueprint)moveEvent.Blueprint; @@ -26,6 +37,58 @@ namespace osu.Game.Rulesets.Mania.Edit return true; } + public override bool HandleFlip(Direction direction, bool flipOverOrigin) + { + var selectedObjects = SelectedItems.OfType().ToArray(); + var maniaPlayfield = ((ManiaHitObjectComposer)composer).Playfield; + + if (selectedObjects.Length == 0) + return false; + + switch (direction) + { + case Direction.Horizontal: + if (!canFlipX(selectedObjects)) + return false; + + int firstColumn = flipOverOrigin ? 0 : selectedObjects.Min(ho => ho.Column); + int lastColumn = flipOverOrigin ? (int)EditorBeatmap.BeatmapInfo.Difficulty.CircleSize - 1 : selectedObjects.Max(ho => ho.Column); + + EditorBeatmap.PerformOnSelection(hitObject => + { + var maniaObject = (ManiaHitObject)hitObject; + maniaPlayfield.Remove(maniaObject); + maniaObject.Column = firstColumn + (lastColumn - maniaObject.Column); + maniaPlayfield.Add(maniaObject); + }); + + return true; + + case Direction.Vertical: + if (!canFlipY(selectedObjects)) + return false; + + double selectionStartTime = selectedObjects.Min(ho => ho.StartTime); + double selectionEndTime = selectedObjects.Max(ho => ho.GetEndTime()); + + EditorBeatmap.PerformOnSelection(hitObject => + { + hitObject.StartTime = selectionStartTime + (selectionEndTime - hitObject.GetEndTime()); + }); + + return true; + + default: + throw new ArgumentOutOfRangeException(nameof(direction), direction, "Cannot flip over the supplied direction."); + } + } + + private static bool canFlipX(ManiaHitObject[] selectedObjects) + => selectedObjects.Select(ho => ho.Column).Distinct().Count() > 1; + + private static bool canFlipY(ManiaHitObject[] selectedObjects) + => selectedObjects.Length > 1 && selectedObjects.Min(ho => ho.StartTime) < selectedObjects.Max(ho => ho.GetEndTime()); + private void performColumnMovement(int lastColumn, MoveSelectionEvent moveEvent) { var maniaPlayfield = ((ManiaHitObjectComposer)composer).Playfield; From f787a29f49ae8ed8bde13ef0663f3604921c1b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 7 Jun 2024 09:19:17 +0200 Subject: [PATCH 80/87] Add test coverage --- .../Editor/TestSceneManiaSelectionHandler.cs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs new file mode 100644 index 0000000000..b48f579ec0 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaSelectionHandler.cs @@ -0,0 +1,96 @@ +// 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.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual; +using osuTK.Input; + +namespace osu.Game.Rulesets.Mania.Tests.Editor +{ + public partial class TestSceneManiaSelectionHandler : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new ManiaRuleset(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + [Test] + public void TestHorizontalFlipOverSelection() + { + ManiaHitObject first = null!, second = null!, third = null!; + + AddStep("create objects", () => + { + EditorBeatmap.Add(first = new Note { StartTime = 250, Column = 2 }); + EditorBeatmap.Add(second = new HoldNote { StartTime = 750, Duration = 1500, Column = 1 }); + EditorBeatmap.Add(third = new Note { StartTime = 1250, Column = 3 }); + }); + + AddStep("select everything", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("flip horizontally over selection", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("first object stayed in place", () => first.Column, () => Is.EqualTo(2)); + AddAssert("second object flipped", () => second.Column, () => Is.EqualTo(3)); + AddAssert("third object flipped", () => third.Column, () => Is.EqualTo(1)); + } + + [Test] + public void TestHorizontalFlipOverPlayfield() + { + ManiaHitObject first = null!, second = null!, third = null!; + + AddStep("create objects", () => + { + EditorBeatmap.Add(first = new Note { StartTime = 250, Column = 2 }); + EditorBeatmap.Add(second = new HoldNote { StartTime = 750, Duration = 1500, Column = 1 }); + EditorBeatmap.Add(third = new Note { StartTime = 1250, Column = 3 }); + }); + + AddStep("select everything", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("flip horizontally", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Key(Key.H); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + AddAssert("first object flipped", () => first.Column, () => Is.EqualTo(1)); + AddAssert("second object flipped", () => second.Column, () => Is.EqualTo(2)); + AddAssert("third object flipped", () => third.Column, () => Is.EqualTo(0)); + } + + [Test] + public void TestVerticalFlip() + { + ManiaHitObject first = null!, second = null!, third = null!; + + AddStep("create objects", () => + { + EditorBeatmap.Add(first = new Note { StartTime = 250, Column = 2 }); + EditorBeatmap.Add(second = new HoldNote { StartTime = 750, Duration = 1500, Column = 1 }); + EditorBeatmap.Add(third = new Note { StartTime = 1250, Column = 3 }); + }); + + AddStep("select everything", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("flip vertically", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Key(Key.J); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + AddAssert("first object flipped", () => first.StartTime, () => Is.EqualTo(2250)); + AddAssert("second object flipped", () => second.StartTime, () => Is.EqualTo(250)); + AddAssert("third object flipped", () => third.StartTime, () => Is.EqualTo(1250)); + } + } +} From 199d31c0f4f68b1049cd0692d172273f57689bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 7 Jun 2024 09:54:00 +0200 Subject: [PATCH 81/87] Fix test not compiling A little ugly but maybe it'll do... --- .../Gameplay/TestSceneSkinnableRankDisplay.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs index dc8b3d994b..d442e69c61 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableRankDisplay.cs @@ -3,9 +3,11 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; @@ -16,6 +18,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + private Bindable rank => (Bindable)scoreProcessor.Rank; + protected override Drawable CreateDefaultImplementation() => new DefaultRankDisplay(); protected override Drawable CreateLegacyImplementation() => new LegacyRankDisplay(); @@ -23,15 +27,15 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestChangingRank() { - AddStep("Set rank to SS Hidden", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.XH); - AddStep("Set rank to SS", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.X); - AddStep("Set rank to S Hidden", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.SH); - AddStep("Set rank to S", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.S); - AddStep("Set rank to A", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.A); - AddStep("Set rank to B", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.B); - AddStep("Set rank to C", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.C); - AddStep("Set rank to D", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.D); - AddStep("Set rank to F", () => scoreProcessor.Rank.Value = Scoring.ScoreRank.F); + AddStep("Set rank to SS Hidden", () => rank.Value = ScoreRank.XH); + AddStep("Set rank to SS", () => rank.Value = ScoreRank.X); + AddStep("Set rank to S Hidden", () => rank.Value = ScoreRank.SH); + AddStep("Set rank to S", () => rank.Value = ScoreRank.S); + AddStep("Set rank to A", () => rank.Value = ScoreRank.A); + AddStep("Set rank to B", () => rank.Value = ScoreRank.B); + AddStep("Set rank to C", () => rank.Value = ScoreRank.C); + AddStep("Set rank to D", () => rank.Value = ScoreRank.D); + AddStep("Set rank to F", () => rank.Value = ScoreRank.F); } } -} \ No newline at end of file +} From 72890bb9acf9ab6b3733dd0d3ede0ad6961a45a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 7 Jun 2024 09:54:27 +0200 Subject: [PATCH 82/87] Add stable-like animation legacy rank display Just substituting the sprite felt pretty terrible. --- osu.Game/Skinning/LegacyRankDisplay.cs | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 38ece4e5e4..71d487eade 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Scoring; +using osuTK; namespace osu.Game.Skinning { @@ -25,12 +26,38 @@ namespace osu.Game.Skinning { AutoSizeAxes = Axes.Both; - AddInternal(rank = new Sprite()); + AddInternal(rank = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); } protected override void LoadComplete() { - scoreProcessor.Rank.BindValueChanged(v => rank.Texture = source.GetTexture($"ranking-{v.NewValue}-small"), true); + scoreProcessor.Rank.BindValueChanged(v => + { + var texture = source.GetTexture($"ranking-{v.NewValue}-small"); + + rank.Texture = texture; + + if (texture != null) + { + var transientRank = new Sprite + { + Texture = texture, + Blending = BlendingParameters.Additive, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BypassAutoSizeAxes = Axes.Both, + }; + AddInternal(transientRank); + transientRank.FadeOutFromOne(1200, Easing.Out) + .ScaleTo(new Vector2(1.625f), 1200, Easing.Out) + .Expire(); + } + }, true); + FinishTransforms(true); } } -} \ No newline at end of file +} From 366ef64a2c12e1f7f8a1ff7c975fe0fe5ed7ac90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2024 16:54:12 +0800 Subject: [PATCH 83/87] Apply NRT to `UpdateableRank` --- osu.Game/Online/Leaderboards/UpdateableRank.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/UpdateableRank.cs b/osu.Game/Online/Leaderboards/UpdateableRank.cs index 46cfe8ec65..717adee79d 100644 --- a/osu.Game/Online/Leaderboards/UpdateableRank.cs +++ b/osu.Game/Online/Leaderboards/UpdateableRank.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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Scoring; @@ -22,7 +20,7 @@ namespace osu.Game.Online.Leaderboards Rank = rank; } - protected override Drawable CreateDrawable(ScoreRank? rank) + protected override Drawable? CreateDrawable(ScoreRank? rank) { if (rank.HasValue) { From 9c6e707f00454f9370a8ee3b0424903c9c9b917c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2024 17:04:16 +0800 Subject: [PATCH 84/87] Adjust transitions --- .../Online/Leaderboards/UpdateableRank.cs | 28 +++++++++++++++++++ osu.Game/Skinning/LegacyRankDisplay.cs | 4 +-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/UpdateableRank.cs b/osu.Game/Online/Leaderboards/UpdateableRank.cs index 717adee79d..b64fab6861 100644 --- a/osu.Game/Online/Leaderboards/UpdateableRank.cs +++ b/osu.Game/Online/Leaderboards/UpdateableRank.cs @@ -1,14 +1,19 @@ // 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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transforms; using osu.Game.Scoring; namespace osu.Game.Online.Leaderboards { public partial class UpdateableRank : ModelBackedDrawable { + protected override double TransformDuration => 600; + protected override bool TransformImmediately => true; + public ScoreRank? Rank { get => Model; @@ -20,6 +25,16 @@ namespace osu.Game.Online.Leaderboards Rank = rank; } + protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) + { + return base.CreateDelayedLoadWrapper(createContentFunc, timeBeforeLoad) + .With(w => + { + w.Anchor = Anchor.Centre; + w.Origin = Anchor.Centre; + }); + } + protected override Drawable? CreateDrawable(ScoreRank? rank) { if (rank.HasValue) @@ -33,5 +48,18 @@ namespace osu.Game.Online.Leaderboards return null; } + + protected override TransformSequence ApplyShowTransforms(Drawable drawable) + { + drawable.ScaleTo(1); + return base.ApplyShowTransforms(drawable); + } + + protected override TransformSequence ApplyHideTransforms(Drawable drawable) + { + drawable.ScaleTo(1.8f, TransformDuration, Easing.Out); + + return base.ApplyHideTransforms(drawable); + } } } diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 71d487eade..70b5ed0278 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -52,8 +52,8 @@ namespace osu.Game.Skinning BypassAutoSizeAxes = Axes.Both, }; AddInternal(transientRank); - transientRank.FadeOutFromOne(1200, Easing.Out) - .ScaleTo(new Vector2(1.625f), 1200, Easing.Out) + transientRank.FadeOutFromOne(500, Easing.Out) + .ScaleTo(new Vector2(1.625f), 500, Easing.Out) .Expire(); } }, true); From f59d94bba4171a0dff65be3b10f3c9576f00795b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 Jun 2024 22:07:37 +0300 Subject: [PATCH 85/87] Move transitions inside `ScreenFooterButton` and re-use `Content` from base implementation instead The point is to apply the transitions against a container that's inside of `ScreenFooterButton`, because the `ScreenFooterButton` drawable's position is being controlled by the flow container it's contained within, and we cannot apply the transitions on it directly. --- osu.Game/Screens/Footer/ScreenFooter.cs | 54 ++---- osu.Game/Screens/Footer/ScreenFooterButton.cs | 173 +++++++++++------- .../SelectV2/Footer/ScreenFooterButtonMods.cs | 2 +- 3 files changed, 115 insertions(+), 114 deletions(-) diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index d299bf7362..9e0f657e8b 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.cs @@ -97,11 +97,9 @@ namespace osu.Game.Screens.Footer removedButtonsContainer.Add(oldButton); if (buttons.Count > 0) - fadeButtonToLeft(oldButton, i, oldButtons.Length); + makeButtonDisappearToRightAndExpire(oldButton, i, oldButtons.Length); else - fadeButtonToBottom(oldButton, i, oldButtons.Length); - - Scheduler.AddDelayed(() => oldButton.Expire(), oldButton.TopLevelContent.LatestTransformEndTime - Time.Current); + makeButtonDisappearToBottomAndExpire(oldButton, i, oldButtons.Length); } for (int i = 0; i < buttons.Count; i++) @@ -123,52 +121,24 @@ namespace osu.Game.Screens.Footer newButton.OnLoadComplete += _ => { if (oldButtons.Length > 0) - fadeButtonFromRight(newButton, index, buttons.Count, 240); + makeButtonAppearFromLeft(newButton, index, buttons.Count, 240); else - fadeButtonFromBottom(newButton, index); + makeButtonAppearFromBottom(newButton, index); }; } } - private void fadeButtonFromRight(ScreenFooterButton button, int index, int count, float startDelay) - { - button.TopLevelContent - .MoveToX(-300f) - .FadeOut(); + private void makeButtonAppearFromLeft(ScreenFooterButton button, int index, int count, float startDelay) + => button.AppearFromLeft(startDelay + (count - index) * delay_per_button); - button.TopLevelContent - .Delay(startDelay + (count - index) * delay_per_button) - .MoveToX(0f, 240, Easing.OutCubic) - .FadeIn(240, Easing.OutCubic); - } + private void makeButtonAppearFromBottom(ScreenFooterButton button, int index) + => button.AppearFromBottom(index * delay_per_button); - private void fadeButtonFromBottom(ScreenFooterButton button, int index) - { - button.TopLevelContent - .MoveToY(100f) - .FadeOut(); + private void makeButtonDisappearToRightAndExpire(ScreenFooterButton button, int index, int count) + => button.DisappearToRightAndExpire((count - index) * delay_per_button); - button.TopLevelContent - .Delay(index * delay_per_button) - .MoveToY(0f, 240, Easing.OutCubic) - .FadeIn(240, Easing.OutCubic); - } - - private void fadeButtonToLeft(ScreenFooterButton button, int index, int count) - { - button.TopLevelContent - .Delay((count - index) * delay_per_button) - .FadeOut(240, Easing.InOutCubic) - .MoveToX(300f, 360, Easing.InOutCubic); - } - - private void fadeButtonToBottom(ScreenFooterButton button, int index, int count) - { - button.TopLevelContent - .Delay((count - index) * delay_per_button) - .FadeOut(240, Easing.InOutCubic) - .MoveToY(100f, 240, Easing.InOutCubic); - } + private void makeButtonDisappearToBottomAndExpire(ScreenFooterButton button, int index, int count) + => button.DisappearToBottomAndExpire((count - index) * delay_per_button); private void showOverlay(OverlayContainer overlay) { diff --git a/osu.Game/Screens/Footer/ScreenFooterButton.cs b/osu.Game/Screens/Footer/ScreenFooterButton.cs index dda95d1d4c..1e5576e47a 100644 --- a/osu.Game/Screens/Footer/ScreenFooterButton.cs +++ b/osu.Game/Screens/Footer/ScreenFooterButton.cs @@ -69,7 +69,6 @@ namespace osu.Game.Screens.Footer private readonly Box glowBox; private readonly Box flashLayer; - public readonly Container TopLevelContent; public readonly OverlayContainer? Overlay; public ScreenFooterButton(OverlayContainer? overlay = null) @@ -78,89 +77,85 @@ namespace osu.Game.Screens.Footer Size = new Vector2(BUTTON_WIDTH, BUTTON_HEIGHT); - Child = TopLevelContent = new Container + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Container { - new Container + EdgeEffect = new EdgeEffectParameters { - EdgeEffect = new EdgeEffectParameters + Type = EdgeEffectType.Shadow, + Radius = 4, + // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. + Colour = Colour4.Black.Opacity(0.25f), + Offset = new Vector2(0, 2), + }, + Shear = BUTTON_SHEAR, + Masking = true, + CornerRadius = CORNER_RADIUS, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + backgroundBox = new Box { - Type = EdgeEffectType.Shadow, - Radius = 4, - // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. - Colour = Colour4.Black.Opacity(0.25f), - Offset = new Vector2(0, 2), + RelativeSizeAxes = Axes.Both }, - Shear = BUTTON_SHEAR, - Masking = true, - CornerRadius = CORNER_RADIUS, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + glowBox = new Box { - backgroundBox = new Box + RelativeSizeAxes = Axes.Both + }, + // For elements that should not be sheared. + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Shear = -BUTTON_SHEAR, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both - }, - glowBox = new Box - { - RelativeSizeAxes = Axes.Both - }, - // For elements that should not be sheared. - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Shear = -BUTTON_SHEAR, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + TextContainer = new Container { - TextContainer = new Container + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Y = 42, + AutoSizeAxes = Axes.Both, + Child = text = new OsuSpriteText { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Y = 42, - AutoSizeAxes = Axes.Both, - Child = text = new OsuSpriteText - { - // figma design says the size is 16, but due to the issues with font sizes 19 matches better - Font = OsuFont.TorusAlternate.With(size: 19), - AlwaysPresent = true - } - }, - icon = new SpriteIcon - { - Y = 12, - Size = new Vector2(20), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, - } - }, - new Container - { - Shear = -BUTTON_SHEAR, - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre, - Y = -CORNER_RADIUS, - Size = new Vector2(120, 6), - Masking = true, - CornerRadius = 3, - Child = bar = new Box + // figma design says the size is 16, but due to the issues with font sizes 19 matches better + Font = OsuFont.TorusAlternate.With(size: 19), + AlwaysPresent = true + } + }, + icon = new SpriteIcon { - RelativeSizeAxes = Axes.Both, - } - }, - flashLayer = new Box + Y = 12, + Size = new Vector2(20), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + } + }, + new Container + { + Shear = -BUTTON_SHEAR, + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre, + Y = -CORNER_RADIUS, + Size = new Vector2(120, 6), + Masking = true, + CornerRadius = 3, + Child = bar = new Box { RelativeSizeAxes = Axes.Both, - Colour = Colour4.White.Opacity(0.9f), - Blending = BlendingParameters.Additive, - Alpha = 0, - }, + } }, - } + flashLayer = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White.Opacity(0.9f), + Blending = BlendingParameters.Additive, + Alpha = 0, + }, + }, } }; } @@ -230,5 +225,41 @@ namespace osu.Game.Screens.Footer glowBox.FadeColour(ColourInfo.GradientVertical(buttonAccentColour.Opacity(0f), buttonAccentColour.Opacity(0.2f)), 150, Easing.OutQuint); } + + public void AppearFromLeft(double delay) + { + Content.MoveToX(-300f) + .FadeOut() + .Delay(delay) + .MoveToX(0f, 240, Easing.OutCubic) + .FadeIn(240, Easing.OutCubic); + } + + public void AppearFromBottom(double delay) + { + Content.MoveToY(100f) + .FadeOut() + .Delay(delay) + .MoveToY(0f, 240, Easing.OutCubic) + .FadeIn(240, Easing.OutCubic); + } + + public void DisappearToRightAndExpire(double delay) + { + Content.Delay(delay) + .FadeOut(240, Easing.InOutCubic) + .MoveToX(300f, 360, Easing.InOutCubic); + + this.Delay(Content.LatestTransformEndTime - Time.Current).Expire(); + } + + public void DisappearToBottomAndExpire(double delay) + { + Content.Delay(delay) + .FadeOut(240, Easing.InOutCubic) + .MoveToY(100f, 240, Easing.InOutCubic); + + this.Delay(Content.LatestTransformEndTime - Time.Current).Expire(); + } } } diff --git a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs index 4df4116de1..841f0297e8 100644 --- a/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs +++ b/osu.Game/Screens/SelectV2/Footer/ScreenFooterButtonMods.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.SelectV2.Footer Icon = FontAwesome.Solid.ExchangeAlt; AccentColour = colours.Lime1; - TopLevelContent.AddRange(new[] + AddRange(new[] { unrankedBadge = new UnrankedBadge(), modDisplayBar = new Container From 5f8f6caedd0907a1b9cc734c2163c441b2fe2265 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 Jun 2024 22:45:22 +0300 Subject: [PATCH 86/87] Use `OsuGame.SHEAR` --- .../SongSelect/TestSceneLeaderboardScoreV2.cs | 2 +- .../Leaderboards/LeaderboardScoreV2.cs | 23 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs index c8725fde08..0f5eb06df7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.SongSelect RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 2f), - Shear = LeaderboardScoreV2.SHEAR + Shear = new Vector2(OsuGame.SHEAR, 0) }, drawWidthText = new OsuSpriteText(), }; diff --git a/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs index 0a558186dd..804a9d24b7 100644 --- a/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs +++ b/osu.Game/Screens/SelectV2/Leaderboards/LeaderboardScoreV2.cs @@ -65,9 +65,6 @@ namespace osu.Game.Screens.SelectV2.Leaderboards private Colour4 backgroundColour; private ColourInfo totalScoreBackgroundGradient; - // TODO: once https://github.com/ppy/osu/pull/28183 is merged, probably use OsuGame.SHEAR - public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); - [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; @@ -113,7 +110,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards this.rank = rank; this.isPersonalBest = isPersonalBest; - Shear = SHEAR; + Shear = new Vector2(OsuGame.SHEAR, 0); RelativeSizeAxes = Axes.X; Height = height; } @@ -246,7 +243,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { RelativeSizeAxes = Axes.Both, User = score.User, - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.FromHex(@"222A27").Opacity(1)), @@ -277,7 +274,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(1.1f), - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), RelativeSizeAxes = Axes.Both, }) { @@ -317,7 +314,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { flagBadgeAndDateContainer = new FillFlowContainer { - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Direction = FillDirection.Horizontal, Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, @@ -341,7 +338,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards nameLabel = new TruncatingSpriteText { RelativeSizeAxes = Axes.X, - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Text = user.Username, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) } @@ -357,7 +354,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Name = @"Statistics container", Padding = new MarginPadding { Right = 40 }, Spacing = new Vector2(25, 0), - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, @@ -415,7 +412,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards }, RankContainer = new Container { - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Y, @@ -473,7 +470,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Anchor = Anchor.TopRight, Origin = Anchor.TopRight, UseFullGlyphHeight = false, - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Current = scoreManager.GetBindableTotalScoreString(score), Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), }, @@ -481,7 +478,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(2f, 0f), @@ -666,7 +663,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards Child = new OsuSpriteText { - Shear = -SHEAR, + Shear = new Vector2(-OsuGame.SHEAR, 0), Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true), From 642095b07b812d3ea90acb334218ea8b08f773ea Mon Sep 17 00:00:00 2001 From: Olle Kelderman Date: Sun, 9 Jun 2024 21:42:37 +0200 Subject: [PATCH 87/87] On the mappool screen the auto-pick map logic on map change still assumed 1 ban per team. Now it listens to the BanCount value from the round --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 665d3c131a..e8b6bdad9f 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -123,7 +123,12 @@ namespace osu.Game.Tournament.Screens.MapPool private void beatmapChanged(ValueChangedEvent beatmap) { - if (CurrentMatch.Value == null || CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) + if (CurrentMatch.Value?.Round.Value == null) + return; + + int totalBansRequired = CurrentMatch.Value.Round.Value.BanCount.Value * 2; + + if (CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < totalBansRequired) return; // if bans have already been placed, beatmap changes result in a selection being made automatically