From 3ac0da2da305feac1ea30999e257027ffe37e51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 26 Mar 2022 21:33:52 +0100 Subject: [PATCH 1/4] Implement sheared toggle button --- .../TestSceneShearedToggleButton.cs | 88 ++++++++++ .../UserInterface/ShearedToggleButton.cs | 155 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs create mode 100644 osu.Game/Graphics/UserInterface/ShearedToggleButton.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs new file mode 100644 index 0000000000..a969858157 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs @@ -0,0 +1,88 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.UserInterface +{ + [TestFixture] + public class TestSceneShearedToggleButton : OsuManualInputManagerTestScene + { + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + + [Test] + public void TestShearedToggleButton() + { + ShearedToggleButton button = null; + + AddStep("create button", () => + { + Child = button = new ShearedToggleButton(0.2f) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Toggle me", + Width = 200 + }; + }); + + AddToggleStep("toggle button", active => button.Active.Value = active); + AddToggleStep("toggle disabled", disabled => button.Active.Disabled = disabled); + } + + [Test] + public void TestDisabledState() + { + ShearedToggleButton button = null; + + AddStep("create button", () => + { + Child = button = new ShearedToggleButton(0.2f) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Toggle me", + Width = 200 + }; + }); + + clickToggle(); + assertToggleState(true); + + clickToggle(); + assertToggleState(false); + + setToggleDisabledState(true); + + assertToggleState(false); + clickToggle(); + assertToggleState(false); + + setToggleDisabledState(false); + assertToggleState(false); + clickToggle(); + assertToggleState(true); + + setToggleDisabledState(true); + assertToggleState(true); + clickToggle(); + assertToggleState(true); + + void clickToggle() => AddStep("click toggle", () => + { + InputManager.MoveMouseTo(button); + InputManager.Click(MouseButton.Left); + }); + + void assertToggleState(bool active) => AddAssert($"toggle is {(active ? "" : "not ")}active", () => button.Active.Value == active); + + void setToggleDisabledState(bool disabled) => AddStep($"{(disabled ? "disable" : "enable")} toggle", () => button.Active.Disabled = disabled); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs new file mode 100644 index 0000000000..acbed29279 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs @@ -0,0 +1,155 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +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 ShearedToggleButton : OsuClickableContainer + { + public BindableBool Active { get; } = new BindableBool(); + + public LocalisableString Text + { + get => text.Text; + set => text.Text = value; + } + + private readonly Box background; + private readonly OsuSpriteText text; + + private Sample? sampleOff; + private Sample? sampleOn; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public ShearedToggleButton(float shear) + { + Height = 50; + Padding = new MarginPadding { Horizontal = shear * 50 }; + + Content.CornerRadius = 7; + Content.Shear = new Vector2(shear, 0); + Content.Masking = true; + Content.BorderThickness = 2; + Content.Anchor = Content.Origin = Anchor.Centre; + + 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) + } + }; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleOn = audio.Samples.Get(@"UI/check-on"); + sampleOff = audio.Samples.Get(@"UI/check-off"); + } + + protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(sampleSet); + + protected override void LoadComplete() + { + base.LoadComplete(); + + Active.BindValueChanged(_ => + { + updateState(); + playSample(); + }); + Active.BindDisabledChanged(disabled => + { + updateState(); + Action = disabled ? (Action?)null : Active.Toggle; + }, true); + + FinishTransforms(true); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + Content.ScaleTo(0.8f, 2000, Easing.OutQuint); + return base.OnMouseDown(e); + } + + protected override void OnMouseUp(MouseUpEvent e) + { + Content.ScaleTo(1, 1000, Easing.OutElastic); + base.OnMouseUp(e); + } + + private void updateState() + { + var darkerColour = Active.Value ? colourProvider.Highlight1 : colourProvider.Background3; + var lighterColour = Active.Value ? colourProvider.Colour0 : colourProvider.Background1; + + if (Active.Disabled) + { + darkerColour = darkerColour.Darken(0.3f); + lighterColour = lighterColour.Darken(0.3f); + } + else if (IsHovered) + { + darkerColour = darkerColour.Lighten(0.3f); + lighterColour = lighterColour.Lighten(0.3f); + } + + background.FadeColour(darkerColour, 150, Easing.OutQuint); + Content.TransformTo(nameof(BorderColour), ColourInfo.GradientVertical(darkerColour, lighterColour), 150, Easing.OutQuint); + + var textColour = Active.Value ? colourProvider.Background6 : colourProvider.Content1; + if (Active.Disabled) + textColour = textColour.Opacity(0.6f); + + text.FadeColour(textColour, 150, Easing.OutQuint); + } + + private void playSample() + { + if (Active.Value) + sampleOn?.Play(); + else + sampleOff?.Play(); + } + } +} From b3896257ca0721e50ce5e21f8572ade3da40dccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 31 Mar 2022 22:09:03 +0200 Subject: [PATCH 2/4] Move shear amount to constant --- .../Visual/UserInterface/TestSceneShearedToggleButton.cs | 4 ++-- osu.Game/Graphics/UserInterface/ShearedToggleButton.cs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs index a969858157..5082e93f37 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("create button", () => { - Child = button = new ShearedToggleButton(0.2f) + Child = button = new ShearedToggleButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("create button", () => { - Child = button = new ShearedToggleButton(0.2f) + Child = button = new ShearedToggleButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs index acbed29279..27d2611983 100644 --- a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs @@ -37,10 +37,12 @@ namespace osu.Game.Graphics.UserInterface private Sample? sampleOff; private Sample? sampleOn; + private const float shear = 0.2f; + [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public ShearedToggleButton(float shear) + public ShearedToggleButton() { Height = 50; Padding = new MarginPadding { Horizontal = shear * 50 }; From e180db145dcee071d8e559345a1bdb25f66856ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 31 Mar 2022 22:19:08 +0200 Subject: [PATCH 3/4] Add constructor argument to facilitate fixed width/autosizing --- .../TestSceneShearedToggleButton.cs | 25 +++++++++++++++++-- .../UserInterface/ShearedToggleButton.cs | 22 +++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs index 5082e93f37..f12cbc4979 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs @@ -23,12 +23,11 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("create button", () => { - Child = button = new ShearedToggleButton + Child = button = new ShearedToggleButton(200) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Toggle me", - Width = 200 }; }); @@ -36,6 +35,28 @@ namespace osu.Game.Tests.Visual.UserInterface AddToggleStep("toggle disabled", disabled => button.Active.Disabled = disabled); } + [Test] + public void TestSizing() + { + ShearedToggleButton toggleButton = null; + + AddStep("create fixed width button", () => Child = toggleButton = new ShearedToggleButton(200) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Fixed width" + }); + AddStep("change text", () => toggleButton.Text = "New text"); + + AddStep("create auto-sizing button", () => Child = toggleButton = new ShearedToggleButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "This button autosizes to its text!" + }); + AddStep("change text", () => toggleButton.Text = "New text"); + } + [Test] public void TestDisabledState() { diff --git a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs index 27d2611983..aed3be20a0 100644 --- a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs @@ -42,7 +42,17 @@ namespace osu.Game.Graphics.UserInterface [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public ShearedToggleButton() + /// + /// Creates a new + /// + /// + /// The width of the button. + /// + /// If a non- value is provided, this button will have a fixed width equal to the provided value. + /// If a value is provided (or the argument is omitted entirely), the button will autosize in width to fit the text. + /// + /// + public ShearedToggleButton(float? width = null) { Height = 50; Padding = new MarginPadding { Horizontal = shear * 50 }; @@ -67,6 +77,16 @@ namespace osu.Game.Graphics.UserInterface Shear = new Vector2(-shear, 0) } }; + + if (width != null) + { + Width = width.Value; + } + else + { + AutoSizeAxes = Axes.X; + text.Margin = new MarginPadding { Horizontal = 15 }; + } } [BackgroundDependencyLoader] From 058350dfd8bf7c7754ccc25bb20357185a750817 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Apr 2022 10:53:14 +0900 Subject: [PATCH 4/4] Fix failing test due to incorrect sizing specification --- .../Visual/UserInterface/TestSceneShearedToggleButton.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs index f12cbc4979..b5109aa58d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedToggleButton.cs @@ -64,12 +64,11 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("create button", () => { - Child = button = new ShearedToggleButton + Child = button = new ShearedToggleButton(200) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Toggle me", - Width = 200 }; });