From 57ba7b7cbbbd93870978d047b6edb957cd49d8cf Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 13 Apr 2021 15:55:23 +0900 Subject: [PATCH] Partially revert the changes of `CurrentFrame` and `NextFrame` for compatibility Making those always non-null is postponed as when a replay's frame contains keypress the behavior is changed. Previously, the key is pressed at the time of the first frame. But using non-null frames means the key is pressed at negative infinity. However, I think the new way of always using non-null frames makes the client code so I plan to bundle the change to more breaking changes. --- .../NonVisual/FramedReplayInputHandlerTest.cs | 22 +++++++++---------- .../Replays/FramedReplayInputHandler.cs | 9 ++++---- 2 files changed, 16 insertions(+), 15 deletions(-) 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