From af248457b02b9380c49dc09d8dd2085b9ebe7766 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 22:49:04 +0300 Subject: [PATCH 01/52] Implement OverlayRulesetSelector --- .../TestSceneOverlayRulesetSelector.cs | 68 +++++++++++++ osu.Game/Overlays/OverlayRulesetSelector.cs | 44 +++++++++ osu.Game/Overlays/OverlayRulesetTabItem.cs | 98 +++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs create mode 100644 osu.Game/Overlays/OverlayRulesetSelector.cs create mode 100644 osu.Game/Overlays/OverlayRulesetTabItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs new file mode 100644 index 0000000000..6c921b13b4 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -0,0 +1,68 @@ +// 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.Graphics; +using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Taiko; +using osu.Framework.Bindables; +using osu.Game.Overlays; +using osu.Game.Rulesets; +using NUnit.Framework; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOverlayRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlayRulesetSelector), + typeof(OverlayRulesetTabItem), + }; + + private readonly OverlayRulesetSelector selector; + private readonly Bindable ruleset = new Bindable(); + + public TestSceneOverlayRulesetSelector() + { + Add(selector = new OverlayRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = ruleset, + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + selector.AccentColour = colours.Lime; + } + + [Test] + public void TestSelection() + { + var osuRuleset = new OsuRuleset().RulesetInfo; + var maniaRuleset = new ManiaRuleset().RulesetInfo; + var taikoRuleset = new TaikoRuleset().RulesetInfo; + var catchRuleset = new CatchRuleset().RulesetInfo; + + AddStep("Select osu!", () => ruleset.Value = osuRuleset); + AddAssert("Check osu! selected", () => selector.Current.Value == osuRuleset); + + AddStep("Select mania", () => ruleset.Value = maniaRuleset); + AddAssert("Check mania selected", () => selector.Current.Value == maniaRuleset); + + AddStep("Select taiko", () => ruleset.Value = taikoRuleset); + AddAssert("Check taiko selected", () => selector.Current.Value == taikoRuleset); + + AddStep("Select catch", () => ruleset.Value = catchRuleset); + AddAssert("Check catch selected", () => selector.Current.Value == catchRuleset); + } + } +} diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs new file mode 100644 index 0000000000..1dcfc97562 --- /dev/null +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -0,0 +1,44 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; +using System.Linq; + +namespace osu.Game.Overlays +{ + public class OverlayRulesetSelector : RulesetSelector + { + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + foreach (var i in TabContainer.Children.OfType()) + i.AccentColour = value; + } + } + + public OverlayRulesetSelector() + { + AutoSizeAxes = Axes.Both; + } + + protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(25, 0), + }; + } +} diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs new file mode 100644 index 0000000000..9d6d28a81f --- /dev/null +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -0,0 +1,98 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK.Graphics; +using osuTK; + +namespace osu.Game.Overlays +{ + public class OverlayRulesetTabItem : TabItem, IHasAccentColour + { + protected readonly OsuSpriteText Text; + private readonly FillFlowContainer content; + + public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + UpdateState(); + } + } + + protected override Container Content => content; + + public OverlayRulesetTabItem(RulesetInfo value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + AddRangeInternal(new Drawable[] + { + content = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Child = Text = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = value.Name, + } + }, + new HoverClickSounds() + }); + + Enabled.Value = true; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Enabled.BindValueChanged(_ => UpdateState(), true); + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + UpdateState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + UpdateState(); + } + + protected override void OnActivated() => UpdateState(); + + protected override void OnDeactivated() => UpdateState(); + + protected virtual void UpdateState() + { + Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); + Text.FadeColour(GetColour(), 120, Easing.OutQuint); + } + + protected Color4 GetColour() => IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; + } +} From b016238c16f8ac0d8e2c6e97d1e2559c6c58930e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 22:55:28 +0300 Subject: [PATCH 02/52] Make ProfileRulesetSelector inherit from OverlayRulesetSelector --- .../Online/TestSceneProfileRulesetSelector.cs | 2 +- .../Components/ProfileRulesetSelector.cs | 33 +------ .../Components/ProfileRulesetTabItem.cs | 97 +++---------------- 3 files changed, 20 insertions(+), 112 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index 1f5ba67e03..a36b6880d2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online public TestSceneProfileRulesetSelector() { ProfileRulesetSelector selector; - Bindable user = new Bindable(); + var user = new Bindable(); Child = selector = new ProfileRulesetSelector { diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 2c9a3dd5f9..e63102f989 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -3,37 +3,21 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Rulesets; using osu.Game.Users; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetSelector : RulesetSelector + public class ProfileRulesetSelector : OverlayRulesetSelector { - private Color4 accentColour = Color4.White; - public readonly Bindable User = new Bindable(); - public ProfileRulesetSelector() - { - TabContainer.Masking = false; - TabContainer.Spacing = new Vector2(10, 0); - AutoSizeAxes = Axes.Both; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { - accentColour = colours.Seafoam; - - foreach (TabItem tabItem in TabContainer) - ((ProfileRulesetTabItem)tabItem).AccentColour = accentColour; + AccentColour = colours.Seafoam; } protected override void LoadComplete() @@ -45,19 +29,10 @@ namespace osu.Game.Overlays.Profile.Header.Components public void SetDefaultRuleset(RulesetInfo ruleset) { - foreach (TabItem tabItem in TabContainer) + foreach (var tabItem in TabContainer) ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID; } - protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value) - { - AccentColour = accentColour - }; - - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - }; + protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value); } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index b5170ea3a2..adf324b259 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -2,38 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetTabItem : TabItem, IHasAccentColour + public class ProfileRulesetTabItem : OverlayRulesetTabItem { - private readonly OsuSpriteText text; private readonly SpriteIcon icon; - private Color4 accentColour; - - public Color4 AccentColour + public new Color4 AccentColour { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateState(); - } + get => base.AccentColour; + set => base.AccentColour = icon.Colour = value; } private bool isDefault; @@ -55,71 +38,21 @@ namespace osu.Game.Overlays.Profile.Header.Components public ProfileRulesetTabItem(RulesetInfo value) : base(value) { - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] + Add(icon = new SpriteIcon { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), - Children = new Drawable[] - { - text = new OsuSpriteText - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Text = value.Name, - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0, - AlwaysPresent = true, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(12), - }, - } - }, - new HoverClickSounds() - }; + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + AlwaysPresent = true, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }); } - protected override bool OnHover(HoverEvent e) + protected override void UpdateState() { - base.OnHover(e); - updateState(); - return true; - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - updateState(); - } - - protected override void OnActivated() => updateState(); - - protected override void OnDeactivated() => updateState(); - - private void updateState() - { - text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - - if (IsHovered || Active.Value) - { - text.FadeColour(Color4.White, 120, Easing.InQuad); - icon.FadeColour(Color4.White, 120, Easing.InQuad); - } - else - { - text.FadeColour(AccentColour, 120, Easing.InQuad); - icon.FadeColour(AccentColour, 120, Easing.InQuad); - } + base.UpdateState(); + icon.FadeColour(GetColour(), 120, Easing.OutQuint); } } } From 2d6a07e970420893feea193e778f1ff3cc28e4f9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 23:14:26 +0300 Subject: [PATCH 03/52] Fix OverlayRulesetSelector don't have default colour --- .../TestSceneOverlayRulesetSelector.cs | 35 +++++++++---------- osu.Game/Overlays/OverlayRulesetSelector.cs | 8 +++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index 6c921b13b4..93aa414c94 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -25,6 +25,9 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(OverlayRulesetTabItem), }; + [Resolved] + private OsuColour colours { get; set; } + private readonly OverlayRulesetSelector selector; private readonly Bindable ruleset = new Bindable(); @@ -38,31 +41,27 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - selector.AccentColour = colours.Lime; - } - [Test] public void TestSelection() { - var osuRuleset = new OsuRuleset().RulesetInfo; - var maniaRuleset = new ManiaRuleset().RulesetInfo; - var taikoRuleset = new TaikoRuleset().RulesetInfo; - var catchRuleset = new CatchRuleset().RulesetInfo; + AddStep("Select osu!", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddAssert("Check osu! selected", () => selector.Current.Value.Equals(new OsuRuleset().RulesetInfo)); - AddStep("Select osu!", () => ruleset.Value = osuRuleset); - AddAssert("Check osu! selected", () => selector.Current.Value == osuRuleset); + AddStep("Select mania", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddAssert("Check mania selected", () => selector.Current.Value.Equals(new ManiaRuleset().RulesetInfo)); - AddStep("Select mania", () => ruleset.Value = maniaRuleset); - AddAssert("Check mania selected", () => selector.Current.Value == maniaRuleset); + AddStep("Select taiko", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddAssert("Check taiko selected", () => selector.Current.Value.Equals(new TaikoRuleset().RulesetInfo)); - AddStep("Select taiko", () => ruleset.Value = taikoRuleset); - AddAssert("Check taiko selected", () => selector.Current.Value == taikoRuleset); + AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); + } - AddStep("Select catch", () => ruleset.Value = catchRuleset); - AddAssert("Check catch selected", () => selector.Current.Value == catchRuleset); + [Test] + public void TestColours() + { + AddStep("Set colour to blue", () => selector.AccentColour = colours.Blue); + AddAssert("Check colour is blue", () => selector.AccentColour == colours.Blue); } } } diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 1dcfc97562..da49335250 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -32,6 +33,13 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Both; } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + if (accentColour == default) + AccentColour = colours.Pink; + } + protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer From 904b068a15c5bb55629d70c8bb5ca035a1d65649 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 2 Jan 2020 13:18:18 +0300 Subject: [PATCH 04/52] Simplify colour setting for additional elements in OverlayRulesetTabItem --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 23 +++++++++++-------- .../Components/ProfileRulesetTabItem.cs | 13 +---------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index 9d6d28a81f..e1cc1de8de 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osuTK; +using System; namespace osu.Game.Overlays { @@ -33,10 +34,12 @@ namespace osu.Game.Overlays accentColour = value; - UpdateState(); + updateState(); } } + protected Action OnStateUpdated; + protected override Container Content => content; public OverlayRulesetTabItem(RulesetInfo value) @@ -67,32 +70,32 @@ namespace osu.Game.Overlays protected override void LoadComplete() { base.LoadComplete(); - Enabled.BindValueChanged(_ => UpdateState(), true); + Enabled.BindValueChanged(_ => updateState(), true); } protected override bool OnHover(HoverEvent e) { base.OnHover(e); - UpdateState(); + updateState(); return true; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - UpdateState(); + updateState(); } - protected override void OnActivated() => UpdateState(); + protected override void OnActivated() => updateState(); - protected override void OnDeactivated() => UpdateState(); + protected override void OnDeactivated() => updateState(); - protected virtual void UpdateState() + private void updateState() { + var updatedColour = IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - Text.FadeColour(GetColour(), 120, Easing.OutQuint); + Text.FadeColour(updatedColour, 120, Easing.OutQuint); + OnStateUpdated?.Invoke(updatedColour); } - - protected Color4 GetColour() => IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index adf324b259..d416e98b31 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { @@ -13,12 +12,6 @@ namespace osu.Game.Overlays.Profile.Header.Components { private readonly SpriteIcon icon; - public new Color4 AccentColour - { - get => base.AccentColour; - set => base.AccentColour = icon.Colour = value; - } - private bool isDefault; public bool IsDefault @@ -47,12 +40,8 @@ namespace osu.Game.Overlays.Profile.Header.Components Icon = FontAwesome.Solid.Star, Size = new Vector2(12), }); - } - protected override void UpdateState() - { - base.UpdateState(); - icon.FadeColour(GetColour(), 120, Easing.OutQuint); + OnStateUpdated += colour => icon.FadeColour(colour, 120, Easing.OutQuint); } } } From 79a6655e1f6d64cb4246fc197560e607cccbbe87 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 21:02:56 +0300 Subject: [PATCH 05/52] Use bindables for colour updates --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 31 +++++++++---------- .../Components/ProfileRulesetTabItem.cs | 12 +++++-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index e1cc1de8de..bf24895306 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osuTK; -using System; +using osu.Framework.Bindables; namespace osu.Game.Overlays { @@ -22,24 +22,15 @@ namespace osu.Game.Overlays public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; - private Color4 accentColour; + private readonly Bindable accentColour = new Bindable(); + private readonly Bindable currentColour = new Bindable(); public Color4 AccentColour { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateState(); - } + get => accentColour.Value; + set => accentColour.Value = value; } - protected Action OnStateUpdated; - protected override Container Content => content; public OverlayRulesetTabItem(RulesetInfo value) @@ -70,6 +61,9 @@ namespace osu.Game.Overlays protected override void LoadComplete() { base.LoadComplete(); + + currentColour.BindValueChanged(OnCurrentColourChanged); + accentColour.BindValueChanged(_ => updateState()); Enabled.BindValueChanged(_ => updateState(), true); } @@ -92,10 +86,13 @@ namespace osu.Game.Overlays private void updateState() { - var updatedColour = IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - Text.FadeColour(updatedColour, 120, Easing.OutQuint); - OnStateUpdated?.Invoke(updatedColour); + + currentColour.Value = IsHovered || Active.Value + ? Color4.White + : Enabled.Value ? AccentColour : Color4.DimGray; } + + protected virtual void OnCurrentColourChanged(ValueChangedEvent colour) => Text.FadeColour(colour.NewValue, 120, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index d416e98b31..038509d371 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -1,17 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { public class ProfileRulesetTabItem : OverlayRulesetTabItem { - private readonly SpriteIcon icon; - private bool isDefault; public bool IsDefault @@ -28,6 +28,8 @@ namespace osu.Game.Overlays.Profile.Header.Components } } + private readonly SpriteIcon icon; + public ProfileRulesetTabItem(RulesetInfo value) : base(value) { @@ -40,8 +42,12 @@ namespace osu.Game.Overlays.Profile.Header.Components Icon = FontAwesome.Solid.Star, Size = new Vector2(12), }); + } - OnStateUpdated += colour => icon.FadeColour(colour, 120, Easing.OutQuint); + protected override void OnCurrentColourChanged(ValueChangedEvent colour) + { + base.OnCurrentColourChanged(colour); + icon.FadeColour(colour.NewValue, 120, Easing.OutQuint); } } } From bd5140c3fa72b79d8f03b6e1eda6ccbd919e12f8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 21:20:31 +0300 Subject: [PATCH 06/52] Add missing line breaks --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index bf24895306..91cf2d6b96 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -90,7 +90,9 @@ namespace osu.Game.Overlays currentColour.Value = IsHovered || Active.Value ? Color4.White - : Enabled.Value ? AccentColour : Color4.DimGray; + : Enabled.Value + ? AccentColour + : Color4.DimGray; } protected virtual void OnCurrentColourChanged(ValueChangedEvent colour) => Text.FadeColour(colour.NewValue, 120, Easing.OutQuint); From 11e7c8be3f3f3da461a65a22d1be2b5ec8017a7d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 20 Jan 2020 08:34:46 +0300 Subject: [PATCH 07/52] Use colour schemes for OverlayRulesetSelector --- .../Online/TestSceneProfileRulesetSelector.cs | 3 +- .../TestSceneOverlayRulesetSelector.cs | 28 ++++++++++--------- osu.Game/Overlays/OverlayRulesetSelector.cs | 9 ++++-- .../Components/ProfileRulesetSelector.cs | 7 ++--- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index a36b6880d2..1a9dca51c9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Users; using osu.Framework.Bindables; +using osu.Game.Graphics; namespace osu.Game.Tests.Visual.Online { @@ -27,7 +28,7 @@ namespace osu.Game.Tests.Visual.Online ProfileRulesetSelector selector; var user = new Bindable(); - Child = selector = new ProfileRulesetSelector + Child = selector = new ProfileRulesetSelector(OverlayColourScheme.Green) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index 93aa414c94..bc5f66da0b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -13,7 +13,8 @@ using osu.Game.Overlays; using osu.Game.Rulesets; using NUnit.Framework; using osu.Game.Graphics; -using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osuTK; namespace osu.Game.Tests.Visual.UserInterface { @@ -25,19 +26,27 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(OverlayRulesetTabItem), }; - [Resolved] - private OsuColour colours { get; set; } - private readonly OverlayRulesetSelector selector; private readonly Bindable ruleset = new Bindable(); public TestSceneOverlayRulesetSelector() { - Add(selector = new OverlayRulesetSelector + Add(new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = ruleset, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new[] + { + selector = new OverlayRulesetSelector(OverlayColourScheme.Green) { Current = ruleset }, + new OverlayRulesetSelector(OverlayColourScheme.Blue) { Current = ruleset }, + new OverlayRulesetSelector(OverlayColourScheme.Orange) { Current = ruleset }, + new OverlayRulesetSelector(OverlayColourScheme.Pink) { Current = ruleset }, + new OverlayRulesetSelector(OverlayColourScheme.Purple) { Current = ruleset }, + new OverlayRulesetSelector(OverlayColourScheme.Red) { Current = ruleset } + } }); } @@ -56,12 +65,5 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); } - - [Test] - public void TestColours() - { - AddStep("Set colour to blue", () => selector.AccentColour = colours.Blue); - AddAssert("Check colour is blue", () => selector.AccentColour == colours.Blue); - } } } diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index da49335250..b70d6a08f2 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -28,16 +28,19 @@ namespace osu.Game.Overlays } } - public OverlayRulesetSelector() + protected OverlayColourScheme ColourScheme { get; } + + public OverlayRulesetSelector(OverlayColourScheme colourScheme) { + ColourScheme = colourScheme; + AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - if (accentColour == default) - AccentColour = colours.Pink; + AccentColour = colours.ForOverlayElement(ColourScheme, 1, 0.7f); } protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index e63102f989..f7e8d4b1f5 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; @@ -14,16 +13,14 @@ namespace osu.Game.Overlays.Profile.Header.Components { public readonly Bindable User = new Bindable(); - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public ProfileRulesetSelector(OverlayColourScheme colourScheme) + : base(colourScheme) { - AccentColour = colours.Seafoam; } protected override void LoadComplete() { base.LoadComplete(); - User.BindValueChanged(u => SetDefaultRuleset(Rulesets.GetRuleset(u.NewValue?.PlayMode ?? "osu")), true); } From 7cd60e3193a615c4ce71311693762ec6c01aa57e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 26 Jan 2020 17:07:17 +0300 Subject: [PATCH 08/52] Make OverlayRulesetSelector use colour provider --- .../Online/TestSceneProfileRulesetSelector.cs | 8 ++++-- .../TestSceneOverlayRulesetSelector.cs | 27 ++++++++++++++----- osu.Game/Overlays/OverlayRulesetSelector.cs | 10 +++---- .../Components/ProfileRulesetSelector.cs | 6 ----- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index 1a9dca51c9..826624f686 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -11,7 +11,8 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Users; using osu.Framework.Bindables; -using osu.Game.Graphics; +using osu.Game.Overlays; +using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Online { @@ -23,12 +24,15 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileRulesetTabItem), }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + public TestSceneProfileRulesetSelector() { ProfileRulesetSelector selector; var user = new Bindable(); - Child = selector = new ProfileRulesetSelector(OverlayColourScheme.Green) + Child = selector = new ProfileRulesetSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index bc5f66da0b..8a98127793 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -12,9 +12,9 @@ using osu.Framework.Bindables; using osu.Game.Overlays; using osu.Game.Rulesets; using NUnit.Framework; -using osu.Game.Graphics; using osu.Framework.Graphics.Containers; using osuTK; +using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.UserInterface { @@ -40,16 +40,29 @@ namespace osu.Game.Tests.Visual.UserInterface Spacing = new Vector2(0, 5), Children = new[] { - selector = new OverlayRulesetSelector(OverlayColourScheme.Green) { Current = ruleset }, - new OverlayRulesetSelector(OverlayColourScheme.Blue) { Current = ruleset }, - new OverlayRulesetSelector(OverlayColourScheme.Orange) { Current = ruleset }, - new OverlayRulesetSelector(OverlayColourScheme.Pink) { Current = ruleset }, - new OverlayRulesetSelector(OverlayColourScheme.Purple) { Current = ruleset }, - new OverlayRulesetSelector(OverlayColourScheme.Red) { Current = ruleset } + new ColourProvidedContainer(OverlayColourScheme.Green, selector = new OverlayRulesetSelector { Current = ruleset }), + new ColourProvidedContainer(OverlayColourScheme.Blue, new OverlayRulesetSelector { Current = ruleset }), + new ColourProvidedContainer(OverlayColourScheme.Orange, new OverlayRulesetSelector { Current = ruleset }), + new ColourProvidedContainer(OverlayColourScheme.Pink, new OverlayRulesetSelector { Current = ruleset }), + new ColourProvidedContainer(OverlayColourScheme.Purple, new OverlayRulesetSelector { Current = ruleset }), + new ColourProvidedContainer(OverlayColourScheme.Red, new OverlayRulesetSelector { Current = ruleset }), } }); } + private class ColourProvidedContainer : Container + { + [Cached] + private readonly OverlayColourProvider colourProvider; + + public ColourProvidedContainer(OverlayColourScheme colourScheme, OverlayRulesetSelector rulesetSelector) + { + colourProvider = new OverlayColourProvider(colourScheme); + AutoSizeAxes = Axes.Both; + Add(rulesetSelector); + } + } + [Test] public void TestSelection() { diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index b70d6a08f2..0c87686f6f 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -28,19 +28,15 @@ namespace osu.Game.Overlays } } - protected OverlayColourScheme ColourScheme { get; } - - public OverlayRulesetSelector(OverlayColourScheme colourScheme) + public OverlayRulesetSelector() { - ColourScheme = colourScheme; - AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { - AccentColour = colours.ForOverlayElement(ColourScheme, 1, 0.7f); + AccentColour = colourProvider.Highlight1; } protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index f7e8d4b1f5..41a3ee8ad6 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -3,7 +3,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics; using osu.Game.Rulesets; using osu.Game.Users; @@ -13,11 +12,6 @@ namespace osu.Game.Overlays.Profile.Header.Components { public readonly Bindable User = new Bindable(); - public ProfileRulesetSelector(OverlayColourScheme colourScheme) - : base(colourScheme) - { - } - protected override void LoadComplete() { base.LoadComplete(); From 786ed038683f49ebd105b7668da9b95007c4e6d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 29 Jan 2020 21:01:40 +0300 Subject: [PATCH 09/52] Update profile recent activities in line with the web design --- .../Online/TestSceneHistoricalSection.cs | 6 +- .../TestSceneUserProfileRecentSection.cs | 5 + .../Sections/BeatmapMetadataContainer.cs | 2 +- .../Profile/Sections/DrawableProfileRow.cs | 124 ------------------ .../Sections/Recent/DrawableRecentActivity.cs | 78 +++++++---- .../Profile/Sections/Recent/MedalIcon.cs | 3 +- .../PaginatedRecentActivityContainer.cs | 4 +- 7 files changed, 68 insertions(+), 154 deletions(-) delete mode 100644 osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index d3b037f499..5825bc72f7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Overlays; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Historical; using osu.Game.Users; @@ -24,9 +26,11 @@ namespace osu.Game.Tests.Visual.Online typeof(HistoricalSection), typeof(PaginatedMostPlayedBeatmapContainer), typeof(DrawableMostPlayedBeatmap), - typeof(DrawableProfileRow) }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + public TestSceneHistoricalSection() { HistoricalSection section; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index f022425bf6..532aaa9c92 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -5,6 +5,7 @@ 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.Shapes; @@ -12,6 +13,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Recent; @@ -28,6 +30,9 @@ namespace osu.Game.Tests.Visual.Online typeof(MedalIcon) }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + public TestSceneUserProfileRecentSection() { Children = new Drawable[] diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 13b547eed3..67a976fe6f 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Profile.Sections { /// - /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ). + /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row. /// public abstract class BeatmapMetadataContainer : OsuHoverContainer { diff --git a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs deleted file mode 100644 index 03ee29d0c2..0000000000 --- a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs +++ /dev/null @@ -1,124 +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.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Overlays.Profile.Sections -{ - public abstract class DrawableProfileRow : Container - { - private const int fade_duration = 200; - - private Box underscoreLine; - private Box coloredBackground; - private Container background; - - /// - /// A visual element displayed to the left of content. - /// - protected abstract Drawable CreateLeftVisual(); - - protected FillFlowContainer LeftFlowContainer { get; private set; } - protected FillFlowContainer RightFlowContainer { get; private set; } - - protected override Container Content { get; } - - protected DrawableProfileRow() - { - RelativeSizeAxes = Axes.X; - Height = 60; - - Content = new Container - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 0.97f, - }; - } - - [BackgroundDependencyLoader(true)] - private void load(OsuColour colour) - { - InternalChildren = new Drawable[] - { - background = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 3, - Alpha = 0, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(0f, 1f), - Radius = 1f, - Colour = Color4.Black.Opacity(0.2f), - }, - Child = coloredBackground = new Box { RelativeSizeAxes = Axes.Both } - }, - Content, - underscoreLine = new Box - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = 1, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - CreateLeftVisual(), - LeftFlowContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Left = 10 }, - Direction = FillDirection.Vertical, - }, - } - }, - RightFlowContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Direction = FillDirection.Vertical, - }, - }; - - coloredBackground.Colour = underscoreLine.Colour = colour.Gray4; - } - - protected override bool OnClick(ClickEvent e) => true; - - protected override bool OnHover(HoverEvent e) - { - background.FadeIn(fade_duration, Easing.OutQuint); - underscoreLine.FadeOut(fade_duration, Easing.OutQuint); - return true; - } - - protected override void OnHoverLost(HoverLostEvent e) - { - background.FadeOut(fade_duration, Easing.OutQuint); - underscoreLine.FadeIn(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } -} diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 4e856845ac..aef8044b12 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -14,7 +14,7 @@ using osu.Game.Online.Leaderboards; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class DrawableRecentActivity : DrawableProfileRow + public class DrawableRecentActivity : CompositeDrawable { private IAPIProvider api; @@ -28,24 +28,55 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load(IAPIProvider api, OverlayColourProvider colourProvider) { this.api = api; - LeftFlowContainer.Padding = new MarginPadding { Left = 10, Right = 160 }; - - LeftFlowContainer.Add(content = new LinkFlowContainer + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + AddInternal(new GridContainer { - AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - }); - - RightFlowContainer.Add(new DrawableDate(activity.CreatedAt) - { - Font = OsuFont.GetFont(size: 13), - Colour = OsuColour.Gray(0xAA), - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, size: 40), + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = createIcon().With(icon => + { + icon.Anchor = Anchor.Centre; + icon.Origin = Anchor.Centre; + }) + }, + content = new LinkFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }, + new DrawableDate(activity.CreatedAt) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Colour = colourProvider.Foreground1, + } + } + } }); var formatted = createMessage(); @@ -53,36 +84,33 @@ namespace osu.Game.Overlays.Profile.Sections.Recent content.AddLinks(formatted.Text, formatted.Links); } - protected override Drawable CreateLeftVisual() + private Drawable createIcon() { switch (activity.Type) { case RecentActivityType.Rank: return new UpdateableRank(activity.ScoreRank) { - RelativeSizeAxes = Axes.Y, - Width = 60, + RelativeSizeAxes = Axes.X, + Height = 16, FillMode = FillMode.Fit, }; case RecentActivityType.Achievement: return new DelayedLoadWrapper(new MedalIcon(activity.Achievement.Slug) { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, }) { - RelativeSizeAxes = Axes.Y, - Width = 60, + RelativeSizeAxes = Axes.X, + Height = 20 }; default: - return new Container - { - RelativeSizeAxes = Axes.Y, - Width = 60, - FillMode = FillMode.Fit, - }; + return Empty(); } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 4563510046..0c1f8b2e92 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -23,8 +23,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent Child = sprite = new Sprite { - Height = 40, - Width = 40, + RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, }; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 3f9d4dc93e..7a9cce4675 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API; using System.Collections.Generic; +using osuTK; namespace osu.Game.Overlays.Profile.Sections.Recent { @@ -16,7 +17,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent public PaginatedRecentActivityContainer(Bindable user, string header, string missing) : base(user, header, missing) { - ItemsPerPage = 5; + ItemsPerPage = 10; + ItemsContainer.Spacing = new Vector2(0, 5); } protected override APIRequest> CreateRequest() => From ea2f66da1d9d10a9608a87cfed312b46a95afc4d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 10:34:22 +0300 Subject: [PATCH 10/52] Simplify OverlayRulesetTabItem.AccentColour --- osu.Game/Overlays/OverlayRulesetSelector.cs | 23 ----------- osu.Game/Overlays/OverlayRulesetTabItem.cs | 40 ++++++++----------- .../Components/ProfileRulesetTabItem.cs | 17 ++++---- 3 files changed, 27 insertions(+), 53 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 0c87686f6f..b73d38eeb3 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -1,44 +1,21 @@ // 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.UserInterface; -using osu.Game.Graphics; using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; -using System.Linq; namespace osu.Game.Overlays { public class OverlayRulesetSelector : RulesetSelector { - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - foreach (var i in TabContainer.Children.OfType()) - i.AccentColour = value; - } - } - public OverlayRulesetSelector() { AutoSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - AccentColour = colourProvider.Highlight1; - } - protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index 91cf2d6b96..5b53d9d1fa 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -11,27 +11,31 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osuTK; -using osu.Framework.Bindables; +using osu.Framework.Allocation; namespace osu.Game.Overlays { - public class OverlayRulesetTabItem : TabItem, IHasAccentColour + public class OverlayRulesetTabItem : TabItem { protected readonly OsuSpriteText Text; private readonly FillFlowContainer content; - public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; + protected override Container Content => content; - private readonly Bindable accentColour = new Bindable(); - private readonly Bindable currentColour = new Bindable(); + private Color4 accentColour; - public Color4 AccentColour + protected virtual Color4 AccentColour { - get => accentColour.Value; - set => accentColour.Value = value; + get => accentColour; + set + { + accentColour = value; + Text.FadeColour(value, 120, Easing.OutQuint); + } } - protected override Container Content => content; + [Resolved] + private OverlayColourProvider colourProvider { get; set; } public OverlayRulesetTabItem(RulesetInfo value) : base(value) @@ -58,13 +62,10 @@ namespace osu.Game.Overlays Enabled.Value = true; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - base.LoadComplete(); - - currentColour.BindValueChanged(OnCurrentColourChanged); - accentColour.BindValueChanged(_ => updateState()); - Enabled.BindValueChanged(_ => updateState(), true); + updateState(); } protected override bool OnHover(HoverEvent e) @@ -87,14 +88,7 @@ namespace osu.Game.Overlays private void updateState() { Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - - currentColour.Value = IsHovered || Active.Value - ? Color4.White - : Enabled.Value - ? AccentColour - : Color4.DimGray; + AccentColour = IsHovered || Active.Value ? Color4.White : colourProvider.Highlight1; } - - protected virtual void OnCurrentColourChanged(ValueChangedEvent colour) => Text.FadeColour(colour.NewValue, 120, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index 038509d371..3d20fba542 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets; @@ -28,6 +27,16 @@ namespace osu.Game.Overlays.Profile.Header.Components } } + protected override Color4 AccentColour + { + get => base.AccentColour; + set + { + base.AccentColour = value; + icon.FadeColour(value, 120, Easing.OutQuint); + } + } + private readonly SpriteIcon icon; public ProfileRulesetTabItem(RulesetInfo value) @@ -43,11 +52,5 @@ namespace osu.Game.Overlays.Profile.Header.Components Size = new Vector2(12), }); } - - protected override void OnCurrentColourChanged(ValueChangedEvent colour) - { - base.OnCurrentColourChanged(colour); - icon.FadeColour(colour.NewValue, 120, Easing.OutQuint); - } } } From b2c501a4393751eb58cd220400688b5fd52f08dc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 10:54:58 +0300 Subject: [PATCH 11/52] Adjust font size --- .../Profile/Sections/Recent/DrawableRecentActivity.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index aef8044b12..b8b53f6ab6 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -16,6 +16,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { public class DrawableRecentActivity : CompositeDrawable { + private const int font_size = 14; + private IAPIProvider api; private readonly APIRecentActivity activity; @@ -62,7 +64,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent icon.Origin = Anchor.Centre; }) }, - content = new LinkFlowContainer + content = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: font_size)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -74,6 +76,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Colour = colourProvider.Foreground1, + Font = OsuFont.GetFont(size: font_size), } } } From 2f7076f91c15b21896a92c08b2c3c86969e13a35 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 11:16:58 +0300 Subject: [PATCH 12/52] Adjust icons size --- .../Profile/Sections/Recent/DrawableRecentActivity.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index b8b53f6ab6..0387f79131 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent AutoSizeAxes = Axes.Y, ColumnDimensions = new[] { - new Dimension(GridSizeMode.Absolute, size: 40), + new Dimension(GridSizeMode.Absolute, size: 28), new Dimension(), new Dimension(GridSizeMode.AutoSize) }, @@ -95,8 +95,9 @@ namespace osu.Game.Overlays.Profile.Sections.Recent return new UpdateableRank(activity.ScoreRank) { RelativeSizeAxes = Axes.X, - Height = 16, + Height = 11, FillMode = FillMode.Fit, + Margin = new MarginPadding { Top = 2 } }; case RecentActivityType.Achievement: @@ -109,7 +110,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent }) { RelativeSizeAxes = Axes.X, - Height = 20 + Width = 0.5f, + Height = 18 }; default: From 7bf2e9b36989dddd793b997fef8a254e993ee9a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 17:37:52 +0900 Subject: [PATCH 13/52] Decouple ModSelectOverlay from global SelectedMods --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 5 ++--- osu.Game/Screens/Select/SongSelect.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 38f5d54714..6afe398172 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Mods protected readonly Container ModSettingsContainer; - protected readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); + public readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); private Bindable>> availableMods; @@ -321,14 +321,13 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, Bindable> selectedMods, OsuGameBase osu) + private void load(OsuColour colours, AudioManager audio, OsuGameBase osu) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; UnrankedLabel.Colour = colours.Blue; availableMods = osu.AvailableMods.GetBoundCopy(); - SelectedMods.BindTo(selectedMods); sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 74a4aea033..018c487250 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -75,6 +75,9 @@ namespace osu.Game.Screens.Select [Resolved(canBeNull: true)] private NotificationOverlay notificationOverlay { get; set; } + [Resolved] + private Bindable> selectedMods { get; set; } + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected BeatmapCarousel Carousel { get; private set; } @@ -468,6 +471,8 @@ namespace osu.Game.Screens.Select this.FadeInFromZero(250); FilterControl.Activate(); + + ModSelect.SelectedMods.BindTo(selectedMods); } private const double logo_transition = 250; @@ -508,6 +513,12 @@ namespace osu.Game.Screens.Select public override void OnResuming(IScreen last) { + base.OnResuming(last); + + // required due to https://github.com/ppy/osu-framework/issues/3218 + ModSelect.SelectedMods.Disabled = false; + ModSelect.SelectedMods.BindTo(selectedMods); + BeatmapDetails.Leaderboard.RefreshScores(); Beatmap.Value.Track.Looping = true; @@ -532,6 +543,7 @@ namespace osu.Game.Screens.Select public override void OnSuspending(IScreen next) { + ModSelect.SelectedMods.UnbindFrom(selectedMods); ModSelect.Hide(); BeatmapOptions.Hide(); From bc21e30b09ef42fa17f8297a58bab4873181a100 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 17:35:54 +0900 Subject: [PATCH 14/52] Allow specifying a valid list of types to performFromMenu --- osu.Game/OsuGame.cs | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ff46c6d849..f54e6c02af 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -327,10 +327,10 @@ namespace osu.Game return; } - performFromMainMenu(() => + performFromScreen(screen => { // we might already be at song select, so a check is required before performing the load to solo. - if (menuScreen.IsCurrentScreen()) + if (screen is MainMenu) menuScreen.LoadToSolo(); // we might even already be at the song @@ -344,7 +344,7 @@ namespace osu.Game Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); - }, $"load {beatmap}", bypassScreenAllowChecks: true, targetScreen: typeof(PlaySongSelect)); + }, $"load {beatmap}", bypassScreenAllowChecks: true, validScreens: new[] { typeof(PlaySongSelect) }); } /// @@ -381,11 +381,11 @@ namespace osu.Game return; } - performFromMainMenu(() => + performFromScreen(screen => { Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - menuScreen.Push(new ReplayPlayerLoader(databasedScore)); + screen.Push(new ReplayPlayerLoader(databasedScore)); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } @@ -441,17 +441,20 @@ namespace osu.Game private ScheduledDelegate performFromMainMenuTask; /// - /// Perform an action only after returning to the main menu. + /// Perform an action only after returning to a specific screen specification. /// Eagerly tries to exit the current screen until it succeeds. /// /// The action to perform once we are in the correct state. /// The task name to display in a notification (if we can't immediately reach the main menu state). - /// An optional target screen type. If this screen is already current we can immediately perform the action without returning to the menu. + /// An optional collection of valid screen types. If any of these screens are already current we can immediately perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. /// Whether checking should be bypassed. - private void performFromMainMenu(Action action, string taskName, Type targetScreen = null, bool bypassScreenAllowChecks = false) + private void performFromScreen(Action action, string taskName, IEnumerable validScreens = null, bool bypassScreenAllowChecks = false) { performFromMainMenuTask?.Cancel(); + validScreens ??= Enumerable.Empty(); + validScreens = validScreens.Append(typeof(MainMenu)); + // if the current screen does not allow screen changing, give the user an option to try again later. if (!bypassScreenAllowChecks && (ScreenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false) { @@ -460,7 +463,7 @@ namespace osu.Game Text = $"Click here to {taskName}", Activated = () => { - performFromMainMenu(action, taskName, targetScreen, true); + performFromScreen(action, taskName, validScreens, true); return true; } }); @@ -471,23 +474,27 @@ namespace osu.Game CloseAllOverlays(false); // we may already be at the target screen type. - if (targetScreen != null && ScreenStack.CurrentScreen?.GetType() == targetScreen) + if (validScreens.Contains(ScreenStack.CurrentScreen?.GetType()) && !Beatmap.Disabled) { - action(); + action(ScreenStack.CurrentScreen); return; } - // all conditions have been met to continue with the action. - if (menuScreen?.IsCurrentScreen() == true && !Beatmap.Disabled) + // find closest valid target + IScreen screen = ScreenStack.CurrentScreen; + + while (screen != null) { - action(); - return; + if (validScreens.Contains(screen.GetType())) + { + screen.MakeCurrent(); + break; + } + + screen = screen.GetParentScreen(); } - // menuScreen may not be initialised yet (null check required). - menuScreen?.MakeCurrent(); - - performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); + performFromMainMenuTask = Schedule(() => performFromScreen(action, taskName, validScreens)); } /// From f637e0e5a73c356cccf03580cee858c9a737996f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 18:08:34 +0900 Subject: [PATCH 15/52] Remove unused bypassScreenAllowChecks argument --- osu.Game/OsuGame.cs | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f54e6c02af..374bacde00 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -344,7 +344,7 @@ namespace osu.Game Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); - }, $"load {beatmap}", bypassScreenAllowChecks: true, validScreens: new[] { typeof(PlaySongSelect) }); + }, $"load {beatmap}", validScreens: new[] { typeof(PlaySongSelect) }); } /// @@ -386,7 +386,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); screen.Push(new ReplayPlayerLoader(databasedScore)); - }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); + }, $"watch {databasedScoreInfo}"); } protected virtual Loader CreateLoader() => new Loader(); @@ -447,30 +447,13 @@ namespace osu.Game /// The action to perform once we are in the correct state. /// The task name to display in a notification (if we can't immediately reach the main menu state). /// An optional collection of valid screen types. If any of these screens are already current we can immediately perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. - /// Whether checking should be bypassed. - private void performFromScreen(Action action, string taskName, IEnumerable validScreens = null, bool bypassScreenAllowChecks = false) + private void performFromScreen(Action action, string taskName, IEnumerable validScreens = null) { performFromMainMenuTask?.Cancel(); validScreens ??= Enumerable.Empty(); validScreens = validScreens.Append(typeof(MainMenu)); - // if the current screen does not allow screen changing, give the user an option to try again later. - if (!bypassScreenAllowChecks && (ScreenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false) - { - notifications.Post(new SimpleNotification - { - Text = $"Click here to {taskName}", - Activated = () => - { - performFromScreen(action, taskName, validScreens, true); - return true; - } - }); - - return; - } - CloseAllOverlays(false); // we may already be at the target screen type. From 8e0d51766b3c9ca8e90e9ba74f45f0e0c45a4360 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 18:10:19 +0900 Subject: [PATCH 16/52] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 5497a82a7a..a31db201b2 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0ea558bbc7..6c3aea04a1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a215bc65e8..6f9d27a93a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 0975002ef503841177a69bc6c5bccc3a80465fef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 18:16:28 +0900 Subject: [PATCH 17/52] Allow presenting scores from PlaySongSelect --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 374bacde00..597b318c90 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -386,7 +386,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); screen.Push(new ReplayPlayerLoader(databasedScore)); - }, $"watch {databasedScoreInfo}"); + }, $"watch {databasedScoreInfo}", new[] { typeof(PlaySongSelect) }); } protected virtual Loader CreateLoader() => new Loader(); From 29ba82ee448ecab176c603ea4582e0edf3021912 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 12:29:35 +0300 Subject: [PATCH 18/52] Apply different font styles for different content parts --- .../Sections/Recent/DrawableRecentActivity.cs | 80 ++++++++++++------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 0387f79131..e9377bb00b 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API; @@ -82,9 +83,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } }); - var formatted = createMessage(); - - content.AddLinks(formatted.Text, formatted.Links); + createMessage(); } private Drawable createIcon() @@ -119,81 +118,106 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } } - private string toAbsoluteUrl(string url) => $"{api.Endpoint}{url}"; + private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument; - private MessageFormatter.MessageFormatterResult createMessage() + private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) + => OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true); + + private void addUserLink() + => content.AddLink(activity.User?.Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User?.Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold)); + + private void addBeatmapLink() + => content.AddLink(activity.Beatmap?.Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap?.Url), creationParameters: t => t.Font = getLinkFont()); + + private void addBeatmapsetLink() + => content.AddLink(activity.Beatmapset?.Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset?.Url), creationParameters: t => t.Font = getLinkFont()); + + private void addText(string text) + => content.AddText(text, t => t.Font = OsuFont.GetFont(size: font_size, weight: FontWeight.SemiBold)); + + private void createMessage() { - string userLinkTemplate() => $"[{toAbsoluteUrl(activity.User?.Url)} {activity.User?.Username}]"; - string beatmapLinkTemplate() => $"[{toAbsoluteUrl(activity.Beatmap?.Url)} {activity.Beatmap?.Title}]"; - string beatmapsetLinkTemplate() => $"[{toAbsoluteUrl(activity.Beatmapset?.Url)} {activity.Beatmapset?.Title}]"; - - string message; - switch (activity.Type) { case RecentActivityType.Achievement: - message = $"{userLinkTemplate()} unlocked the {activity.Achievement.Name} medal!"; + addUserLink(); + addText($" unlocked the \"{activity.Achievement.Name}\" medal!"); break; case RecentActivityType.BeatmapPlaycount: - message = $"{beatmapLinkTemplate()} has been played {activity.Count} times!"; + addBeatmapLink(); + addText($" has been played {activity.Count} times!"); break; case RecentActivityType.BeatmapsetApprove: - message = $"{beatmapsetLinkTemplate()} has been {activity.Approval.ToString().ToLowerInvariant()}!"; + addBeatmapsetLink(); + addText($" has been {activity.Approval.ToString().ToLowerInvariant()}!"); break; case RecentActivityType.BeatmapsetDelete: - message = $"{beatmapsetLinkTemplate()} has been deleted."; + addBeatmapsetLink(); + addText(" has been deleted."); break; case RecentActivityType.BeatmapsetRevive: - message = $"{beatmapsetLinkTemplate()} has been revived from eternal slumber by {userLinkTemplate()}."; + addBeatmapsetLink(); + addText(" has been revived from eternal slumber by "); + addUserLink(); break; case RecentActivityType.BeatmapsetUpdate: - message = $"{userLinkTemplate()} has updated the beatmap {beatmapsetLinkTemplate()}!"; + addUserLink(); + addText(" has updated the beatmap "); + addBeatmapsetLink(); break; case RecentActivityType.BeatmapsetUpload: - message = $"{userLinkTemplate()} has submitted a new beatmap {beatmapsetLinkTemplate()}!"; + addUserLink(); + addText(" has submitted a new beatmap "); + addBeatmapsetLink(); break; case RecentActivityType.Medal: // apparently this shouldn't exist look at achievement instead (https://github.com/ppy/osu-web/blob/master/resources/assets/coffee/react/profile-page/recent-activity.coffee#L111) - message = string.Empty; break; case RecentActivityType.Rank: - message = $"{userLinkTemplate()} achieved rank #{activity.Rank} on {beatmapLinkTemplate()} ({activity.Mode}!)"; + addUserLink(); + addText($" achieved rank #{activity.Rank} on "); + addBeatmapLink(); + addText($" ({activity.Mode}!)"); break; case RecentActivityType.RankLost: - message = $"{userLinkTemplate()} has lost first place on {beatmapLinkTemplate()} ({activity.Mode}!)"; + addUserLink(); + addText(" has lost first place on "); + addBeatmapLink(); + addText($" ({activity.Mode}!)"); break; case RecentActivityType.UserSupportAgain: - message = $"{userLinkTemplate()} has once again chosen to support osu! - thanks for your generosity!"; + addUserLink(); + addText(" has once again chosen to support osu! - thanks for your generosity!"); break; case RecentActivityType.UserSupportFirst: - message = $"{userLinkTemplate()} has become an osu!supporter - thanks for your generosity!"; + addUserLink(); + addText(" has become an osu!supporter - thanks for your generosity!"); break; case RecentActivityType.UserSupportGift: - message = $"{userLinkTemplate()} has received the gift of osu!supporter!"; + addUserLink(); + addText(" has received the gift of osu!supporter!"); break; case RecentActivityType.UsernameChange: - message = $"{activity.User?.PreviousUsername} has changed their username to {userLinkTemplate()}!"; + addText($"{activity.User?.PreviousUsername} has changed their username to "); + addUserLink(); break; default: - message = string.Empty; break; } - - return MessageFormatter.FormatText(message); } } } From a7a3372a984bd9ad79c3414a4e75d16d883df2b5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 13:01:40 +0300 Subject: [PATCH 19/52] Remove redundant empty switch section --- .../Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index e9377bb00b..d5bdcffeef 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -214,9 +214,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent addText($"{activity.User?.PreviousUsername} has changed their username to "); addUserLink(); break; - - default: - break; } } } From 8e966624e02345c593501f69cabd8c78b34ec384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 19:55:25 +0900 Subject: [PATCH 20/52] Fix regressing tests --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 1 + .../Visual/UserInterface/TestSceneModSettings.cs | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 12ee4ceb2e..cd0ce26ea5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -63,6 +63,7 @@ namespace osu.Game.Tests.Visual.UserInterface RelativeSizeAxes = Axes.X, Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, + SelectedMods = { BindTarget = SelectedMods } }, modDisplay = new ModDisplay diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index e2ce2341e5..a89b4f5ba9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -27,6 +27,13 @@ namespace osu.Game.Tests.Visual.UserInterface private readonly Mod testCustomisableAutoOpenMod = new TestModCustomisable2(); + [SetUp] + public void SetUp() => Schedule(() => + { + SelectedMods.Value = Array.Empty(); + Ruleset.Value = new TestRulesetInfo(); + }); + [Test] public void TestButtonShowsOnCustomisableMod() { @@ -70,13 +77,12 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create mod select", () => { - Ruleset.Value = new TestRulesetInfo(); - Child = modSelect = new TestModSelectOverlay { RelativeSizeAxes = Axes.X, Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, + SelectedMods = { BindTarget = SelectedMods } }; }); } From 3f62c40e709bd1ac2d66abe6f33578fa99ed8aec Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 13:55:50 +0300 Subject: [PATCH 21/52] Increase spacing --- .../Profile/Sections/Recent/PaginatedRecentActivityContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 7a9cce4675..a37f398272 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent : base(user, header, missing) { ItemsPerPage = 10; - ItemsContainer.Spacing = new Vector2(0, 5); + ItemsContainer.Spacing = new Vector2(0, 8); } protected override APIRequest> CreateRequest() => From 3002366e70281b1bc600c741239a529b114ae9f1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 13:56:19 +0300 Subject: [PATCH 22/52] Adjust mode part --- .../Requests/Responses/APIRecentActivity.cs | 31 ++++++++++++++++++- .../Sections/Recent/DrawableRecentActivity.cs | 4 +-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 8695d09570..92b520c36b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -41,8 +41,37 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("count")] public int Count; + public string Mode { get; private set; } + [JsonProperty("mode")] - public string Mode; + private string mode + { + set + { + switch (value) + { + default: + Mode = value; + return; + + case "osu": + Mode = "osu!"; + return; + + case "mania": + Mode = "osu!mania"; + return; + + case "taiko": + Mode = "osu!taiko"; + return; + + case "fruits": + Mode = "osu!catch"; + return; + } + } + } [JsonProperty("beatmap")] public RecentActivityBeatmap Beatmap; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index d5bdcffeef..3f8ab93abd 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -185,14 +185,14 @@ namespace osu.Game.Overlays.Profile.Sections.Recent addUserLink(); addText($" achieved rank #{activity.Rank} on "); addBeatmapLink(); - addText($" ({activity.Mode}!)"); + addText($" ({activity.Mode})"); break; case RecentActivityType.RankLost: addUserLink(); addText(" has lost first place on "); addBeatmapLink(); - addText($" ({activity.Mode}!)"); + addText($" ({activity.Mode})"); break; case RecentActivityType.UserSupportAgain: From 3db4c11f29979057147f0e3589ed3009e917ec13 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 30 Jan 2020 14:05:55 +0300 Subject: [PATCH 23/52] CI fix --- osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 92b520c36b..b416085217 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -41,7 +41,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("count")] public int Count; - public string Mode { get; private set; } + public string Mode; [JsonProperty("mode")] private string mode From 878250056c1dc4096c76c8ace223a6cc202f6787 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 23:34:04 +0900 Subject: [PATCH 24/52] Remove unused parameter --- osu.Game/OsuGame.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 374bacde00..321cb25088 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -327,7 +327,7 @@ namespace osu.Game return; } - performFromScreen(screen => + PerformFromScreen(screen => { // we might already be at song select, so a check is required before performing the load to solo. if (screen is MainMenu) @@ -344,7 +344,7 @@ namespace osu.Game Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); - }, $"load {beatmap}", validScreens: new[] { typeof(PlaySongSelect) }); + }, validScreens: new[] { typeof(PlaySongSelect) }); } /// @@ -381,12 +381,12 @@ namespace osu.Game return; } - performFromScreen(screen => + PerformFromScreen(screen => { Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); screen.Push(new ReplayPlayerLoader(databasedScore)); - }, $"watch {databasedScoreInfo}"); + }); } protected virtual Loader CreateLoader() => new Loader(); @@ -445,9 +445,8 @@ namespace osu.Game /// Eagerly tries to exit the current screen until it succeeds. /// /// The action to perform once we are in the correct state. - /// The task name to display in a notification (if we can't immediately reach the main menu state). /// An optional collection of valid screen types. If any of these screens are already current we can immediately perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. - private void performFromScreen(Action action, string taskName, IEnumerable validScreens = null) + protected void PerformFromScreen(Action action, IEnumerable validScreens = null) { performFromMainMenuTask?.Cancel(); @@ -477,7 +476,7 @@ namespace osu.Game screen = screen.GetParentScreen(); } - performFromMainMenuTask = Schedule(() => performFromScreen(action, taskName, validScreens)); + performFromMainMenuTask = Schedule(() => PerformFromScreen(action, validScreens)); } /// From 6b24b7687f68137c6dfca6fdb10b7121275eba3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jan 2020 23:45:15 +0900 Subject: [PATCH 25/52] Add test coverage --- .../Visual/Navigation/OsuGameTestScene.cs | 11 +++ .../Navigation/TestScenePerformFromScreen.cs | 72 +++++++++++++++++++ .../Navigation/TestSceneScreenNavigation.cs | 19 ++--- 3 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs index 662d9977ba..8d2e4a614d 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs @@ -1,6 +1,8 @@ // 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.Bindables; using osu.Framework.Configuration; @@ -76,6 +78,13 @@ namespace osu.Game.Tests.Visual.Navigation ConfirmAtMainMenu(); } + protected void PushAndConfirm(Func newScreen) + { + Screen screen = null; + AddStep("Push new screen", () => Game.ScreenStack.Push(screen = newScreen())); + AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen == screen && screen.IsLoaded); + } + protected void ConfirmAtMainMenu() => AddUntilStep("Wait for main menu", () => Game.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); public class TestOsuGame : OsuGame @@ -96,6 +105,8 @@ namespace osu.Game.Tests.Visual.Navigation protected override Loader CreateLoader() => new TestLoader(); + public new void PerformFromScreen(Action action, IEnumerable validScreens = null) => base.PerformFromScreen(action, validScreens); + public TestOsuGame(Storage storage, IAPIProvider api) { Storage = storage; diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs new file mode 100644 index 0000000000..75c6a2b733 --- /dev/null +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -0,0 +1,72 @@ +// 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.Game.Screens.Menu; +using osu.Game.Screens.Play; +using osu.Game.Screens.Select; + +namespace osu.Game.Tests.Visual.Navigation +{ + public class TestScenePerformFromScreen : OsuGameTestScene + { + [Test] + public void TestPerformAtMenu() + { + AddAssert("could perform immediately", () => + { + bool actionPerformed = false; + Game.PerformFromScreen(_ => actionPerformed = true); + return actionPerformed; + }); + } + + [Test] + public void TestPerformAtSongSelect() + { + PushAndConfirm(() => new PlaySongSelect()); + + AddAssert("could perform immediately", () => + { + bool actionPerformed = false; + Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(PlaySongSelect) }); + return actionPerformed; + }); + } + + [Test] + public void TestPerformAtMenuFromSongSelect() + { + PushAndConfirm(() => new PlaySongSelect()); + + bool actionPerformed = false; + AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true)); + AddUntilStep("returned to menu", () => Game.ScreenStack.CurrentScreen is MainMenu); + AddAssert("did perform", () => actionPerformed); + } + + [Test] + public void TestPerformAtSongSelectFromPlayerLoader() + { + PushAndConfirm(() => new PlaySongSelect()); + PushAndConfirm(() => new PlayerLoader(() => new Player())); + + bool actionPerformed = false; + AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(PlaySongSelect) })); + AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect); + AddAssert("did perform", () => actionPerformed); + } + + [Test] + public void TestPerformAtMenuFromPlayerLoader() + { + PushAndConfirm(() => new PlaySongSelect()); + PushAndConfirm(() => new PlayerLoader(() => new Player())); + + bool actionPerformed = false; + AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true)); + AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is MainMenu); + AddAssert("did perform", () => actionPerformed); + } + } +} diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index d706d47384..8258cc9465 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -1,13 +1,11 @@ // 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.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; -using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -32,7 +30,7 @@ namespace osu.Game.Tests.Visual.Navigation { TestSongSelect songSelect = null; - pushAndConfirm(() => songSelect = new TestSongSelect()); + PushAndConfirm(() => songSelect = new TestSongSelect()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); pushEscape(); @@ -49,7 +47,7 @@ namespace osu.Game.Tests.Visual.Navigation WorkingBeatmap beatmap() => Game.Beatmap.Value; Track track() => beatmap().Track; - pushAndConfirm(() => new TestSongSelect()); + PushAndConfirm(() => new TestSongSelect()); AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(Game, virtualTrack: true).Wait()); @@ -77,7 +75,7 @@ namespace osu.Game.Tests.Visual.Navigation { TestSongSelect songSelect = null; - pushAndConfirm(() => songSelect = new TestSongSelect()); + PushAndConfirm(() => songSelect = new TestSongSelect()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); @@ -93,14 +91,14 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestExitMultiWithEscape() { - pushAndConfirm(() => new Screens.Multi.Multiplayer()); + PushAndConfirm(() => new Screens.Multi.Multiplayer()); exitViaEscapeAndConfirm(); } [Test] public void TestExitMultiWithBackButton() { - pushAndConfirm(() => new Screens.Multi.Multiplayer()); + PushAndConfirm(() => new Screens.Multi.Multiplayer()); exitViaBackButtonAndConfirm(); } @@ -116,13 +114,6 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden); } - private void pushAndConfirm(Func newScreen) - { - Screen screen = null; - AddStep("Push new screen", () => Game.ScreenStack.Push(screen = newScreen())); - AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen == screen && screen.IsLoaded); - } - private void pushEscape() => AddStep("Press escape", () => pressAndRelease(Key.Escape)); From f51cfa22204c3b4da2ebbd3eb3d32912f11d576f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Jan 2020 00:24:00 +0900 Subject: [PATCH 26/52] Fix too many ticks being displayed on beatmaps with multiple timing sections Closes https://github.com/ppy/osu/issues/7681. --- .../Edit/Compose/Components/Timeline/TimelineTickDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index f9b92c0504..b565a42c5a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = beatmap.ControlPointInfo.TimingPoints.Count < i + 1 ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + var until = beatmap.ControlPointInfo.TimingPoints.Count > i + 1 ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; int beat = 0; From 682d0e6e712984007307e0d3679d23f53da0860b Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 17:46:59 +0100 Subject: [PATCH 27/52] Fix typo in variable --- .../Overlays/Profile/Header/BottomHeaderContainer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index b6c6f33678..aa8b332bd3 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -111,14 +111,14 @@ namespace osu.Game.Overlays.Profile.Header topLinkContainer.AddText("Contributed "); topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); - string websiteWithoutProtcol = user.Website; + string websiteWithoutProtocol = user.Website; - if (!string.IsNullOrEmpty(websiteWithoutProtcol)) + if (!string.IsNullOrEmpty(websiteWithoutProtocol)) { - if (Uri.TryCreate(websiteWithoutProtcol, UriKind.Absolute, out var uri)) + if (Uri.TryCreate(websiteWithoutProtocol, UriKind.Absolute, out var uri)) { - websiteWithoutProtcol = uri.Host + uri.PathAndQuery + uri.Fragment; - websiteWithoutProtcol = websiteWithoutProtcol.TrimEnd('/'); + websiteWithoutProtocol = uri.Host + uri.PathAndQuery + uri.Fragment; + websiteWithoutProtocol = websiteWithoutProtocol.TrimEnd('/'); } } @@ -131,7 +131,7 @@ namespace osu.Game.Overlays.Profile.Header tryAddInfo(FontAwesome.Brands.Discord, user.Discord); tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtcol, user.Website); + tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); From 754200d84358b740f80c744be45018d6968a32f6 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 18:10:40 +0100 Subject: [PATCH 28/52] Fix padding when user has no additional info --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index aa8b332bd3..7531cab024 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -132,6 +132,10 @@ namespace osu.Game.Overlays.Profile.Header tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); + + // Hide the container to prevent adding unnecessary padding if it has no children other than the NewLine + if (!bottomLinkContainer.Children.Skip(1).Any()) + bottomLinkContainer.Hide(); } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); From de9a1737a5f04800c5c1ee2f1dbb9c23a9ffa226 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 18:18:42 +0100 Subject: [PATCH 29/52] Recolour LevelProgressBar --- .../Overlays/Profile/Header/Components/LevelProgressBar.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs index a73ce56a2b..c97df3bc4d 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { InternalChildren = new Drawable[] { @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Header.Components RelativeSizeAxes = Axes.Both, BackgroundColour = Color4.Black, Direction = BarDirection.LeftToRight, - AccentColour = colours.Yellow + AccentColour = colourProvider.Highlight1 } }, levelProgressText = new OsuSpriteText From e69d93ae5c01b90d0a5d6fea4c0aa58bd4f86e2e Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 19:26:42 +0100 Subject: [PATCH 30/52] Adjust ProfileTabControl height --- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 6f0d96c226..045a52a0c7 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Height = 30 + Height = 34 }; Add(new Box From 1751e96840e345d6c51b95eec54dd9f692052807 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 19:45:12 +0100 Subject: [PATCH 31/52] Recolour ProfileHeaderButton --- .../Profile/Header/Components/ProfileHeaderButton.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index ddcf011277..ae94f3485f 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -24,9 +25,6 @@ namespace osu.Game.Overlays.Profile.Header.Components { AutoSizeAxes = Axes.X; - IdleColour = Color4.Black; - HoverColour = OsuColour.Gray(0.1f); - base.Content.Add(new CircularContainer { Masking = true, @@ -47,5 +45,12 @@ namespace osu.Game.Overlays.Profile.Header.Components } }); } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + IdleColour = colourProvider.Background6; + HoverColour = colourProvider.Background5; + } } } From 3970151e31bbc571fbee4b3fe4f7fc159488827f Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 20:51:33 +0100 Subject: [PATCH 32/52] Improve condition check --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 7531cab024..86e816a28c 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Users; using osuTK; using osuTK.Graphics; +using static osu.Framework.Graphics.Containers.TextFlowContainer; namespace osu.Game.Overlays.Profile.Header { @@ -133,9 +134,12 @@ namespace osu.Game.Overlays.Profile.Header tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); - // Hide the container to prevent adding unnecessary padding if it has no children other than the NewLine - if (!bottomLinkContainer.Children.Skip(1).Any()) + // Hide the container to prevent adding unnecessary padding if it has no children other than the NewLineContainer + if (!bottomLinkContainer.Children.Any(child => !(child is NewLineContainer))) bottomLinkContainer.Hide(); + else + // this is needed if user gets changed without the whole header being reloaded + bottomLinkContainer.Show(); } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); From a3877cc29e549999d82bd8e45c2de37e50b2c83d Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 20:55:44 +0100 Subject: [PATCH 33/52] Recolour RankGraph circle --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 250b345db7..aed63293ea 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -167,9 +167,9 @@ namespace osu.Game.Overlays.Profile.Header.Components } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider, OsuColour colours) { - ballBg.Colour = colours.GreySeafoamDarker; + ballBg.Colour = colourProvider.Background5; movingBall.BorderColour = line.Colour = colours.Yellow; } From c38dc815351616ff14ce3b7941ab736d9df18c94 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 21:39:06 +0100 Subject: [PATCH 34/52] Remove unnecessary using --- .../Overlays/Profile/Header/Components/ProfileHeaderButton.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index ae94f3485f..e14d73dd98 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -6,9 +6,7 @@ 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.Graphics.Containers; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { From caf76511a73d8b7b73965bba85b7fa5ebe2ea402 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 21:45:42 +0100 Subject: [PATCH 35/52] Remove double negation --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 86e816a28c..469f9caf4a 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Profile.Header tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); // Hide the container to prevent adding unnecessary padding if it has no children other than the NewLineContainer - if (!bottomLinkContainer.Children.Any(child => !(child is NewLineContainer))) + if (bottomLinkContainer.Children.All(child => child is NewLineContainer)) bottomLinkContainer.Hide(); else // this is needed if user gets changed without the whole header being reloaded From c050eed79b08e07087e337ac582da48fae0e4470 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Thu, 30 Jan 2020 22:05:06 +0100 Subject: [PATCH 36/52] Recolour RankGraphTooltip --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index aed63293ea..a742711d26 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Users; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { @@ -270,7 +271,8 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.GreySeafoamDark; + // To match osu-web, background and text should both be coloured using OverlayColourProvider + background.Colour = colours.Gray1; } public bool SetContent(object content) From b03e7f12ff0e22b0b7c0279bd27ac75fc79b0bcf Mon Sep 17 00:00:00 2001 From: Tree Date: Thu, 30 Jan 2020 22:51:35 +0100 Subject: [PATCH 37/52] Remove unused directive --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index a742711d26..83c6d80dae 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -16,7 +16,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Users; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { From 9a1907d8e07fe2a3bfa92d71dbe8a4912ebbea1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Jan 2020 09:48:20 +0900 Subject: [PATCH 38/52] Apply doc fixes from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/OsuGame.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 321cb25088..fb3ce00824 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -441,11 +441,11 @@ namespace osu.Game private ScheduledDelegate performFromMainMenuTask; /// - /// Perform an action only after returning to a specific screen specification. + /// Perform an action only after returning to a specific screen as indicated by . /// Eagerly tries to exit the current screen until it succeeds. /// /// The action to perform once we are in the correct state. - /// An optional collection of valid screen types. If any of these screens are already current we can immediately perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. + /// An optional collection of valid screen types. If any of these screens are already current we can perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. protected void PerformFromScreen(Action action, IEnumerable validScreens = null) { performFromMainMenuTask?.Cancel(); From 90caa612455425f97c892a81be2f37a46066e9f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Feb 2020 02:05:26 +0900 Subject: [PATCH 39/52] Reverse comparison for readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- .../Edit/Compose/Components/Timeline/TimelineTickDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index b565a42c5a..36ee976bf7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) { var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = beatmap.ControlPointInfo.TimingPoints.Count > i + 1 ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; int beat = 0; From 36116f8c45f06ffa0256f6e2ba53a67182a74753 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 2 Feb 2020 12:03:51 +0300 Subject: [PATCH 40/52] Refactor ruleset presentation --- .../TestSceneUserProfileRecentSection.cs | 16 ++++++++++ .../Requests/Responses/APIRecentActivity.cs | 31 +------------------ .../Sections/Recent/DrawableRecentActivity.cs | 26 ++++++++++++---- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index 532aaa9c92..06091f3c81 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -136,6 +136,22 @@ namespace osu.Game.Tests.Visual.Online Beatmap = dummyBeatmap, }, new APIRecentActivity + { + User = dummyUser, + Type = RecentActivityType.Rank, + Rank = 1, + Mode = "vitaru", + Beatmap = dummyBeatmap, + }, + new APIRecentActivity + { + User = dummyUser, + Type = RecentActivityType.Rank, + Rank = 1, + Mode = "fruits", + Beatmap = dummyBeatmap, + }, + new APIRecentActivity { User = dummyUser, Type = RecentActivityType.RankLost, diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index b416085217..8695d09570 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -41,37 +41,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("count")] public int Count; - public string Mode; - [JsonProperty("mode")] - private string mode - { - set - { - switch (value) - { - default: - Mode = value; - return; - - case "osu": - Mode = "osu!"; - return; - - case "mania": - Mode = "osu!mania"; - return; - - case "taiko": - Mode = "osu!taiko"; - return; - - case "fruits": - Mode = "osu!catch"; - return; - } - } - } + public string Mode; [JsonProperty("beatmap")] public RecentActivityBeatmap Beatmap; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 3f8ab93abd..5a315b59b4 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,6 +13,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets; namespace osu.Game.Overlays.Profile.Sections.Recent { @@ -19,7 +21,11 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { private const int font_size = 14; - private IAPIProvider api; + [Resolved] + private IAPIProvider api { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } private readonly APIRecentActivity activity; @@ -31,10 +37,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private void load(IAPIProvider api, OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider) { - this.api = api; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; AddInternal(new GridContainer @@ -118,6 +122,16 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } } + private string getRulesetName() + { + var shortName = activity.Mode; + + if (rulesets.AvailableRulesets.Select(r => r.ShortName).Contains(shortName)) + return rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == shortName).Name; + + return shortName; + } + private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument; private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) @@ -185,14 +199,14 @@ namespace osu.Game.Overlays.Profile.Sections.Recent addUserLink(); addText($" achieved rank #{activity.Rank} on "); addBeatmapLink(); - addText($" ({activity.Mode})"); + addText($" ({getRulesetName()})"); break; case RecentActivityType.RankLost: addUserLink(); addText(" has lost first place on "); addBeatmapLink(); - addText($" ({activity.Mode})"); + addText($" ({getRulesetName()})"); break; case RecentActivityType.UserSupportAgain: From a70385f2b26058cec6da3d7ebb7d150cbe54967c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 2 Feb 2020 12:19:09 +0300 Subject: [PATCH 41/52] Simplify getRulesetName --- .../Profile/Sections/Recent/DrawableRecentActivity.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 5a315b59b4..f538833eb0 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -126,10 +126,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { var shortName = activity.Mode; - if (rulesets.AvailableRulesets.Select(r => r.ShortName).Contains(shortName)) - return rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == shortName).Name; - - return shortName; + return rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == shortName)?.Name ?? shortName; } private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument; From 30a5835bdbc24abc82d09f8e6832d5aa9aaf37a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Feb 2020 23:07:39 +0900 Subject: [PATCH 42/52] Combine link flows and simplify new line addition --- .../Profile/Header/BottomHeaderContainer.cs | 80 ++++++++----------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 469f9caf4a..bca72666de 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -15,7 +15,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using static osu.Framework.Graphics.Containers.TextFlowContainer; namespace osu.Game.Overlays.Profile.Header { @@ -23,8 +22,7 @@ namespace osu.Game.Overlays.Profile.Header { public readonly Bindable User = new Bindable(); - private LinkFlowContainer topLinkContainer; - private LinkFlowContainer bottomLinkContainer; + private LinkFlowContainer linkContainer; private Color4 iconColour; @@ -45,26 +43,12 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4 }, - new FillFlowContainer + linkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, Spacing = new Vector2(0, 10), - Children = new Drawable[] - { - topLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - bottomLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } - } } }; @@ -73,44 +57,43 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - topLinkContainer.Clear(); - bottomLinkContainer.Clear(); + linkContainer.Clear(); if (user == null) return; if (user.JoinDate.ToUniversalTime().Year < 2008) - topLinkContainer.AddText("Here since the beginning"); + linkContainer.AddText("Here since the beginning"); else { - topLinkContainer.AddText("Joined "); - topLinkContainer.AddText(new DrawableDate(user.JoinDate), embolden); + linkContainer.AddText("Joined "); + linkContainer.AddText(new DrawableDate(user.JoinDate), embolden); } - addSpacer(topLinkContainer); + addSpacer(linkContainer); if (user.IsOnline) { - topLinkContainer.AddText("Currently online"); - addSpacer(topLinkContainer); + linkContainer.AddText("Currently online"); + addSpacer(linkContainer); } else if (user.LastVisit.HasValue) { - topLinkContainer.AddText("Last seen "); - topLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); + linkContainer.AddText("Last seen "); + linkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); - addSpacer(topLinkContainer); + addSpacer(linkContainer); } if (user.PlayStyles?.Length > 0) { - topLinkContainer.AddText("Plays with "); - topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); + linkContainer.AddText("Plays with "); + linkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); - addSpacer(topLinkContainer); + addSpacer(linkContainer); } - topLinkContainer.AddText("Contributed "); - topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); + linkContainer.AddText("Contributed "); + linkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); string websiteWithoutProtocol = user.Website; @@ -123,46 +106,51 @@ namespace osu.Game.Overlays.Profile.Header } } + requireNewLineOnAddInfo = true; + tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); tryAddInfo(OsuIcon.Heart, user.Interests); tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); - bottomLinkContainer.NewLine(); + + requireNewLineOnAddInfo = true; + if (!string.IsNullOrEmpty(user.Twitter)) tryAddInfo(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); tryAddInfo(FontAwesome.Brands.Discord, user.Discord); tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); - - // Hide the container to prevent adding unnecessary padding if it has no children other than the NewLineContainer - if (bottomLinkContainer.Children.All(child => child is NewLineContainer)) - bottomLinkContainer.Hide(); - else - // this is needed if user gets changed without the whole header being reloaded - bottomLinkContainer.Show(); } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); + private bool requireNewLineOnAddInfo; + private void tryAddInfo(IconUsage icon, string content, string link = null) { if (string.IsNullOrEmpty(content)) return; + if (requireNewLineOnAddInfo) + { + linkContainer.NewLine(); + requireNewLineOnAddInfo = false; + } + // newlines could be contained in API returned user content. content = content.Replace("\n", " "); - bottomLinkContainer.AddIcon(icon, text => + linkContainer.AddIcon(icon, text => { text.Font = text.Font.With(size: 10); text.Colour = iconColour; }); if (link != null) - bottomLinkContainer.AddLink(" " + content, link, creationParameters: embolden); + linkContainer.AddLink(" " + content, link, creationParameters: embolden); else - bottomLinkContainer.AddText(" " + content, embolden); + linkContainer.AddText(" " + content, embolden); - addSpacer(bottomLinkContainer); + addSpacer(linkContainer); } private void embolden(SpriteText text) => text.Font = text.Font.With(weight: FontWeight.Bold); From 1f53778d623244d17ac616943be992da7710f532 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 2 Feb 2020 16:59:17 +0100 Subject: [PATCH 43/52] Add explanation to comment --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 83c6d80dae..ffc060b3f1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -270,7 +270,8 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - // To match osu-web, background and text should both be coloured using OverlayColourProvider + // Temporary colour since it's currently impossible to change it without bugs (see https://github.com/ppy/osu-framework/issues/3231) + // If above is fixed, this should use OverlayColourProvider background.Colour = colours.Gray1; } From 7e162d9798d7e88fc27cdebe04bcdcc7dbdbd719 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 2 Feb 2020 17:03:41 +0100 Subject: [PATCH 44/52] Fix failing test --- osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index c70cc4ae4e..8f7e7498a9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using NUnit.Framework; +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.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; using osuTK; @@ -24,6 +26,9 @@ namespace osu.Game.Tests.Visual.Online typeof(LineGraph) }; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink); + public TestSceneRankGraph() { RankGraph graph; From 030d02594cc955a19fb1d2a4c2ccb3b8f8243d99 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 2 Feb 2020 17:10:11 +0100 Subject: [PATCH 45/52] Allow non-italic DrawableDate --- osu.Game/Graphics/DrawableDate.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 925c7981e0..0224c77ee8 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -29,9 +29,9 @@ namespace osu.Game.Graphics } } - public DrawableDate(DateTimeOffset date, float textSize = OsuFont.DEFAULT_FONT_SIZE) + public DrawableDate(DateTimeOffset date, float textSize = OsuFont.DEFAULT_FONT_SIZE, bool italic = true) { - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: textSize, italics: true); + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: textSize, italics: italic); Date = date; } From d15942d1270a803947bb4dcf0811560d32efa71a Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 2 Feb 2020 17:21:22 +0100 Subject: [PATCH 46/52] Revert containers merge and rework bottomLinkContainer visibility logic --- .../Profile/Header/BottomHeaderContainer.cs | 101 ++++++++++-------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index bca72666de..065bef8329 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -22,7 +22,8 @@ namespace osu.Game.Overlays.Profile.Header { public readonly Bindable User = new Bindable(); - private LinkFlowContainer linkContainer; + private LinkFlowContainer topLinkContainer; + private LinkFlowContainer bottomLinkContainer; private Color4 iconColour; @@ -43,12 +44,26 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4 }, - linkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + topLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + bottomLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } } }; @@ -57,43 +72,44 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - linkContainer.Clear(); + topLinkContainer.Clear(); + bottomLinkContainer.Clear(); if (user == null) return; if (user.JoinDate.ToUniversalTime().Year < 2008) - linkContainer.AddText("Here since the beginning"); + topLinkContainer.AddText("Here since the beginning"); else { - linkContainer.AddText("Joined "); - linkContainer.AddText(new DrawableDate(user.JoinDate), embolden); + topLinkContainer.AddText("Joined "); + topLinkContainer.AddText(new DrawableDate(user.JoinDate), embolden); } - addSpacer(linkContainer); + addSpacer(topLinkContainer); if (user.IsOnline) { - linkContainer.AddText("Currently online"); - addSpacer(linkContainer); + topLinkContainer.AddText("Currently online"); + addSpacer(topLinkContainer); } else if (user.LastVisit.HasValue) { - linkContainer.AddText("Last seen "); - linkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); + topLinkContainer.AddText("Last seen "); + topLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); - addSpacer(linkContainer); + addSpacer(topLinkContainer); } if (user.PlayStyles?.Length > 0) { - linkContainer.AddText("Plays with "); - linkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); + topLinkContainer.AddText("Plays with "); + topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); - addSpacer(linkContainer); + addSpacer(topLinkContainer); } - linkContainer.AddText("Contributed "); - linkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); + topLinkContainer.AddText("Contributed "); + topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); string websiteWithoutProtocol = user.Website; @@ -106,51 +122,48 @@ namespace osu.Game.Overlays.Profile.Header } } - requireNewLineOnAddInfo = true; - - tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); - tryAddInfo(OsuIcon.Heart, user.Interests); - tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); - - requireNewLineOnAddInfo = true; + bool anyInfoAdded = false; + anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); + anyInfoAdded |= tryAddInfo(OsuIcon.Heart, user.Interests); + anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); + bottomLinkContainer.NewLine(); if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfo(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); - tryAddInfo(FontAwesome.Brands.Discord, user.Discord); - tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); - tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); + anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Discord, user.Discord); + anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); + anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); + anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); + + // If no information was added to the bottomLinkContainer, hide it to avoid unwanted padding + if (anyInfoAdded) + bottomLinkContainer.Show(); + else + bottomLinkContainer.Hide(); } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); - private bool requireNewLineOnAddInfo; - - private void tryAddInfo(IconUsage icon, string content, string link = null) + private bool tryAddInfo(IconUsage icon, string content, string link = null) { - if (string.IsNullOrEmpty(content)) return; - - if (requireNewLineOnAddInfo) - { - linkContainer.NewLine(); - requireNewLineOnAddInfo = false; - } + if (string.IsNullOrEmpty(content)) return false; // newlines could be contained in API returned user content. content = content.Replace("\n", " "); - linkContainer.AddIcon(icon, text => + bottomLinkContainer.AddIcon(icon, text => { text.Font = text.Font.With(size: 10); text.Colour = iconColour; }); if (link != null) - linkContainer.AddLink(" " + content, link, creationParameters: embolden); + bottomLinkContainer.AddLink(" " + content, link, creationParameters: embolden); else - linkContainer.AddText(" " + content, embolden); + bottomLinkContainer.AddText(" " + content, embolden); - addSpacer(linkContainer); + addSpacer(bottomLinkContainer); + return true; } private void embolden(SpriteText text) => text.Font = text.Font.With(weight: FontWeight.Bold); From 3cc1b811ef21a648eeda60c51aa751fdc6db3431 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 2 Feb 2020 17:22:48 +0100 Subject: [PATCH 47/52] Make dates non-italic to match osu-web --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 065bef8329..3dcd65d64e 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Profile.Header else { topLinkContainer.AddText("Joined "); - topLinkContainer.AddText(new DrawableDate(user.JoinDate), embolden); + topLinkContainer.AddText(new DrawableDate(user.JoinDate, italic: false), embolden); } addSpacer(topLinkContainer); @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Profile.Header else if (user.LastVisit.HasValue) { topLinkContainer.AddText("Last seen "); - topLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); + topLinkContainer.AddText(new DrawableDate(user.LastVisit.Value, italic: false), embolden); addSpacer(topLinkContainer); } From 72107c27c99cb568d8457dfe01f3ce2d271ffbc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 2 Feb 2020 17:39:58 +0100 Subject: [PATCH 48/52] Only add newline if necessary --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 3dcd65d64e..4643ca709b 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -127,7 +127,10 @@ namespace osu.Game.Overlays.Profile.Header anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); anyInfoAdded |= tryAddInfo(OsuIcon.Heart, user.Interests); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); - bottomLinkContainer.NewLine(); + + if (anyInfoAdded) + bottomLinkContainer.NewLine(); + if (!string.IsNullOrEmpty(user.Twitter)) anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); anyInfoAdded |= tryAddInfo(FontAwesome.Brands.Discord, user.Discord); From c479d0efa48be274e36ffa55359bfff6716ab30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 2 Feb 2020 17:41:42 +0100 Subject: [PATCH 49/52] Simplify show/hide logic --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 4643ca709b..c27b5f4b4a 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -139,10 +139,7 @@ namespace osu.Game.Overlays.Profile.Header anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtocol, user.Website); // If no information was added to the bottomLinkContainer, hide it to avoid unwanted padding - if (anyInfoAdded) - bottomLinkContainer.Show(); - else - bottomLinkContainer.Hide(); + bottomLinkContainer.Alpha = anyInfoAdded ? 1 : 0; } private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); From 9680c0941fa1b751b1dd0a4ab48235e6b15081ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Feb 2020 12:46:11 +0900 Subject: [PATCH 50/52] Move private helper methods to botom of file --- .../Sections/Recent/DrawableRecentActivity.cs | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index f538833eb0..8782e82642 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -122,30 +122,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } } - private string getRulesetName() - { - var shortName = activity.Mode; - - return rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == shortName)?.Name ?? shortName; - } - - private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument; - - private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) - => OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true); - - private void addUserLink() - => content.AddLink(activity.User?.Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User?.Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold)); - - private void addBeatmapLink() - => content.AddLink(activity.Beatmap?.Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap?.Url), creationParameters: t => t.Font = getLinkFont()); - - private void addBeatmapsetLink() - => content.AddLink(activity.Beatmapset?.Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset?.Url), creationParameters: t => t.Font = getLinkFont()); - - private void addText(string text) - => content.AddText(text, t => t.Font = OsuFont.GetFont(size: font_size, weight: FontWeight.SemiBold)); - private void createMessage() { switch (activity.Type) @@ -227,5 +203,25 @@ namespace osu.Game.Overlays.Profile.Sections.Recent break; } } + + private string getRulesetName() => + rulesets.AvailableRulesets.FirstOrDefault(r => r.ShortName == activity.Mode)?.Name ?? activity.Mode; + + private void addUserLink() + => content.AddLink(activity.User?.Username, LinkAction.OpenUserProfile, getLinkArgument(activity.User?.Url), creationParameters: t => t.Font = getLinkFont(FontWeight.Bold)); + + private void addBeatmapLink() + => content.AddLink(activity.Beatmap?.Title, LinkAction.OpenBeatmap, getLinkArgument(activity.Beatmap?.Url), creationParameters: t => t.Font = getLinkFont()); + + private void addBeatmapsetLink() + => content.AddLink(activity.Beatmapset?.Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset?.Url), creationParameters: t => t.Font = getLinkFont()); + + private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.Endpoint}{url}").Argument; + + private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) + => OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true); + + private void addText(string text) + => content.AddText(text, t => t.Font = OsuFont.GetFont(size: font_size, weight: FontWeight.SemiBold)); } } From d9d8712360b3093c76bf0cb6f7f1f3922de45578 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Feb 2020 15:13:21 +0900 Subject: [PATCH 51/52] Refactor class layout for readability --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index 5b53d9d1fa..f8a9d14f62 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -17,11 +17,6 @@ namespace osu.Game.Overlays { public class OverlayRulesetTabItem : TabItem { - protected readonly OsuSpriteText Text; - private readonly FillFlowContainer content; - - protected override Container Content => content; - private Color4 accentColour; protected virtual Color4 AccentColour @@ -30,13 +25,17 @@ namespace osu.Game.Overlays set { accentColour = value; - Text.FadeColour(value, 120, Easing.OutQuint); + text.FadeColour(value, 120, Easing.OutQuint); } } + protected override Container Content { get; } + [Resolved] private OverlayColourProvider colourProvider { get; set; } + private readonly OsuSpriteText text; + public OverlayRulesetTabItem(RulesetInfo value) : base(value) { @@ -44,12 +43,12 @@ namespace osu.Game.Overlays AddRangeInternal(new Drawable[] { - content = new FillFlowContainer + Content = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(3, 0), - Child = Text = new OsuSpriteText + Child = text = new OsuSpriteText { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -87,7 +86,7 @@ namespace osu.Game.Overlays private void updateState() { - Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); + text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); AccentColour = IsHovered || Active.Value ? Color4.White : colourProvider.Highlight1; } } From 9183c78319bf3629d67e8c0346e0e5640ca83219 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Feb 2020 16:04:32 +0900 Subject: [PATCH 52/52] Fix crash on exiting song select with ctrl-enter autoplay --- .../SongSelect/TestScenePlaySongSelect.cs | 27 ++++++++++++++++++- osu.Game/Screens/Select/PlaySongSelect.cs | 4 +-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index c01dee2959..80192b9ebc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -23,6 +23,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko; +using osu.Game.Screens.Play; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; @@ -77,7 +78,6 @@ namespace osu.Game.Tests.Visual.SongSelect private OsuConfigManager config; - [SetUpSteps] public override void SetUpSteps() { base.SetUpSteps(); @@ -426,6 +426,31 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("start not requested", () => !startRequested); } + [Test] + public void TestAutoplayViaCtrlEnter() + { + addRulesetImportStep(0); + + createSongSelect(); + + AddStep("press ctrl+enter", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.PressKey(Key.Enter); + + InputManager.ReleaseKey(Key.ControlLeft); + InputManager.ReleaseKey(Key.Enter); + }); + + AddUntilStep("wait for player", () => Stack.CurrentScreen is PlayerLoader); + + AddAssert("autoplay enabled", () => songSelect.Mods.Value.FirstOrDefault() is ModAutoplay); + + AddUntilStep("wait for return to ss", () => songSelect.IsCurrentScreen()); + + AddAssert("mod disabled", () => songSelect.Mods.Value.Count == 0); + } + [Test] public void TestHideSetSelectsCorrectBeatmap() { diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 9368bac69f..18f13c5e1d 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -33,6 +33,8 @@ namespace osu.Game.Screens.Select public override void OnResuming(IScreen last) { + base.OnResuming(last); + player = null; if (removeAutoModOnResume) @@ -41,8 +43,6 @@ namespace osu.Game.Screens.Select ModSelect.DeselectTypes(new[] { autoType }, true); removeAutoModOnResume = false; } - - base.OnResuming(last); } protected override bool OnStart()