1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-15 17:47:18 +08:00

Use DI to provide dependencies for KPS Calculator and improve input

gathering

KPS Calculator now uses DI to retrieve the clocks. Using `HUDOverlay` it
is now cached for `KeysPerSecondCounter`s to resolve it. This also
allows to make an "Attach" flow like `KeyCounter`.
This commit is contained in:
Ryuki 2022-08-08 21:27:46 +02:00
parent b2557a8d2d
commit b52a07c16a
No known key found for this signature in database
GPG Key ID: A353889EAEACBF49
6 changed files with 90 additions and 54 deletions

View File

@ -30,6 +30,7 @@ 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.KPSCounter;
using osuTK;
namespace osu.Game.Rulesets.UI
@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.UI
/// Displays an interactive ruleset gameplay instance.
/// </summary>
/// <typeparam name="TObject">The type of HitObject contained by this DrawableRuleset.</typeparam>
public abstract class DrawableRuleset<TObject> : DrawableRuleset, IProvideCursor, ICanAttachKeyCounter
public abstract class DrawableRuleset<TObject> : DrawableRuleset, IProvideCursor, ICanAttachKeyCounter, ICanAttachKpsCalculator
where TObject : HitObject
{
public override event Action<JudgementResult> NewResult;
@ -340,6 +341,8 @@ namespace osu.Game.Rulesets.UI
public void Attach(KeyCounterDisplay keyCounter) =>
(KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(keyCounter);
public void Attach(KeysPerSecondCalculator kps) => (KeyBindingInputManager as ICanAttachKpsCalculator)?.Attach(kps);
/// <summary>
/// Creates a key conversion input manager. An exception will be thrown if a valid <see cref="RulesetInputManager{T}"/> is not returned.
/// </summary>

View File

@ -20,11 +20,12 @@ using osu.Game.Input.Bindings;
using osu.Game.Input.Handlers;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD.KPSCounter;
using static osu.Game.Input.Handlers.ReplayInputHandler;
namespace osu.Game.Rulesets.UI
{
public abstract class RulesetInputManager<T> : PassThroughInputManager, ICanAttachKeyCounter, IHasReplayHandler, IHasRecordingHandler
public abstract class RulesetInputManager<T> : PassThroughInputManager, ICanAttachKeyCounter, IHasReplayHandler, IHasRecordingHandler, ICanAttachKpsCalculator
where T : struct
{
public readonly KeyBindingContainer<T> KeyBindingContainer;
@ -186,6 +187,35 @@ namespace osu.Game.Rulesets.UI
#endregion
#region KPS Counter Attachment
public void Attach(KeysPerSecondCalculator kps)
{
var listener = new ActionListener();
KeyBindingContainer.Add(listener);
kps.Listener = listener;
}
public class ActionListener : KeysPerSecondCalculator.InputListener, IKeyBindingHandler<T>
{
public override event Action OnNewInput;
public bool OnPressed(KeyBindingPressEvent<T> e)
{
OnNewInput?.Invoke();
return false;
}
public void OnReleased(KeyBindingReleaseEvent<T> e)
{
}
}
#endregion
protected virtual KeyBindingContainer<T> CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
=> new RulesetKeyBindingContainer(ruleset, variant, unique);
@ -229,6 +259,11 @@ namespace osu.Game.Rulesets.UI
void Attach(KeyCounterDisplay keyCounter);
}
public interface ICanAttachKpsCalculator
{
void Attach(KeysPerSecondCalculator keysPerSecondCalculator);
}
public class RulesetInputManagerInputState<T> : InputState
where T : struct
{

View File

@ -4,55 +4,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
namespace osu.Game.Screens.Play.HUD.KPSCounter
{
public class KeysPerSecondCalculator
public class KeysPerSecondCalculator : Component
{
public static void AddInput()
{
onNewInput?.Invoke();
}
private readonly List<double> timestamps;
private GameplayClock? gameplayClock;
private DrawableRuleset? drawableRuleset;
public GameplayClock? GameplayClock
private InputListener? listener;
[Resolved]
private GameplayClock? gameplayClock { get; set; }
[Resolved(canBeNull: true)]
private DrawableRuleset? drawableRuleset { get; set; }
public InputListener Listener
{
get => gameplayClock;
set
{
onResetRequested?.Invoke();
if (value != null)
{
gameplayClock = value;
}
listener = value;
listener.OnNewInput += addTimestamp;
}
}
public DrawableRuleset? DrawableRuleset
{
get => drawableRuleset;
set
{
onResetRequested?.Invoke();
if (value != null)
{
drawableRuleset = value;
baseRate = (drawableRuleset.Mods.FirstOrDefault(m => m is ModRateAdjust) as ModRateAdjust)?.SpeedChange.Value
?? 1;
}
}
}
private static event Action? onNewInput;
private static event Action? onResetRequested;
private event Action? onResetRequested;
private IClock? workingClock => drawableRuleset?.FrameStableClock;
@ -81,8 +62,8 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
public KeysPerSecondCalculator()
{
RelativeSizeAxes = Axes.Both;
timestamps = new List<double>();
onNewInput += addTimestamp;
onResetRequested += cleanUp;
}
@ -90,6 +71,9 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
{
timestamps.Clear();
maxTime = double.NegativeInfinity;
if (listener != null)
listener.OnNewInput -= addTimestamp;
}
private void addTimestamp()
@ -111,5 +95,21 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
double relativeTime = workingClock.CurrentTime - timestamp;
return relativeTime >= 0 && relativeTime <= span;
}
~KeysPerSecondCalculator()
{
cleanUp();
}
public abstract class InputListener : Component
{
protected InputListener()
{
RelativeSizeAxes = Axes.Both;
Depth = float.MinValue;
}
public abstract event Action? OnNewInput;
}
}
}

View File

@ -22,21 +22,15 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
private readonly Bindable<bool> valid = new Bindable<bool>();
private static readonly KeysPerSecondCalculator calculator = new KeysPerSecondCalculator();
[Resolved]
private GameplayClock? gameplayClock
{
get => calculator.GameplayClock;
set => calculator.GameplayClock = value;
}
private KeysPerSecondCalculator? calculator { get; set; }
// This is to force the skin editor to show the component only in a Gameplay context
[Resolved]
private GameplayClock? gameplayClock { get; set; }
[Resolved(canBeNull: true)]
private DrawableRuleset? drawableRuleset
{
get => calculator.DrawableRuleset;
set => calculator.DrawableRuleset = value;
}
private DrawableRuleset? drawableRuleset { get; set; }
protected override double RollingDuration => 350;
@ -59,8 +53,8 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
{
base.Update();
valid.Value = calculator.Ready;
Current.Value = calculator.Ready ? calculator.Value : 0;
valid.Value = calculator != null && calculator.Ready;
Current.Value = calculator != null ? calculator.Ready ? calculator.Value : 0 : 0;
}
protected override IHasText CreateText() => new TextComponent

View File

@ -22,6 +22,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play.HUD;
using osu.Game.Screens.Play.HUD.KPSCounter;
using osu.Game.Skinning;
using osuTK;
@ -49,6 +50,9 @@ namespace osu.Game.Screens.Play
public readonly HoldForMenuButton HoldToQuit;
public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
[Cached]
private readonly KeysPerSecondCalculator keysPerSecondCalculator;
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
private readonly DrawableRuleset drawableRuleset;
@ -122,7 +126,8 @@ namespace osu.Game.Screens.Play
KeyCounter = CreateKeyCounter(),
HoldToQuit = CreateHoldForMenuButton(),
}
}
},
keysPerSecondCalculator = new KeysPerSecondCalculator()
};
}
@ -260,6 +265,7 @@ namespace osu.Game.Screens.Play
protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset)
{
(drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter);
(drawableRuleset as ICanAttachKpsCalculator)?.Attach(keysPerSecondCalculator);
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
}

View File

@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Screens.Play.HUD.KPSCounter;
using osuTK;
using osuTK.Graphics;
@ -56,7 +55,6 @@ namespace osu.Game.Screens.Play
public void Increment()
{
KeysPerSecondCalculator.AddInput();
if (!IsCounting)
return;