diff --git a/osu.Game/Graphics/UserInterface/ShearedNub.cs b/osu.Game/Graphics/UserInterface/ShearedNub.cs index 6bee4fc3b7..390d6ff9be 100644 --- a/osu.Game/Graphics/UserInterface/ShearedNub.cs +++ b/osu.Game/Graphics/UserInterface/ShearedNub.cs @@ -1,26 +1,41 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +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.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public partial class ShearedNub : Nub + public partial class ShearedNub : Container, IHasCurrentValue, IHasAccentColour { + protected const float BORDER_WIDTH = 3; + public const int HEIGHT = 30; public const float EXPANDED_SIZE = 50; public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); + private readonly Box fill; + private readonly Container main; + + /// + /// Implements the shape for the nub, allowing for any type of container to be used. + /// + /// public ShearedNub() { Size = new Vector2(EXPANDED_SIZE, HEIGHT); - } - - protected override Container CreateNubContainer() => - new Container + InternalChild = main = new Container { Shear = SHEAR, BorderColour = Colour4.White, @@ -30,6 +45,136 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Child = fill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + } }; + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider, OsuColour colours) + { + AccentColour = colourProvider?.Highlight1 ?? colours.Pink; + GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; + GlowColour = colourProvider?.Highlight1 ?? colours.PinkLighter; + + main.EdgeEffect = new EdgeEffectParameters + { + Colour = GlowColour.Opacity(0), + Type = EdgeEffectType.Glow, + Radius = 8, + Roundness = 4, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(onCurrentValueChanged, true); + } + + private bool glowing; + + public bool Glowing + { + get => glowing; + set + { + glowing = value; + + if (value) + { + main.FadeColour(GlowingAccentColour.Lighten(0.5f), 40, Easing.OutQuint) + .Then() + .FadeColour(GlowingAccentColour, 800, Easing.OutQuint); + + main.FadeEdgeEffectTo(Color4.White.Opacity(0.1f), 40, Easing.OutQuint) + .Then() + .FadeEdgeEffectTo(GlowColour.Opacity(0.1f), 800, Easing.OutQuint); + } + else + { + main.FadeEdgeEffectTo(GlowColour.Opacity(0), 800, Easing.OutQuint); + main.FadeColour(AccentColour, 800, Easing.OutQuint); + } + } + } + + private readonly Bindable current = new Bindable(); + + public Bindable Current + { + get => current; + set + { + ArgumentNullException.ThrowIfNull(value); + + current.UnbindBindings(); + current.BindTo(value); + } + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + if (!Glowing) + main.Colour = value; + } + } + + private Color4 glowingAccentColour; + + public Color4 GlowingAccentColour + { + get => glowingAccentColour; + set + { + glowingAccentColour = value; + if (Glowing) + main.Colour = value; + } + } + + private Color4 glowColour; + + public Color4 GlowColour + { + get => glowColour; + set + { + glowColour = value; + + var effect = main.EdgeEffect; + effect.Colour = Glowing ? value : value.Opacity(0); + main.EdgeEffect = effect; + } + } + + private void onCurrentValueChanged(ValueChangedEvent filled) + { + const double duration = 200; + + fill.FadeTo(filled.NewValue ? 1 : 0, duration, Easing.OutQuint); + + if (filled.NewValue) + { + main.ResizeWidthTo(1, duration, Easing.OutElasticHalf); + main.TransformTo(nameof(BorderThickness), 8.5f, duration, Easing.OutElasticHalf); + } + else + { + main.ResizeWidthTo(0.75f, duration, Easing.OutQuint); + main.TransformTo(nameof(BorderThickness), BORDER_WIDTH, duration, Easing.OutQuint); + } + } } }