mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 17:13:06 +08:00
Merge pull request #19777 from peppy/even-nicer-frame-stability-clock
Tidy up and document `FrameStabilityContainer`
This commit is contained in:
commit
adeabc632b
@ -22,9 +22,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Cached(typeof(IGameplayClock))]
|
[Cached(typeof(IGameplayClock))]
|
||||||
[Cached(typeof(IFrameStableClock))]
|
[Cached(typeof(IFrameStableClock))]
|
||||||
public class FrameStabilityContainer : Container, IHasReplayHandler, IFrameStableClock, IGameplayClock
|
public sealed class FrameStabilityContainer : Container, IHasReplayHandler, IFrameStableClock, IGameplayClock
|
||||||
{
|
{
|
||||||
private readonly double gameplayStartTime;
|
public ReplayInputHandler? ReplayInputHandler { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of frames (per parent frame) which can be run in an attempt to catch-up to real-time.
|
/// The number of frames (per parent frame) which can be run in an attempt to catch-up to real-time.
|
||||||
@ -34,13 +34,48 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to enable frame-stable playback.
|
/// Whether to enable frame-stable playback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal bool FrameStablePlayback = true;
|
internal bool FrameStablePlayback { get; set; } = true;
|
||||||
|
|
||||||
public readonly Bindable<bool> IsCatchingUp = new Bindable<bool>();
|
protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && state != PlaybackState.NotValid;
|
||||||
|
|
||||||
public readonly Bindable<bool> WaitingOnFrames = new Bindable<bool>();
|
private readonly Bindable<bool> isCatchingUp = new Bindable<bool>();
|
||||||
|
|
||||||
public IBindable<bool> IsPaused { get; } = new BindableBool();
|
private readonly Bindable<bool> waitingOnFrames = new Bindable<bool>();
|
||||||
|
|
||||||
|
private readonly double gameplayStartTime;
|
||||||
|
|
||||||
|
private IGameplayClock? parentGameplayClock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A clock which is used as reference for time, rate and running state.
|
||||||
|
/// </summary>
|
||||||
|
private IClock referenceClock = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A local manual clock which tracks the reference clock.
|
||||||
|
/// Values are transferred from <see cref="referenceClock"/> each update call.
|
||||||
|
/// </summary>
|
||||||
|
private readonly ManualClock manualClock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main framed clock which has stability applied to it.
|
||||||
|
/// This gets exposed to children as an <see cref="IGameplayClock"/>.
|
||||||
|
/// </summary>
|
||||||
|
private readonly FramedClock framedClock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current direction of playback to be exposed to frame stable children.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initially it is presumed that playback will proceed in the forward direction.
|
||||||
|
/// </remarks>
|
||||||
|
private int direction = 1;
|
||||||
|
|
||||||
|
private PlaybackState state;
|
||||||
|
|
||||||
|
private bool hasReplayAttached => ReplayInputHandler != null;
|
||||||
|
|
||||||
|
private bool firstConsumption = true;
|
||||||
|
|
||||||
public FrameStabilityContainer(double gameplayStartTime = double.MinValue)
|
public FrameStabilityContainer(double gameplayStartTime = double.MinValue)
|
||||||
{
|
{
|
||||||
@ -51,22 +86,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
this.gameplayStartTime = gameplayStartTime;
|
this.gameplayStartTime = gameplayStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ManualClock manualClock;
|
|
||||||
|
|
||||||
private readonly FramedClock framedClock;
|
|
||||||
|
|
||||||
private IGameplayClock? parentGameplayClock;
|
|
||||||
|
|
||||||
private IClock referenceClock = null!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The current direction of playback to be exposed to frame stable children.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Initially it is presumed that playback will proceed in the forward direction.
|
|
||||||
/// </remarks>
|
|
||||||
private int direction = 1;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IGameplayClock? gameplayClock)
|
private void load(IGameplayClock? gameplayClock)
|
||||||
{
|
{
|
||||||
@ -80,16 +99,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
Clock = this;
|
Clock = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaybackState state;
|
|
||||||
|
|
||||||
protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && state != PlaybackState.NotValid;
|
|
||||||
|
|
||||||
private bool hasReplayAttached => ReplayInputHandler != null;
|
|
||||||
|
|
||||||
private const double sixty_frame_time = 1000.0 / 60;
|
|
||||||
|
|
||||||
private bool firstConsumption = true;
|
|
||||||
|
|
||||||
public override bool UpdateSubTree()
|
public override bool UpdateSubTree()
|
||||||
{
|
{
|
||||||
int loops = MaxCatchUpFrames;
|
int loops = MaxCatchUpFrames;
|
||||||
@ -112,7 +121,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
private void updateClock()
|
private void updateClock()
|
||||||
{
|
{
|
||||||
if (WaitingOnFrames.Value)
|
if (waitingOnFrames.Value)
|
||||||
{
|
{
|
||||||
// if waiting on frames, run one update loop to determine if frames have arrived.
|
// if waiting on frames, run one update loop to determine if frames have arrived.
|
||||||
state = PlaybackState.Valid;
|
state = PlaybackState.Valid;
|
||||||
@ -150,8 +159,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
double timeBehind = Math.Abs(proposedTime - referenceClock.CurrentTime);
|
double timeBehind = Math.Abs(proposedTime - referenceClock.CurrentTime);
|
||||||
|
|
||||||
IsCatchingUp.Value = timeBehind > 200;
|
isCatchingUp.Value = timeBehind > 200;
|
||||||
WaitingOnFrames.Value = state == PlaybackState.NotValid;
|
waitingOnFrames.Value = state == PlaybackState.NotValid;
|
||||||
|
|
||||||
manualClock.CurrentTime = proposedTime;
|
manualClock.CurrentTime = proposedTime;
|
||||||
manualClock.Rate = Math.Abs(referenceClock.Rate) * direction;
|
manualClock.Rate = Math.Abs(referenceClock.Rate) * direction;
|
||||||
@ -211,6 +220,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// <param name="proposedTime">The time which is to be displayed.</param>
|
/// <param name="proposedTime">The time which is to be displayed.</param>
|
||||||
private void applyFrameStability(ref double proposedTime)
|
private void applyFrameStability(ref double proposedTime)
|
||||||
{
|
{
|
||||||
|
const double sixty_frame_time = 1000.0 / 60;
|
||||||
|
|
||||||
if (firstConsumption)
|
if (firstConsumption)
|
||||||
{
|
{
|
||||||
// On the first update, frame-stability seeking would result in unexpected/unwanted behaviour.
|
// On the first update, frame-stability seeking would result in unexpected/unwanted behaviour.
|
||||||
@ -234,9 +245,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplayInputHandler? ReplayInputHandler { get; set; }
|
#region Delegation of IGameplayClock
|
||||||
|
|
||||||
#region Delegation of IFrameStableClock
|
public IBindable<bool> IsPaused { get; } = new BindableBool();
|
||||||
|
|
||||||
public double CurrentTime => framedClock.CurrentTime;
|
public double CurrentTime => framedClock.CurrentTime;
|
||||||
|
|
||||||
@ -252,10 +263,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public FrameTimeInfo TimeInfo => framedClock.TimeInfo;
|
public FrameTimeInfo TimeInfo => framedClock.TimeInfo;
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Delegation of IGameplayClock
|
|
||||||
|
|
||||||
public double TrueGameplayRate
|
public double TrueGameplayRate
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -280,6 +287,13 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Delegation of IFrameStableClock
|
||||||
|
|
||||||
|
IBindable<bool> IFrameStableClock.IsCatchingUp => isCatchingUp;
|
||||||
|
IBindable<bool> IFrameStableClock.WaitingOnFrames => waitingOnFrames;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private enum PlaybackState
|
private enum PlaybackState
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -298,8 +312,5 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Valid
|
Valid
|
||||||
}
|
}
|
||||||
|
|
||||||
IBindable<bool> IFrameStableClock.IsCatchingUp => IsCatchingUp;
|
|
||||||
IBindable<bool> IFrameStableClock.WaitingOnFrames => WaitingOnFrames;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user