1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-24 04:07:26 +08:00
osu-lazer/osu.Game/Screens/Play/HUD/KPSCounter/KeysPerSecondCalculator.cs
Ryuki b2557a8d2d
Refactor KPS
- Remove '#nullable disable' in KeysPerSecondCalculator and
  KeysPerSecondCounter
- Remove KeysPerSecondCalculator IDisposable implementation
- Make KeysPerSecondCalculator static instance initialized once by
  KeysPerSecondCounters
- Auto transfer dependencies from KeysPerSecondCounter to
  KeysPerSecondCalculator using Resolved properties
- Add internal reset logic to KeysPerSecondCalculator and make it
  independent from Player
- Use GameplayClock.TrueGameplayRate to get real-time rate. If 0 then it
  defaults to the last non 0 rate if no such mod is enabled
2022-08-07 00:53:00 +02:00

116 lines
3.1 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
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 static void AddInput()
{
onNewInput?.Invoke();
}
private readonly List<double> timestamps;
private GameplayClock? gameplayClock;
private DrawableRuleset? drawableRuleset;
public GameplayClock? GameplayClock
{
get => gameplayClock;
set
{
onResetRequested?.Invoke();
if (value != null)
{
gameplayClock = value;
}
}
}
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 IClock? workingClock => drawableRuleset?.FrameStableClock;
private double baseRate;
private double rate
{
get
{
if (gameplayClock != null)
{
if (gameplayClock.TrueGameplayRate > 0)
{
baseRate = gameplayClock.TrueGameplayRate;
}
}
return baseRate;
}
}
private double maxTime = double.NegativeInfinity;
public bool Ready => workingClock != null && gameplayClock != null;
public int Value => timestamps.Count(isTimestampWithinSpan);
public KeysPerSecondCalculator()
{
timestamps = new List<double>();
onNewInput += addTimestamp;
onResetRequested += cleanUp;
}
private void cleanUp()
{
timestamps.Clear();
maxTime = double.NegativeInfinity;
}
private void addTimestamp()
{
if (workingClock == null) return;
if (workingClock.CurrentTime >= maxTime)
{
timestamps.Add(workingClock.CurrentTime);
maxTime = workingClock.CurrentTime;
}
}
private bool isTimestampWithinSpan(double timestamp)
{
if (workingClock == null) return false;
double span = 1000 * rate;
double relativeTime = workingClock.CurrentTime - timestamp;
return relativeTime >= 0 && relativeTime <= span;
}
}
}