From 9e6b0a42ec4795eb3878e47946370d900aa8d453 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Oct 2020 16:28:50 +0900 Subject: [PATCH] Allow FrameStabilityContainer to handle waiting-for-data state better (and pause outwards) --- .../Replays/FramedReplayInputHandler.cs | 28 +++++++++++++++++-- .../Rulesets/UI/FrameStabilityContainer.cs | 3 +- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 62b24f6b55..ddf85b7300 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -124,20 +124,42 @@ namespace osu.Game.Rulesets.Replays if (HasFrames) { + var next = NextFrame; + // check if the next frame is valid for the current playback direction. // validity is if the next frame is equal or "earlier" - var compare = time.CompareTo(NextFrame?.Time); + var compare = time.CompareTo(next?.Time); - if (compare == 0 || compare == currentDirection) + if (next != null && (compare == 0 || compare == currentDirection)) { if (advanceFrame()) return CurrentTime = CurrentFrame.Time; } else { - // if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. + // this is the case where the frame can't be advanced (in the replay). + // even so, we may be able to move the clock forward due to being at the end of the replay or + // in a section where replay accuracy doesn't matter. + + // important section is always respected to block the update loop. if (inImportantSection) return null; + + if (next == null) + { + // in the case we have no more frames and haven't received the full replay, block. + if (!replay.HasReceivedAllFrames) + return null; + + // else allow play to end. + } + else if (next.Time.CompareTo(time) != currentDirection) + { + // in the case we have more frames, block if the next frame's time is less than the current time. + return null; + } + + // if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. } } diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 28b7975a89..fb6c7d4c17 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -96,6 +96,7 @@ namespace osu.Game.Rulesets.UI public override bool UpdateSubTree() { requireMoreUpdateLoops = true; + validState = !frameStableClock.IsPaused.Value; int loops = 0; @@ -191,7 +192,7 @@ namespace osu.Game.Rulesets.UI finally { if (newProposedTime != manualClock.CurrentTime) - direction = newProposedTime > manualClock.CurrentTime ? 1 : -1; + direction = newProposedTime >= manualClock.CurrentTime ? 1 : -1; manualClock.CurrentTime = newProposedTime; manualClock.Rate = Math.Abs(parentGameplayClock.Rate) * direction;