diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index e0a1533c4b..57f5f54d8f 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -30,6 +30,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.HUD.ClicksPerSecond; using osuTK; namespace osu.Game.Rulesets.UI @@ -38,7 +40,7 @@ namespace osu.Game.Rulesets.UI /// Displays an interactive ruleset gameplay instance. /// /// The type of HitObject contained by this DrawableRuleset. - public abstract partial class DrawableRuleset : DrawableRuleset, IProvideCursor, IKeybindingEventsEmitter + public abstract partial class DrawableRuleset : DrawableRuleset, IProvideCursor, ICanAttachHUDPieces where TObject : HitObject { public override event Action NewResult; @@ -327,8 +329,11 @@ namespace osu.Game.Rulesets.UI /// The representing . public abstract DrawableHitObject CreateDrawableRepresentation(TObject h); - public void Attach(IKeybindingListener skinComponent) => - (KeyBindingInputManager as IKeybindingEventsEmitter)?.Attach(skinComponent); + public void Attach(KeyCounterController keyCounter) => + (KeyBindingInputManager as ICanAttachHUDPieces)?.Attach(keyCounter); + + public void Attach(ClicksPerSecondCalculator calculator) => + (KeyBindingInputManager as ICanAttachHUDPieces)?.Attach(calculator); /// /// Creates a key conversion input manager. An exception will be thrown if a valid is not returned. diff --git a/osu.Game/Rulesets/UI/IKeybindingListener.cs b/osu.Game/Rulesets/UI/IKeybindingListener.cs deleted file mode 100644 index f38ce8643e..0000000000 --- a/osu.Game/Rulesets/UI/IKeybindingListener.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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 System.Collections.Generic; -using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; - -namespace osu.Game.Rulesets.UI -{ - /// - /// Listens to events emitted by an . - /// Alternative to for classes that need to not depend on type parameters. - /// - public interface IKeybindingListener - { - /// - /// This class or a member of this class can already handle keybindings. - /// Signals to the that and - /// don't necessarily need to be called. - /// - /// - /// This is usually true for s and s that need to - /// pass s events to children that can already handle them. - /// - public bool CanHandleKeybindings { get; } - - /// - /// Prepares this class to receive events. - /// - /// The list of possible actions that can occur. - /// The type actions, commonly enums. - public void Setup(IEnumerable actions) where T : struct; - - /// - /// Called when an action is pressed. - /// - /// The event containing information about the pressed action. - /// The type of binding, commonly enums. - public void OnPressed(KeyBindingPressEvent action) where T : struct; - - /// - /// Called when an action is released. - /// - /// The event containing information about the released action. - /// The type of binding, commonly enums. - public void OnReleased(KeyBindingReleaseEvent action) where T : struct; - } -} diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 44c1f00cf7..2c403139b6 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -19,11 +19,13 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Input.Handlers; using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.HUD.ClicksPerSecond; using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.UI { - public abstract partial class RulesetInputManager : PassThroughInputManager, IKeybindingEventsEmitter, IHasReplayHandler, IHasRecordingHandler + public abstract partial class RulesetInputManager : PassThroughInputManager, ICanAttachHUDPieces, IHasReplayHandler, IHasRecordingHandler where T : struct { protected override bool AllowRightClickFromLongTouch => false; @@ -64,7 +66,6 @@ namespace osu.Game.Rulesets.UI InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique) .WithChild(content = new Container { RelativeSizeAxes = Axes.Both }); - KeyBindingContainer.Add(actionListener = new ActionListener()); } [BackgroundDependencyLoader(true)] @@ -157,49 +158,47 @@ namespace osu.Game.Rulesets.UI #endregion - #region Component attachement + #region Key Counter Attachment - private readonly ActionListener actionListener; - - public void Attach(IKeybindingListener skinComponent) + public void Attach(KeyCounterController keyCounter) { - skinComponent.Setup(KeyBindingContainer.DefaultKeyBindings + KeyBindingContainer.Add(keyCounter); + + keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings .Select(b => b.GetAction()) .Distinct() - .OrderBy(a => a)); + .OrderBy(action => action) + .Select(action => new KeyCounterActionTrigger(action))); + } - if (skinComponent.CanHandleKeybindings && skinComponent is Drawable component) - { - try - { - KeyBindingContainer.Add(component); - return; - } - catch (Exception) - { - return; - } - } + #endregion - actionListener.OnPressedEvent += skinComponent.OnPressed; - actionListener.OnReleasedEvent += skinComponent.OnReleased; + #region Keys per second Counter Attachment + + public void Attach(ClicksPerSecondCalculator calculator) + { + var listener = new ActionListener(calculator); + + KeyBindingContainer.Add(listener); } private partial class ActionListener : Component, IKeyBindingHandler { - public event Action> OnPressedEvent; + private readonly ClicksPerSecondCalculator calculator; - public event Action> OnReleasedEvent; + public ActionListener(ClicksPerSecondCalculator calculator) + { + this.calculator = calculator; + } public bool OnPressed(KeyBindingPressEvent e) { - OnPressedEvent?.Invoke(e); + calculator.AddInputTimestamp(); return false; } public void OnReleased(KeyBindingReleaseEvent e) { - OnReleasedEvent?.Invoke(e); } } @@ -240,11 +239,17 @@ namespace osu.Game.Rulesets.UI } /// - /// Sends events to a + /// Supports attaching various HUD pieces. + /// Keys will be populated automatically and a receptor will be injected inside. /// - public interface IKeybindingEventsEmitter + public interface ICanAttachHUDPieces + { + void Attach(KeyCounterController keyCounter); + void Attach(ClicksPerSecondCalculator calculator); + } + + public interface IAttachableSkinComponent { - void Attach(IKeybindingListener component); } public class RulesetInputManagerInputState : InputState diff --git a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs index e0e93cb66e..3e55e11f1c 100644 --- a/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs +++ b/osu.Game/Screens/Play/HUD/ClicksPerSecond/ClicksPerSecondCalculator.cs @@ -4,12 +4,11 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.Events; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play.HUD.ClicksPerSecond { - public partial class ClicksPerSecondCalculator : Component, IKeybindingListener + public partial class ClicksPerSecondCalculator : Component, IAttachableSkinComponent { private readonly List timestamps = new List(); @@ -54,21 +53,5 @@ namespace osu.Game.Screens.Play.HUD.ClicksPerSecond Value = count; } - - #region IKeybindingListener - - bool IKeybindingListener.CanHandleKeybindings => false; - - void IKeybindingListener.Setup(IEnumerable actions) - { - } - - void IKeybindingListener.OnPressed(KeyBindingPressEvent action) => AddInputTimestamp(); - - void IKeybindingListener.OnReleased(KeyBindingReleaseEvent action) - { - } - - #endregion } } diff --git a/osu.Game/Screens/Play/HUD/KeyCounterController.cs b/osu.Game/Screens/Play/HUD/KeyCounterController.cs index 2e678e55fc..0fa02afbb4 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterController.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterController.cs @@ -3,16 +3,14 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play.HUD { - public partial class KeyCounterController : CompositeComponent, IKeybindingListener + public partial class KeyCounterController : CompositeComponent, IAttachableSkinComponent { public readonly Bindable IsCounting = new BindableBool(true); @@ -38,22 +36,5 @@ namespace osu.Game.Screens.Play.HUD public override bool HandleNonPositionalInput => true; public override bool HandlePositionalInput => true; - - #region IKeybindingListener - - bool IKeybindingListener.CanHandleKeybindings => true; - - void IKeybindingListener.Setup(IEnumerable actions) - => AddRange(actions.Select(a => new KeyCounterActionTrigger(a))); - - void IKeybindingListener.OnPressed(KeyBindingPressEvent action) - { - } - - void IKeybindingListener.OnReleased(KeyBindingReleaseEvent action) - { - } - - #endregion } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index b74b5d835a..21636ac04c 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -10,7 +10,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; @@ -103,8 +102,6 @@ namespace osu.Game.Screens.Play private readonly List hideTargets; - private readonly IEnumerable actionInjectionCandidates; - public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods, bool alwaysShowLeaderboard = true) { Drawable rulesetComponents; @@ -166,8 +163,6 @@ namespace osu.Game.Screens.Play hideTargets = new List { mainComponents, rulesetComponents, topRightElements }; - actionInjectionCandidates = new IKeybindingListener[] { clicksPerSecondCalculator, KeyCounter }; - if (!alwaysShowLeaderboard) hideTargets.Add(LeaderboardFlow); } @@ -324,8 +319,11 @@ namespace osu.Game.Screens.Play protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset) { - if (drawableRuleset is IKeybindingEventsEmitter attachTarget) - actionInjectionCandidates.ForEach(attachTarget.Attach); + if (drawableRuleset is ICanAttachHUDPieces attachTarget) + { + attachTarget.Attach(KeyCounter); + attachTarget.Attach(clicksPerSecondCalculator); + } replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); }