From 148e26a6d49d50860d4f8fb1b3dbe47c4eee3c56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Mar 2019 12:40:40 +0900 Subject: [PATCH 1/7] Fix FramedReplayInputHandler starting at frame 0 when it shouldn't --- .../Replays/OsuFramedReplayInputHandler.cs | 10 ++++--- .../Replays/FramedReplayInputHandler.cs | 27 +++---------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index d1ac77857d..1765cde3a3 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -18,16 +18,18 @@ public OsuFramedReplayInputHandler(Replay replay) { } - protected override bool IsImportant(OsuReplayFrame frame) => frame.Actions.Any(); + protected override bool IsImportant(OsuReplayFrame frame) => frame?.Actions.Any() ?? false; protected Vector2? Position { get { - if (!HasFrames) + var frame = CurrentFrame; + + if (frame == null) return null; - return Interpolation.ValueAt(CurrentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); + return Interpolation.ValueAt(CurrentTime, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); } } @@ -41,7 +43,7 @@ public override List GetPendingInputs() }, new ReplayState { - PressedActions = CurrentFrame.Actions + PressedActions = CurrentFrame?.Actions ?? new List() } }; } diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index c89ac59e10..133fe99ca8 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using osu.Game.Input.Handlers; using osu.Game.Replays; using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Replays { @@ -22,12 +21,12 @@ public abstract class FramedReplayInputHandler : ReplayInputHandler protected List Frames => replay.Frames; - public TFrame CurrentFrame => !HasFrames ? null : (TFrame)Frames[currentFrameIndex]; + public TFrame CurrentFrame => !HasFrames || !currentFrameIndex.HasValue ? null : (TFrame)Frames[currentFrameIndex.Value]; public TFrame NextFrame => !HasFrames ? null : (TFrame)Frames[nextFrameIndex]; - private int currentFrameIndex; + private int? currentFrameIndex; - private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1); + private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { @@ -47,9 +46,6 @@ private bool advanceFrame() public override List GetPendingInputs() => new List(); - public bool AtLastFrame => currentFrameIndex == Frames.Count - 1; - public bool AtFirstFrame => currentFrameIndex == 0; - private const double sixty_frame_time = 1000.0 / 60; protected double CurrentTime { get; private set; } @@ -106,22 +102,5 @@ private bool advanceFrame() return CurrentTime = time; } - - protected class ReplayMouseState : osu.Framework.Input.States.MouseState - { - public ReplayMouseState(Vector2 position) - { - Position = position; - } - } - - protected class ReplayKeyboardState : osu.Framework.Input.States.KeyboardState - { - public ReplayKeyboardState(List keys) - { - foreach (var key in keys) - Keys.Add(key); - } - } } } From 09a7950a3b01372c233894901a087f55d5339d6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Mar 2019 15:09:06 +0900 Subject: [PATCH 2/7] Fix handlers for other rulesets --- .../Replays/CatchFramedReplayInputHandler.cs | 6 ++++-- .../Replays/ManiaFramedReplayInputHandler.cs | 2 +- .../Replays/TaikoFramedReplayInputHandler.cs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index dd0223314d..91f5c52440 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -22,10 +22,12 @@ protected float? Position { get { - if (!HasFrames) + var frame = CurrentFrame; + + if (frame == null) return null; - return Interpolation.ValueAt(CurrentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); + return Interpolation.ValueAt(CurrentTime, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index 197b105437..899718b77e 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -18,6 +18,6 @@ public ManiaFramedReplayInputHandler(Replay replay) protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any(); - public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame.Actions } }; + public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() } }; } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index d97d7626ef..97337acc45 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -18,6 +18,6 @@ public TaikoFramedReplayInputHandler(Replay replay) protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any(); - public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame.Actions } }; + public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() } }; } } From 70f99400ad066d380fd80c73d11ef37aee5a9d14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Mar 2019 19:28:13 +0900 Subject: [PATCH 3/7] Fix many behavioural issues and add tests --- .../Replays/CatchFramedReplayInputHandler.cs | 5 +- .../Replays/OsuFramedReplayInputHandler.cs | 5 +- .../NonVisual/FramedReplayinputHandlerTest.cs | 211 ++++++++++++++++++ .../Replays/FramedReplayInputHandler.cs | 42 ++-- 4 files changed, 245 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 91f5c52440..c6c6ccd1f3 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; using osu.Game.Replays; @@ -27,7 +28,9 @@ protected float? Position if (frame == null) return null; - return Interpolation.ValueAt(CurrentTime, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); + Debug.Assert(CurrentTime != null); + + return Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index 1765cde3a3..b96a477e42 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; @@ -29,7 +30,9 @@ protected Vector2? Position if (frame == null) return null; - return Interpolation.ValueAt(CurrentTime, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); + Debug.Assert(CurrentTime != null); + + return Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); } } diff --git a/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs new file mode 100644 index 0000000000..05bcef7d16 --- /dev/null +++ b/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs @@ -0,0 +1,211 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Game.Replays; +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class FramedReplayinputHandlerTest + { + private Replay replay; + private TestInputHandler handler; + + [SetUp] + public void SetUp() + { + handler = new TestInputHandler(replay = new Replay + { + Frames = new List + { + new TestReplayFrame(0), + new TestReplayFrame(1000), + new TestReplayFrame(2000), + new TestReplayFrame(3000, true), + new TestReplayFrame(4000, true), + new TestReplayFrame(5000, true), + new TestReplayFrame(7000, true), + new TestReplayFrame(8000), + } + }); + } + + [Test] + public void TestNormalPlayback() + { + Assert.IsNull(handler.CurrentFrame); + + confirmCurrentFrame(null); + confirmNextFrame(0); + + setTime(0, 0); + confirmCurrentFrame(0); + confirmNextFrame(1); + + //if we hit the first frame perfectly, time should progress to it. + setTime(1000, 1000); + confirmCurrentFrame(1); + confirmNextFrame(2); + + //in between non-important frames should progress based on input. + setTime(1200, 1200); + confirmCurrentFrame(1); + + setTime(1400, 1400); + confirmCurrentFrame(1); + + // progressing beyond the next frame should force time to that frame once. + setTime(2200, 2000); + confirmCurrentFrame(2); + + // second attempt should progress to input time + setTime(2200, 2200); + confirmCurrentFrame(2); + + // entering important section + setTime(3000, 3000); + confirmCurrentFrame(3); + + // cannot progress within + setTime(3500, null); + confirmCurrentFrame(3); + + setTime(4000, 4000); + confirmCurrentFrame(4); + + // still cannot progress + setTime(4500, null); + confirmCurrentFrame(4); + + setTime(5200, 5000); + confirmCurrentFrame(5); + + // important section AllowedImportantTimeSpan allowance + setTime(5200, 5200); + confirmCurrentFrame(5); + + setTime(7200, 7000); + confirmCurrentFrame(6); + + setTime(7200, null); + confirmCurrentFrame(6); + + // exited important section + setTime(8200, 8000); + confirmCurrentFrame(7); + confirmNextFrame(null); + + setTime(8200, 8200); + confirmCurrentFrame(7); + confirmNextFrame(null); + } + + [Test] + public void TestIntroTime() + { + setTime(-1000, -1000); + confirmCurrentFrame(null); + confirmNextFrame(0); + + setTime(-500, -500); + confirmCurrentFrame(null); + confirmNextFrame(0); + + setTime(0, 0); + confirmCurrentFrame(0); + confirmNextFrame(1); + } + + [Test] + public void TestBasicRewind() + { + setTime(3000, 0); + setTime(3000, 1000); + setTime(3000, 2000); + setTime(3000, 3000); + confirmCurrentFrame(3); + confirmNextFrame(4); + + setTime(1980, 2000); + confirmCurrentFrame(2); + confirmNextFrame(1); + + setTime(1980, 1980); + confirmCurrentFrame(2); + confirmNextFrame(1); + + setTime(1200, 1200); + confirmCurrentFrame(2); + confirmNextFrame(1); + + setTime(-500, 1000); + confirmCurrentFrame(1); + confirmNextFrame(0); + + setTime(-500, 0); + confirmCurrentFrame(0); + confirmNextFrame(null); + + setTime(-500, -500); + confirmCurrentFrame(0); + confirmNextFrame(null); + } + + private void setTime(double set, double? expect) + { + Assert.AreEqual(expect, handler.SetFrameFromTime(set)); + } + + private void confirmCurrentFrame(int? frame) + { + if (frame.HasValue) + { + Assert.IsNotNull(handler.CurrentFrame); + Assert.AreEqual(replay.Frames[frame.Value].Time, handler.CurrentFrame.Time); + } + else + { + Assert.IsNull(handler.CurrentFrame); + } + } + + private void confirmNextFrame(int? frame) + { + if (frame.HasValue) + { + Assert.IsNotNull(handler.NextFrame); + Assert.AreEqual(replay.Frames[frame.Value].Time, handler.NextFrame.Time); + } + else + { + Assert.IsNull(handler.NextFrame); + } + } + + private class TestReplayFrame : ReplayFrame + { + public readonly bool IsImportant; + + public TestReplayFrame(double time, bool isImportant = false) + : base(time) + { + IsImportant = isImportant; + } + } + + private class TestInputHandler : FramedReplayInputHandler + { + public TestInputHandler(Replay replay) + : base(replay) + { + } + + protected override double AllowedImportantTimeSpan => 1000; + + protected override bool IsImportant(TestReplayFrame frame) => frame?.IsImportant ?? false; + } + } +} diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 133fe99ca8..acd19721f5 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -22,7 +22,7 @@ public abstract class FramedReplayInputHandler : ReplayInputHandler protected List Frames => replay.Frames; public TFrame CurrentFrame => !HasFrames || !currentFrameIndex.HasValue ? null : (TFrame)Frames[currentFrameIndex.Value]; - public TFrame NextFrame => !HasFrames ? null : (TFrame)Frames[nextFrameIndex]; + public TFrame NextFrame => !HasFrames || ((currentDirection > 0 && currentFrameIndex == Frames.Count - 1) || (currentDirection < 0 && currentFrameIndex == 0)) ? null : (TFrame)Frames[nextFrameIndex]; private int? currentFrameIndex; @@ -48,7 +48,10 @@ private bool advanceFrame() private const double sixty_frame_time = 1000.0 / 60; - protected double CurrentTime { get; private set; } + protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2; + + protected double? CurrentTime { get; private set; } + private int currentDirection; /// @@ -64,7 +67,7 @@ private bool advanceFrame() //a button is in a pressed state IsImportant(currentDirection > 0 ? CurrentFrame : NextFrame) && //the next frame is within an allowable time span - Math.Abs(CurrentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2; + Math.Abs(CurrentTime - NextFrame?.Time ?? 0) <= AllowedImportantTimeSpan; protected virtual bool IsImportant(TFrame frame) => false; @@ -77,27 +80,34 @@ private bool advanceFrame() /// The usable time value. If null, we should not advance time as we do not have enough data. public override double? SetFrameFromTime(double time) { - currentDirection = time.CompareTo(CurrentTime); - if (currentDirection == 0) currentDirection = 1; + if (!CurrentTime.HasValue) + { + CurrentTime = time; + currentDirection = 1; + } + else + { + currentDirection = time.CompareTo(CurrentTime); + if (currentDirection == 0) currentDirection = 1; + } if (HasFrames) { - // check if the next frame is in the "future" for the current playback direction - if (currentDirection != time.CompareTo(NextFrame.Time)) + // 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); + + if (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. if (inImportantSection) return null; } - else if (advanceFrame()) - { - // If going backwards, we need to execute once _before_ the frame time to reverse any judgements - // that would occur as a result of this frame in forward playback - if (currentDirection == -1) - return CurrentTime = CurrentFrame.Time - 1; - - return CurrentTime = CurrentFrame.Time; - } } return CurrentTime = time; From d770dac3bc3cc957d60ffa540d611e6f3c5bedef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2019 00:35:26 +0900 Subject: [PATCH 4/7] Fix interpolation nullrefs --- .../Replays/CatchFramedReplayInputHandler.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index c6c6ccd1f3..103aa6c3f1 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -30,7 +30,7 @@ protected float? Position Debug.Assert(CurrentTime != null); - return Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); + return NextFrame != null ? Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time) : frame.Position; } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index b96a477e42..614edba400 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -32,7 +32,7 @@ protected Vector2? Position Debug.Assert(CurrentTime != null); - return Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time); + return NextFrame != null ? Interpolation.ValueAt(CurrentTime.Value, frame.Position, NextFrame.Position, frame.Time, NextFrame.Time) : frame.Position; } } From 82b9dfdeb1a73f3f29a7e20dfe54f756e51ef26d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2019 11:34:39 +0900 Subject: [PATCH 5/7] Add important section rewind tests --- .../NonVisual/FramedReplayinputHandlerTest.cs | 87 +++++++++++++++++-- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs index 05bcef7d16..976bb3e177 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs @@ -122,17 +122,19 @@ public void TestIntroTime() [Test] public void TestBasicRewind() { - setTime(3000, 0); - setTime(3000, 1000); - setTime(3000, 2000); - setTime(3000, 3000); - confirmCurrentFrame(3); - confirmNextFrame(4); + setTime(2800, 0); + setTime(2800, 1000); + setTime(2800, 2000); + setTime(2800, 2800); + confirmCurrentFrame(2); + confirmNextFrame(3); - setTime(1980, 2000); + // pivot without crossing a frame boundary + setTime(2700, 2700); confirmCurrentFrame(2); confirmNextFrame(1); + // cross current frame boundary; should not yet update frame setTime(1980, 1980); confirmCurrentFrame(2); confirmNextFrame(1); @@ -141,6 +143,7 @@ public void TestBasicRewind() confirmCurrentFrame(2); confirmNextFrame(1); + //ensure each frame plays out until start setTime(-500, 1000); confirmCurrentFrame(1); confirmNextFrame(0); @@ -154,6 +157,76 @@ public void TestBasicRewind() confirmNextFrame(null); } + [Test] + public void TestRewindInsideImportantSection() + { + // fast forward to important section + while (handler.SetFrameFromTime(3000) != null) + { + } + + setTime(4000, 4000); + confirmCurrentFrame(4); + confirmNextFrame(5); + + setTime(3500, null); + confirmCurrentFrame(4); + confirmNextFrame(3); + + setTime(3000, 3000); + confirmCurrentFrame(3); + confirmNextFrame(2); + + setTime(3500, null); + confirmCurrentFrame(3); + confirmNextFrame(4); + + setTime(4000, 4000); + confirmCurrentFrame(4); + confirmNextFrame(5); + + setTime(4500, null); + confirmCurrentFrame(4); + confirmNextFrame(5); + + setTime(4000, null); + confirmCurrentFrame(4); + confirmNextFrame(5); + + setTime(3500, null); + confirmCurrentFrame(4); + confirmNextFrame(3); + + setTime(3000, 3000); + confirmCurrentFrame(3); + confirmNextFrame(2); + } + + [Test] + public void TestRewindOutOfImportantSection() + { + // fast forward to important section + while (handler.SetFrameFromTime(3500) != null) + { + } + + confirmCurrentFrame(3); + confirmNextFrame(4); + + setTime(3200, null); + // next frame doesn't change even though direction reversed, because of important section. + confirmCurrentFrame(3); + confirmNextFrame(4); + + setTime(3000, null); + confirmCurrentFrame(3); + confirmNextFrame(4); + + setTime(2800, 2800); + confirmCurrentFrame(3); + confirmNextFrame(2); + } + private void setTime(double set, double? expect) { Assert.AreEqual(expect, handler.SetFrameFromTime(set)); From 5b0aa7bf8d52f29f52378313ad9a182678eaeb71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2019 12:38:40 +0900 Subject: [PATCH 6/7] Split out current/next frame conditionals for readability --- .../Replays/FramedReplayInputHandler.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index acd19721f5..361cae910f 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -21,8 +21,33 @@ public abstract class FramedReplayInputHandler : ReplayInputHandler protected List Frames => replay.Frames; - public TFrame CurrentFrame => !HasFrames || !currentFrameIndex.HasValue ? null : (TFrame)Frames[currentFrameIndex.Value]; - public TFrame NextFrame => !HasFrames || ((currentDirection > 0 && currentFrameIndex == Frames.Count - 1) || (currentDirection < 0 && currentFrameIndex == 0)) ? null : (TFrame)Frames[nextFrameIndex]; + public TFrame CurrentFrame + { + get + { + if (!HasFrames || !currentFrameIndex.HasValue) + return null; + + return (TFrame)Frames[currentFrameIndex.Value]; + } + } + + public TFrame NextFrame + { + get + { + if (!HasFrames) + return null; + + if (!currentFrameIndex.HasValue) + return (TFrame)Frames[0]; + + if (currentDirection > 0) + return currentFrameIndex == Frames.Count - 1 ? null : (TFrame)Frames[currentFrameIndex.Value + 1]; + else + return currentFrameIndex == 0 ? null : (TFrame)Frames[nextFrameIndex]; + } + } private int? currentFrameIndex; From e7b38cdc755151068417a00c3726f77cd2b7d64d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2019 12:38:47 +0900 Subject: [PATCH 7/7] Remove unnecessary set --- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 361cae910f..178e1c2364 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -107,7 +107,6 @@ private bool advanceFrame() { if (!CurrentTime.HasValue) { - CurrentTime = time; currentDirection = 1; } else