mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09: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:
@ -30,6 +30,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Play.HUD.KPSCounter;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.UI
|
namespace osu.Game.Rulesets.UI
|
||||||
@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// Displays an interactive ruleset gameplay instance.
|
/// Displays an interactive ruleset gameplay instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TObject">The type of HitObject contained by this DrawableRuleset.</typeparam>
|
/// <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
|
where TObject : HitObject
|
||||||
{
|
{
|
||||||
public override event Action<JudgementResult> NewResult;
|
public override event Action<JudgementResult> NewResult;
|
||||||
@ -340,6 +341,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
public void Attach(KeyCounterDisplay keyCounter) =>
|
public void Attach(KeyCounterDisplay keyCounter) =>
|
||||||
(KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(keyCounter);
|
(KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(keyCounter);
|
||||||
|
|
||||||
|
public void Attach(KeysPerSecondCalculator kps) => (KeyBindingInputManager as ICanAttachKpsCalculator)?.Attach(kps);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a key conversion input manager. An exception will be thrown if a valid <see cref="RulesetInputManager{T}"/> is not returned.
|
/// Creates a key conversion input manager. An exception will be thrown if a valid <see cref="RulesetInputManager{T}"/> is not returned.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -20,11 +20,12 @@ using osu.Game.Input.Bindings;
|
|||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Play.HUD.KPSCounter;
|
||||||
using static osu.Game.Input.Handlers.ReplayInputHandler;
|
using static osu.Game.Input.Handlers.ReplayInputHandler;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.UI
|
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
|
where T : struct
|
||||||
{
|
{
|
||||||
public readonly KeyBindingContainer<T> KeyBindingContainer;
|
public readonly KeyBindingContainer<T> KeyBindingContainer;
|
||||||
@ -186,6 +187,35 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
#endregion
|
#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)
|
protected virtual KeyBindingContainer<T> CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
|
||||||
=> new RulesetKeyBindingContainer(ruleset, variant, unique);
|
=> new RulesetKeyBindingContainer(ruleset, variant, unique);
|
||||||
|
|
||||||
@ -229,6 +259,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
void Attach(KeyCounterDisplay keyCounter);
|
void Attach(KeyCounterDisplay keyCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ICanAttachKpsCalculator
|
||||||
|
{
|
||||||
|
void Attach(KeysPerSecondCalculator keysPerSecondCalculator);
|
||||||
|
}
|
||||||
|
|
||||||
public class RulesetInputManagerInputState<T> : InputState
|
public class RulesetInputManagerInputState<T> : InputState
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
|
@ -4,55 +4,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play.HUD.KPSCounter
|
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 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
|
set
|
||||||
{
|
{
|
||||||
onResetRequested?.Invoke();
|
onResetRequested?.Invoke();
|
||||||
|
listener = value;
|
||||||
if (value != null)
|
listener.OnNewInput += addTimestamp;
|
||||||
{
|
|
||||||
gameplayClock = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrawableRuleset? DrawableRuleset
|
private event Action? onResetRequested;
|
||||||
{
|
|
||||||
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 IClock? workingClock => drawableRuleset?.FrameStableClock;
|
private IClock? workingClock => drawableRuleset?.FrameStableClock;
|
||||||
|
|
||||||
@ -81,8 +62,8 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
|
|||||||
|
|
||||||
public KeysPerSecondCalculator()
|
public KeysPerSecondCalculator()
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
timestamps = new List<double>();
|
timestamps = new List<double>();
|
||||||
onNewInput += addTimestamp;
|
|
||||||
onResetRequested += cleanUp;
|
onResetRequested += cleanUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +71,9 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
|
|||||||
{
|
{
|
||||||
timestamps.Clear();
|
timestamps.Clear();
|
||||||
maxTime = double.NegativeInfinity;
|
maxTime = double.NegativeInfinity;
|
||||||
|
|
||||||
|
if (listener != null)
|
||||||
|
listener.OnNewInput -= addTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTimestamp()
|
private void addTimestamp()
|
||||||
@ -111,5 +95,21 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
|
|||||||
double relativeTime = workingClock.CurrentTime - timestamp;
|
double relativeTime = workingClock.CurrentTime - timestamp;
|
||||||
return relativeTime >= 0 && relativeTime <= span;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,15 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
|
|||||||
|
|
||||||
private readonly Bindable<bool> valid = new Bindable<bool>();
|
private readonly Bindable<bool> valid = new Bindable<bool>();
|
||||||
|
|
||||||
private static readonly KeysPerSecondCalculator calculator = new KeysPerSecondCalculator();
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private GameplayClock? gameplayClock
|
private KeysPerSecondCalculator? calculator { get; set; }
|
||||||
{
|
|
||||||
get => calculator.GameplayClock;
|
// This is to force the skin editor to show the component only in a Gameplay context
|
||||||
set => calculator.GameplayClock = value;
|
[Resolved]
|
||||||
}
|
private GameplayClock? gameplayClock { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private DrawableRuleset? drawableRuleset
|
private DrawableRuleset? drawableRuleset { get; set; }
|
||||||
{
|
|
||||||
get => calculator.DrawableRuleset;
|
|
||||||
set => calculator.DrawableRuleset = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override double RollingDuration => 350;
|
protected override double RollingDuration => 350;
|
||||||
|
|
||||||
@ -59,8 +53,8 @@ namespace osu.Game.Screens.Play.HUD.KPSCounter
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
valid.Value = calculator.Ready;
|
valid.Value = calculator != null && calculator.Ready;
|
||||||
Current.Value = calculator.Ready ? calculator.Value : 0;
|
Current.Value = calculator != null ? calculator.Ready ? calculator.Value : 0 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IHasText CreateText() => new TextComponent
|
protected override IHasText CreateText() => new TextComponent
|
||||||
|
@ -22,6 +22,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Screens.Play.HUD.KPSCounter;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -49,6 +50,9 @@ namespace osu.Game.Screens.Play
|
|||||||
public readonly HoldForMenuButton HoldToQuit;
|
public readonly HoldForMenuButton HoldToQuit;
|
||||||
public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
|
public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly KeysPerSecondCalculator keysPerSecondCalculator;
|
||||||
|
|
||||||
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
|
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
|
||||||
|
|
||||||
private readonly DrawableRuleset drawableRuleset;
|
private readonly DrawableRuleset drawableRuleset;
|
||||||
@ -122,7 +126,8 @@ namespace osu.Game.Screens.Play
|
|||||||
KeyCounter = CreateKeyCounter(),
|
KeyCounter = CreateKeyCounter(),
|
||||||
HoldToQuit = CreateHoldForMenuButton(),
|
HoldToQuit = CreateHoldForMenuButton(),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
keysPerSecondCalculator = new KeysPerSecondCalculator()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +265,7 @@ namespace osu.Game.Screens.Play
|
|||||||
protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset)
|
protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset)
|
||||||
{
|
{
|
||||||
(drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter);
|
(drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter);
|
||||||
|
(drawableRuleset as ICanAttachKpsCalculator)?.Attach(keysPerSecondCalculator);
|
||||||
|
|
||||||
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
|
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Screens.Play.HUD.KPSCounter;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -56,7 +55,6 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public void Increment()
|
public void Increment()
|
||||||
{
|
{
|
||||||
KeysPerSecondCalculator.AddInput();
|
|
||||||
if (!IsCounting)
|
if (!IsCounting)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user