From 74a58fb674945a5ec82f20ca2bffff91b6de776c Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 01:24:27 +0000 Subject: [PATCH] refactor: separate things in KeyCounter To implement different different sources of input for KeyCounter, it is now possible to create a Trigger class (to inherit) instead of inheriting KeyCounter. This eases the creation of more input sources (like for tests) while allowing to implement different UI variants. That way, if another variant of the key counter needs to implemented (for whathever reason), this can be done by only inheriting KeyCounter and changing how things are arranged visually. --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 9 +- osu.Game/Screens/Play/DefaultKeyCounter.cs | 105 +++++++++++++ osu.Game/Screens/Play/KeyCounter.cs | 157 +++++++------------- osu.Game/Screens/Play/KeyCounterAction.cs | 10 +- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 11 +- osu.Game/Screens/Play/KeyCounterMouse.cs | 11 +- 6 files changed, 177 insertions(+), 126 deletions(-) create mode 100644 osu.Game/Screens/Play/DefaultKeyCounter.cs diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index a5e442b7de..0fa1f0b332 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.UI .Select(b => b.GetAction()) .Distinct() .OrderBy(action => action) - .Select(action => new KeyCounterAction(action))); + .Select(action => keyCounter.CreateKeyCounter(new KeyCounterAction(action)))); } private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler @@ -176,11 +176,14 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(KeyBindingPressEvent e) => Target.Children.OfType>().Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); + public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.CounterTrigger is KeyCounterAction) + .Select(c => (KeyCounterAction)c.CounterTrigger) + .Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); public void OnReleased(KeyBindingReleaseEvent e) { - foreach (var c in Target.Children.OfType>()) + foreach (var c + in Target.Children.Where(c => c.CounterTrigger is KeyCounterAction).Select(c => (KeyCounterAction)c.CounterTrigger)) c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/DefaultKeyCounter.cs new file mode 100644 index 0000000000..dcb425ae1d --- /dev/null +++ b/osu.Game/Screens/Play/DefaultKeyCounter.cs @@ -0,0 +1,105 @@ +// 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.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + public partial class DefaultKeyCounter : KeyCounter + { + private Sprite buttonSprite = null!; + private Sprite glowSprite = null!; + private Container textLayer = null!; + private SpriteText countSpriteText = null!; + + //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor + public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; + public Color4 KeyUpTextColor { get; set; } = Color4.White; + public double FadeTime { get; set; } + + public DefaultKeyCounter(Trigger trigger) + : base(trigger) + { + } + + [BackgroundDependencyLoader(true)] + private void load(TextureStore textures) + { + Children = new Drawable[] + { + buttonSprite = new Sprite + { + Texture = textures.Get(@"KeyCounter/key-up"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + glowSprite = new Sprite + { + Texture = textures.Get(@"KeyCounter/key-glow"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0 + }, + textLayer = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = Name, + Font = OsuFont.Numeric.With(size: 12), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(0, -0.25f), + Colour = KeyUpTextColor + }, + countSpriteText = new OsuSpriteText + { + Text = CountPresses.ToString(@"#,0"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(0, 0.25f), + Colour = KeyUpTextColor + } + } + } + }; + // Set this manually because an element with Alpha=0 won't take it size to AutoSizeContainer, + // so the size can be changing between buttonSprite and glowSprite. + Height = buttonSprite.DrawHeight; + Width = buttonSprite.DrawWidth; + + IsLit.BindValueChanged(e => updateGlowSprite(e.NewValue), true); + PressesCount.BindValueChanged(e => countSpriteText.Text = e.NewValue.ToString(@"#,0"), true); + } + + private void updateGlowSprite(bool show) + { + if (show) + { + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); + } + else + { + double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; + glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 4405542b3b..a612edbace 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,57 +1,37 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osuTK; -using osuTK.Graphics; +using osu.Framework.Input.Events; namespace osu.Game.Screens.Play { public abstract partial class KeyCounter : Container { - private Sprite buttonSprite; - private Sprite glowSprite; - private Container textLayer; - private SpriteText countSpriteText; + public readonly Trigger CounterTrigger; - public bool IsCounting { get; set; } = true; - private int countPresses; + protected Bindable IsCountingBindable = new BindableBool(true); + + protected Bindable PressesCount = new BindableInt + { + MinValue = 0 + }; + + public bool IsCounting + { + get => IsCountingBindable.Value; + set => IsCountingBindable.Value = value; + } public int CountPresses { - get => countPresses; - private set - { - if (countPresses != value) - { - countPresses = value; - countSpriteText.Text = value.ToString(@"#,0"); - } - } + get => PressesCount.Value; + private set => PressesCount.Value = value; } - private bool isLit; - - public bool IsLit - { - get => isLit; - protected set - { - if (isLit != value) - { - isLit = value; - updateGlowSprite(value); - } - } - } + protected Bindable IsLit = new BindableBool(); public void Increment() { @@ -69,82 +49,51 @@ namespace osu.Game.Screens.Play CountPresses--; } - //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor - public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; - public Color4 KeyUpTextColor { get; set; } = Color4.White; - public double FadeTime { get; set; } - - protected KeyCounter(string name) + protected override void LoadComplete() { - Name = name; + Add(CounterTrigger); + base.LoadComplete(); } - [BackgroundDependencyLoader(true)] - private void load(TextureStore textures) + protected override bool Handle(UIEvent e) => CounterTrigger.TriggerEvent(e); + + protected KeyCounter(Trigger trigger) { - Children = new Drawable[] - { - buttonSprite = new Sprite - { - Texture = textures.Get(@"KeyCounter/key-up"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - glowSprite = new Sprite - { - Texture = textures.Get(@"KeyCounter/key-glow"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Alpha = 0 - }, - textLayer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = Name, - Font = OsuFont.Numeric.With(size: 12), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(0, -0.25f), - Colour = KeyUpTextColor - }, - countSpriteText = new OsuSpriteText - { - Text = CountPresses.ToString(@"#,0"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(0, 0.25f), - Colour = KeyUpTextColor - } - } - } - }; - // Set this manually because an element with Alpha=0 won't take it size to AutoSizeContainer, - // so the size can be changing between buttonSprite and glowSprite. - Height = buttonSprite.DrawHeight; - Width = buttonSprite.DrawWidth; + CounterTrigger = trigger; + trigger.Target = this; + Name = trigger.Name; } - private void updateGlowSprite(bool show) + public abstract partial class Trigger : Component { - if (show) + private KeyCounter? target; + + public KeyCounter Target { - double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); - glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); - textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); + set => target = value; } - else + + protected Trigger(string name) { - double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; - glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); - textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); + Name = name; + } + + protected void Lit(bool increment = true) + { + if (target == null) return; + + target.IsLit.Value = true; + if (increment) + target.Increment(); + } + + protected void Unlit(bool preserve = true) + { + if (target == null) return; + + target.IsLit.Value = false; + if (!preserve) + target.Decrement(); } } } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 900d9bcd0e..058dbb1480 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public partial class KeyCounterAction : KeyCounter + public partial class KeyCounterAction : KeyCounter.Trigger where T : struct { public T Action { get; } @@ -23,9 +23,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return false; - IsLit = true; - if (forwards) - Increment(); + Lit(forwards); return false; } @@ -34,9 +32,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return; - IsLit = false; - if (!forwards) - Decrement(); + Unlit(forwards); } } } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index c5c8b7eeae..4306efd360 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public partial class KeyCounterKeyboard : KeyCounter + public partial class KeyCounterKeyboard : KeyCounter.Trigger { public Key Key { get; } @@ -21,17 +21,16 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { if (e.Key == Key) - { - IsLit = true; - Increment(); - } + Lit(); return base.OnKeyDown(e); } protected override void OnKeyUp(KeyUpEvent e) { - if (e.Key == Key) IsLit = false; + if (e.Key == Key) + Unlit(); + base.OnKeyUp(e); } } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index cf9c7c029f..00fca47ba2 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public partial class KeyCounterMouse : KeyCounter + public partial class KeyCounterMouse : KeyCounter.Trigger { public MouseButton Button { get; } @@ -39,17 +39,16 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == Button) - { - IsLit = true; - Increment(); - } + Lit(); return base.OnMouseDown(e); } protected override void OnMouseUp(MouseUpEvent e) { - if (e.Button == Button) IsLit = false; + if (e.Button == Button) + Unlit(); + base.OnMouseUp(e); } }