diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs new file mode 100644 index 0000000000..9e77fcf675 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs @@ -0,0 +1,20 @@ +// 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.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOsuDropdown : ThemeComparisonTestScene + { + protected override Drawable CreateContent() => + new OsuEnumDropdown + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 150 + }; + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs new file mode 100644 index 0000000000..f8b9e8223b --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -0,0 +1,69 @@ +// 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.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public abstract class ThemeComparisonTestScene : OsuGridTestScene + { + protected ThemeComparisonTestScene() + : base(1, 2) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Cell(0, 0).AddRange(new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.GreySeafoam + }, + CreateContent() + }); + } + + private void createThemedContent(OverlayColourScheme colourScheme) + { + var colourProvider = new OverlayColourProvider(colourScheme); + + Cell(0, 1).Clear(); + Cell(0, 1).Add(new DependencyProvidingContainer + { + RelativeSizeAxes = Axes.Both, + CachedDependencies = new (Type, object)[] + { + (typeof(OverlayColourProvider), colourProvider) + }, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4 + }, + CreateContent() + } + }); + } + + protected abstract Drawable CreateContent(); + + [Test] + public void TestAllColourSchemes() + { + foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) + AddStep($"set {scheme} scheme", () => createThemedContent(scheme)); + } + } +} diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index 1eceb56e33..7067f82fd3 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -181,7 +181,11 @@ namespace osu.Game.Collections MaxHeight = 200; } - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new CollectionDropdownMenuItem(item); + protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new CollectionDropdownMenuItem(item) + { + BackgroundColourHover = HoverColour, + BackgroundColourSelected = SelectionColour + }; } protected class CollectionDropdownMenuItem : OsuDropdownMenu.DrawableOsuDropdownMenuItem diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 5831d9ab1f..b1d4691938 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -21,44 +21,17 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class OsuDropdown : Dropdown, IHasAccentColour + public class OsuDropdown : Dropdown { private const float corner_radius = 5; - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - updateAccentColour(); - } - } - - [BackgroundDependencyLoader(true)] - private void load(OverlayColourProvider? colourProvider, OsuColour colours) - { - if (accentColour == default) - accentColour = colourProvider?.Light4 ?? colours.PinkDarker; - updateAccentColour(); - } - - private void updateAccentColour() - { - if (Header is IHasAccentColour header) header.AccentColour = accentColour; - - if (Menu is IHasAccentColour menu) menu.AccentColour = accentColour; - } - protected override DropdownHeader CreateHeader() => new OsuDropdownHeader(); protected override DropdownMenu CreateMenu() => new OsuDropdownMenu(); #region OsuDropdownMenu - protected class OsuDropdownMenu : DropdownMenu, IHasAccentColour + protected class OsuDropdownMenu : DropdownMenu { public override bool HandleNonPositionalInput => State == MenuState.Open; @@ -78,9 +51,11 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader(true)] - private void load(OverlayColourProvider? colourProvider, AudioManager audio) + private void load(OverlayColourProvider? colourProvider, OsuColour colours, AudioManager audio) { BackgroundColour = colourProvider?.Background5 ?? Color4.Black.Opacity(0.5f); + HoverColour = colourProvider?.Light4 ?? colours.PinkDarker; + SelectionColour = colourProvider?.Background3 ?? colours.PinkDarker.Opacity(0.5f); sampleOpen = audio.Samples.Get(@"UI/dropdown-open"); sampleClose = audio.Samples.Get(@"UI/dropdown-close"); @@ -121,57 +96,77 @@ namespace osu.Game.Graphics.UserInterface } } - private Color4 accentColour; + private Color4 hoverColour; - public Color4 AccentColour + public Color4 HoverColour { - get => accentColour; + get => hoverColour; set { - accentColour = value; - foreach (var c in Children.OfType()) - c.AccentColour = value; + hoverColour = value; + foreach (var c in Children.OfType()) + c.BackgroundColourHover = value; + } + } + + private Color4 selectionColour; + + public Color4 SelectionColour + { + get => selectionColour; + set + { + selectionColour = value; + foreach (var c in Children.OfType()) + c.BackgroundColourSelected = value; } } protected override Menu CreateSubMenu() => new OsuMenu(Direction.Vertical); - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuDropdownMenuItem(item) { AccentColour = accentColour }; + protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuDropdownMenuItem(item) + { + BackgroundColourHover = HoverColour, + BackgroundColourSelected = SelectionColour + }; protected override ScrollContainer CreateScrollContainer(Direction direction) => new OsuScrollContainer(direction); #region DrawableOsuDropdownMenuItem - public class DrawableOsuDropdownMenuItem : DrawableDropdownMenuItem, IHasAccentColour + public class DrawableOsuDropdownMenuItem : DrawableDropdownMenuItem { // IsHovered is used public override bool HandlePositionalInput => true; - private Color4? accentColour; - - public Color4 AccentColour + public new Color4 BackgroundColourHover { - get => accentColour ?? nonAccentSelectedColour; + get => base.BackgroundColourHover; set { - accentColour = value; + base.BackgroundColourHover = value; + updateColours(); + } + } + + public new Color4 BackgroundColourSelected + { + get => base.BackgroundColourSelected; + set + { + base.BackgroundColourSelected = value; updateColours(); } } private void updateColours() { - BackgroundColourHover = accentColour ?? nonAccentHoverColour; - BackgroundColourSelected = accentColour ?? nonAccentSelectedColour; BackgroundColour = BackgroundColourHover.Opacity(0); UpdateBackgroundColour(); UpdateForegroundColour(); } - private Color4 nonAccentHoverColour; - private Color4 nonAccentSelectedColour; - public DrawableOsuDropdownMenuItem(MenuItem item) : base(item) { @@ -182,12 +177,8 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - nonAccentHoverColour = colours.PinkDarker; - nonAccentSelectedColour = Color4.Black.Opacity(0.5f); - updateColours(); - AddInternal(new HoverSounds()); } @@ -290,7 +281,7 @@ namespace osu.Game.Graphics.UserInterface #endregion - public class OsuDropdownHeader : DropdownHeader, IHasAccentColour + public class OsuDropdownHeader : DropdownHeader { protected readonly SpriteText Text; @@ -302,18 +293,6 @@ namespace osu.Game.Graphics.UserInterface protected readonly SpriteIcon Icon; - private Color4 accentColour; - - public virtual Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - BackgroundColourHover = accentColour; - } - } - public OsuDropdownHeader() { Foreground.Padding = new MarginPadding(10); diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs index 24b9ca8d90..68ffc6bf4e 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs @@ -11,13 +11,33 @@ using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { - public class OsuTabDropdown : OsuDropdown + public class OsuTabDropdown : OsuDropdown, IHasAccentColour { + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + + if (IsLoaded) + propagateAccentColour(); + } + } + public OsuTabDropdown() { RelativeSizeAxes = Axes.X; } + protected override void LoadComplete() + { + base.LoadComplete(); + propagateAccentColour(); + } + protected override DropdownMenu CreateMenu() => new OsuTabDropdownMenu(); protected override DropdownHeader CreateHeader() => new OsuTabDropdownHeader @@ -26,6 +46,18 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.TopRight }; + private void propagateAccentColour() + { + if (Menu is OsuDropdownMenu dropdownMenu) + { + dropdownMenu.HoverColour = accentColour; + dropdownMenu.SelectionColour = accentColour.Opacity(0.5f); + } + + if (Header is OsuTabDropdownHeader tabDropdownHeader) + tabDropdownHeader.AccentColour = accentColour; + } + private class OsuTabDropdownMenu : OsuDropdownMenu { public OsuTabDropdownMenu() @@ -37,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface MaxHeight = 400; } - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item) { AccentColour = AccentColour }; + protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item); private class DrawableOsuTabDropdownMenuItem : DrawableOsuDropdownMenuItem { @@ -49,15 +81,18 @@ namespace osu.Game.Graphics.UserInterface } } - protected class OsuTabDropdownHeader : OsuDropdownHeader + protected class OsuTabDropdownHeader : OsuDropdownHeader, IHasAccentColour { - public override Color4 AccentColour + private Color4 accentColour; + + public Color4 AccentColour { - get => base.AccentColour; + get => accentColour; set { - base.AccentColour = value; - Foreground.Colour = value; + accentColour = value; + BackgroundColourHover = value; + updateColour(); } } @@ -93,15 +128,20 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - Foreground.Colour = BackgroundColour; + updateColour(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - Foreground.Colour = BackgroundColourHover; + updateColour(); base.OnHoverLost(e); } + + private void updateColour() + { + Foreground.Colour = IsHovered ? BackgroundColour : BackgroundColourHover; + } } } } diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index ac4e7f8eda..5c3a41aec9 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -29,12 +29,6 @@ namespace osu.Game.Overlays.Login } } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AccentColour = colours.Gray5; - } - protected class UserDropdownMenu : OsuDropdownMenu { public UserDropdownMenu() @@ -56,6 +50,8 @@ namespace osu.Game.Overlays.Login private void load(OsuColour colours) { BackgroundColour = colours.Gray3; + SelectionColour = colours.Gray4; + HoverColour = colours.Gray5; } protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableUserDropdownMenuItem(item); @@ -118,6 +114,7 @@ namespace osu.Game.Overlays.Login private void load(OsuColour colours) { BackgroundColour = colours.Gray3; + BackgroundColourHover = colours.Gray5; } } } diff --git a/osu.Game/Overlays/Music/CollectionDropdown.cs b/osu.Game/Overlays/Music/CollectionDropdown.cs index ed0ebf696b..658eebe67b 100644 --- a/osu.Game/Overlays/Music/CollectionDropdown.cs +++ b/osu.Game/Overlays/Music/CollectionDropdown.cs @@ -19,12 +19,6 @@ namespace osu.Game.Overlays.Music { protected override bool ShowManageCollectionsItem => false; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AccentColour = colours.Gray6; - } - protected override CollectionDropdownHeader CreateCollectionHeader() => new CollectionsHeader(); protected override CollectionDropdownMenu CreateCollectionMenu() => new CollectionsMenu(); @@ -41,6 +35,8 @@ namespace osu.Game.Overlays.Music private void load(OsuColour colours) { BackgroundColour = colours.Gray4; + SelectionColour = colours.Gray5; + HoverColour = colours.Gray6; } } @@ -50,6 +46,7 @@ namespace osu.Game.Overlays.Music private void load(OsuColour colours) { BackgroundColour = colours.Gray4; + BackgroundColourHover = colours.Gray6; } public CollectionsHeader() diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 0f071883ca..dfa45cc543 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -175,18 +175,18 @@ namespace osu.Game.Overlays.Rankings private class SpotlightsDropdown : OsuDropdown { - private DropdownMenu menu; + private OsuDropdownMenu menu; - protected override DropdownMenu CreateMenu() => menu = base.CreateMenu().With(m => m.MaxHeight = 400); + protected override DropdownMenu CreateMenu() => menu = (OsuDropdownMenu)base.CreateMenu().With(m => m.MaxHeight = 400); protected override DropdownHeader CreateHeader() => new SpotlightsDropdownHeader(); [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - // osu-web adds a 0.6 opacity container on top of the 0.5 base one when hovering, 0.8 on a single container here matches the resulting colour - AccentColour = colourProvider.Background6.Opacity(0.8f); menu.BackgroundColour = colourProvider.Background5; + menu.HoverColour = colourProvider.Background4; + menu.SelectionColour = colourProvider.Background3; Padding = new MarginPadding { Vertical = 20 }; } @@ -205,7 +205,8 @@ namespace osu.Game.Overlays.Rankings private void load(OverlayColourProvider colourProvider) { BackgroundColour = colourProvider.Background6.Opacity(0.5f); - BackgroundColourHover = colourProvider.Background5; + // osu-web adds a 0.6 opacity container on top of the 0.5 base one when hovering, 0.8 on a single container here matches the resulting colour + BackgroundColourHover = colourProvider.Background6.Opacity(0.8f); } } }