diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 954871595e..a42b7d54ee 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -84,11 +84,11 @@ namespace osu.Game.Tests.NonVisual // exited important section setTime(8200, 8000); confirmCurrentFrame(7); - confirmNextFrame(7); + confirmNextFrame(null); setTime(8200, 8200); confirmCurrentFrame(7); - confirmNextFrame(7); + confirmNextFrame(null); } [Test] @@ -97,11 +97,11 @@ namespace osu.Game.Tests.NonVisual setReplayFrames(); setTime(-1000, -1000); - confirmCurrentFrame(0); + confirmCurrentFrame(null); confirmNextFrame(0); setTime(-500, -500); - confirmCurrentFrame(0); + confirmCurrentFrame(null); confirmNextFrame(0); setTime(0, 0); @@ -145,7 +145,7 @@ namespace osu.Game.Tests.NonVisual confirmNextFrame(1); setTime(-500, -500); - confirmCurrentFrame(0); + confirmCurrentFrame(null); confirmNextFrame(0); } @@ -231,7 +231,7 @@ namespace osu.Game.Tests.NonVisual Assert.IsFalse(handler.WaitingForFrame, "Should not be waiting yet"); setTime(1000, 1000); confirmCurrentFrame(1); - confirmNextFrame(1); + confirmNextFrame(null); Assert.IsTrue(handler.WaitingForFrame, "Should be waiting"); // cannot seek beyond the last frame @@ -243,7 +243,7 @@ namespace osu.Game.Tests.NonVisual // can seek to the point before the first frame, however setTime(-100, -100); - confirmCurrentFrame(0); + confirmCurrentFrame(null); confirmNextFrame(0); fastForwardToPoint(1000); @@ -311,14 +311,14 @@ namespace osu.Game.Tests.NonVisual Assert.AreEqual(expect, handler.SetFrameFromTime(set), "Unexpected return value"); } - private void confirmCurrentFrame(int frame) + private void confirmCurrentFrame(int? frame) { - Assert.AreEqual(replay.Frames[frame].Time, handler.CurrentFrame.Time, "Unexpected current frame"); + Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.CurrentFrame?.Time, "Unexpected current frame"); } - private void confirmNextFrame(int frame) + private void confirmNextFrame(int? frame) { - Assert.AreEqual(replay.Frames[frame].Time, handler.NextFrame.Time, "Unexpected next frame"); + Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.NextFrame?.Time, "Unexpected next frame"); } private class TestReplayFrame : ReplayFrame diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index c3cd957f0d..a7f11b1e6f 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -30,6 +30,7 @@ namespace osu.Game.Rulesets.Replays /// The current frame of the replay. /// The current time is always between the start and the end time of the current frame. /// + /// Returns null if the current time is strictly before the first frame. /// The replay is empty. public TFrame CurrentFrame { @@ -38,15 +39,15 @@ namespace osu.Game.Rulesets.Replays if (!HasFrames) throw new InvalidOperationException($"Attempted to get {nameof(CurrentFrame)} of an empty replay"); - return (TFrame)Frames[Math.Max(0, currentFrameIndex)]; + return currentFrameIndex == -1 ? null : (TFrame)Frames[currentFrameIndex]; } } /// /// The next frame of the replay. /// The start time is always greater or equal to the start time of regardless of the seeking direction. - /// If it is before the first frame of the replay or the after the last frame of the replay, and agree. /// + /// Returns null if the current frame is the last frame. /// The replay is empty. public TFrame NextFrame { @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Replays if (!HasFrames) throw new InvalidOperationException($"Attempted to get {nameof(NextFrame)} of an empty replay"); - return (TFrame)Frames[Math.Min(currentFrameIndex + 1, Frames.Count - 1)]; + return currentFrameIndex == Frames.Count - 1 ? null : (TFrame)Frames[currentFrameIndex + 1]; } } @@ -96,7 +97,7 @@ namespace osu.Game.Rulesets.Replays { get { - if (!HasFrames || !FrameAccuratePlayback) + if (!HasFrames || !FrameAccuratePlayback || CurrentFrame == null) return false; return IsImportant(CurrentFrame) && // a button is in a pressed state