2022-04-26 16:31:55 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable enable
using osu.Framework.Allocation ;
using osu.Framework.Graphics ;
using osu.Framework.Graphics.Colour ;
2022-05-22 02:49:29 +08:00
using osu.Framework.Graphics.Containers ;
2022-04-26 16:31:55 +08:00
using osu.Framework.Graphics.Shapes ;
using osu.Framework.Input.Events ;
using osu.Framework.Localisation ;
using osu.Game.Graphics.Containers ;
using osu.Game.Graphics.Sprites ;
using osu.Game.Overlays ;
using osuTK ;
namespace osu.Game.Graphics.UserInterface
{
public class ShearedButton : OsuClickableContainer
{
public LocalisableString Text
{
get = > text . Text ;
set = > text . Text = value ;
}
2022-04-26 17:14:57 +08:00
public float TextSize
{
get = > text . Font . Size ;
set = > text . Font = OsuFont . TorusAlternate . With ( size : value ) ;
}
2022-04-26 16:31:55 +08:00
public Colour4 DarkerColour
{
set
{
darkerColour = value ;
Scheduler . AddOnce ( updateState ) ;
}
}
public Colour4 LighterColour
{
set
{
lighterColour = value ;
Scheduler . AddOnce ( updateState ) ;
}
}
public Colour4 TextColour
{
set
{
textColour = value ;
Scheduler . AddOnce ( updateState ) ;
}
}
[Resolved]
protected OverlayColourProvider ColourProvider { get ; private set ; } = null ! ;
private readonly Box background ;
private readonly OsuSpriteText text ;
private const float shear = 0.2f ;
private Colour4 ? darkerColour ;
private Colour4 ? lighterColour ;
private Colour4 ? textColour ;
2022-05-22 02:49:29 +08:00
private readonly Container backgroundLayer ;
2022-04-26 17:03:34 +08:00
private readonly Box flashLayer ;
2022-04-26 16:31:55 +08:00
/// <summary>
/// Creates a new <see cref="ShearedToggleButton"/>
/// </summary>
/// <param name="width">
/// The width of the button.
/// <list type="bullet">
/// <item>If a non-<see langword="null"/> value is provided, this button will have a fixed width equal to the provided value.</item>
/// <item>If a <see langword="null"/> value is provided (or the argument is omitted entirely), the button will autosize in width to fit the text.</item>
/// </list>
/// </param>
public ShearedButton ( float? width = null )
{
Height = 50 ;
Padding = new MarginPadding { Horizontal = shear * 50 } ;
2022-05-22 02:49:29 +08:00
const float corner_radius = 7 ;
Content . CornerRadius = corner_radius ;
2022-04-26 16:31:55 +08:00
Content . Shear = new Vector2 ( shear , 0 ) ;
Content . Masking = true ;
Content . Anchor = Content . Origin = Anchor . Centre ;
Children = new Drawable [ ]
{
2022-05-22 02:49:29 +08:00
backgroundLayer = new Container
2022-04-26 16:31:55 +08:00
{
2022-05-22 02:49:29 +08:00
RelativeSizeAxes = Axes . Both ,
CornerRadius = corner_radius ,
Masking = true ,
BorderThickness = 2 ,
Children = new Drawable [ ]
{
background = new Box
{
RelativeSizeAxes = Axes . Both
} ,
text = new OsuSpriteText
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
Font = OsuFont . TorusAlternate . With ( size : 17 ) ,
Shear = new Vector2 ( - shear , 0 )
} ,
}
2022-04-26 17:03:34 +08:00
} ,
flashLayer = new Box
{
RelativeSizeAxes = Axes . Both ,
Colour = Colour4 . White . Opacity ( 0.9f ) ,
Blending = BlendingParameters . Additive ,
Alpha = 0 ,
} ,
2022-04-26 16:31:55 +08:00
} ;
if ( width ! = null )
{
Width = width . Value ;
}
else
{
AutoSizeAxes = Axes . X ;
text . Margin = new MarginPadding { Horizontal = 15 } ;
}
}
protected override HoverSounds CreateHoverSounds ( HoverSampleSet sampleSet ) = > new HoverClickSounds ( sampleSet ) ;
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
Enabled . BindValueChanged ( _ = > Scheduler . AddOnce ( updateState ) ) ;
updateState ( ) ;
FinishTransforms ( true ) ;
}
2022-04-26 17:03:34 +08:00
protected override bool OnClick ( ClickEvent e )
{
if ( Enabled . Value )
flashLayer . FadeOutFromOne ( 800 , Easing . OutQuint ) ;
return base . OnClick ( e ) ;
}
2022-04-26 16:31:55 +08:00
protected override bool OnHover ( HoverEvent e )
{
Scheduler . AddOnce ( updateState ) ;
return base . OnHover ( e ) ;
}
protected override void OnHoverLost ( HoverLostEvent e )
{
Scheduler . AddOnce ( updateState ) ;
base . OnHoverLost ( e ) ;
}
protected override bool OnMouseDown ( MouseDownEvent e )
{
2022-05-02 19:30:36 +08:00
Content . ScaleTo ( 0.9f , 2000 , Easing . OutQuint ) ;
2022-04-26 16:31:55 +08:00
return base . OnMouseDown ( e ) ;
}
protected override void OnMouseUp ( MouseUpEvent e )
{
Content . ScaleTo ( 1 , 1000 , Easing . OutElastic ) ;
base . OnMouseUp ( e ) ;
}
private void updateState ( )
{
var colourDark = darkerColour ? ? ColourProvider . Background3 ;
var colourLight = lighterColour ? ? ColourProvider . Background1 ;
var colourText = textColour ? ? ColourProvider . Content1 ;
if ( ! Enabled . Value )
{
2022-05-02 19:30:03 +08:00
colourDark = colourDark . Darken ( 1f ) ;
colourLight = colourLight . Darken ( 1f ) ;
2022-04-26 16:31:55 +08:00
}
else if ( IsHovered )
{
2022-04-26 17:11:03 +08:00
colourDark = colourDark . Lighten ( 0.2f ) ;
colourLight = colourLight . Lighten ( 0.2f ) ;
2022-04-26 16:31:55 +08:00
}
background . FadeColour ( colourDark , 150 , Easing . OutQuint ) ;
2022-05-22 02:49:29 +08:00
backgroundLayer . TransformTo ( nameof ( BorderColour ) , ColourInfo . GradientVertical ( colourDark , colourLight ) , 150 , Easing . OutQuint ) ;
2022-04-26 16:31:55 +08:00
if ( ! Enabled . Value )
colourText = colourText . Opacity ( 0.6f ) ;
text . FadeColour ( colourText , 150 , Easing . OutQuint ) ;
}
}
}