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