diff --git a/src/Core/ReplayPlayback.cs b/src/Core/ReplayPlayback.cs index 471e657..89663cb 100644 --- a/src/Core/ReplayPlayback.cs +++ b/src/Core/ReplayPlayback.cs @@ -106,7 +106,7 @@ public void HandlePlayback() if (elapsedPlaybackTime >= currentReplay.Frames[^1].Time) { - SetPlaybackTime(currentReplay.Frames[^1].Time); + UpdatePlayback(currentReplay.Frames[^1].Time); if (Main.instance.StopReplayWhenDone.Value) StopReplay(); @@ -116,7 +116,7 @@ public void HandlePlayback() if (elapsedPlaybackTime <= 0f) { - SetPlaybackTime(0f); + UpdatePlayback(0f); if (Main.instance.StopReplayWhenDone.Value) StopReplay(); @@ -124,7 +124,7 @@ public void HandlePlayback() return; } - SetPlaybackTime(elapsedPlaybackTime); + UpdatePlayback(elapsedPlaybackTime); ReplayPlaybackControls.timeline?.GetComponent()?.material?.SetFloat("_BP_Current", elapsedPlaybackTime * 1000f); @@ -606,6 +606,8 @@ private IEnumerator SpawnClones(Action done = null) temp.gameObject.SetActive(true); PlaybackPlayers[i] = temp; temp.Controller.transform.SetParent(replayPlayers.transform); + + ReplayAPI.CloneSpawnedInternal(temp); } done?.Invoke(); @@ -1553,6 +1555,8 @@ public void SetPlaybackSpeed(float newSpeed) ReplayPlaybackControls.playbackSpeedText.text = label; ReplayPlaybackControls.playbackSpeedText.ForceMeshUpdate(); } + + ReplayAPI.ReplaySpeedChangedInternal(newSpeed); } public void AddPlaybackSpeed(float delta, float minSpeed = -8f, float maxSpeed = 8f) @@ -1579,6 +1583,11 @@ public void SetPlaybackFrame(int frame) } public void SetPlaybackTime(float time) + { + UpdatePlayback(time); + } + + public void UpdatePlayback(float time) { float oldTime = elapsedPlaybackTime; diff --git a/src/Replay/ReplayAPI.cs b/src/Replay/ReplayAPI.cs index fe28f49..834325a 100644 --- a/src/Replay/ReplayAPI.cs +++ b/src/Replay/ReplayAPI.cs @@ -60,6 +60,16 @@ public static class ReplayAPI /// Invoked when the playback time changes (seek or progression). /// public static event Action onReplayTimeChanged; + + /// + /// Invoked when the playback time changes (seek only). + /// + public static event Action onReplaySeeked; + + /// + /// Invoked when the playback speed changes. + /// + public static event Action onSpeedChanged; /// /// Invoked when playback is paused or resumed, along with the new toggle state. @@ -93,6 +103,11 @@ public static class ReplayAPI /// public static event Action onReplayRenamed; + /// + /// Invoked as a clone is spawned or reset. + /// + public static event Action onCloneSpawned; + private static void InvokeSafe(Delegate action, params object[] args) { if (action == null) @@ -126,8 +141,9 @@ private static void InvokeSafe(Delegate action, params object[] args) internal static void RecordingStartedInternal() => InvokeSafe(onRecordingStarted); internal static void RecordingStoppedInternal() => InvokeSafe(onRecordingStopped); internal static void ReplayTimeChangedInternal(float time) => InvokeSafe(onReplayTimeChanged, time); + internal static void ReplaySeekedInternal(float time) => InvokeSafe(onReplaySeeked, time); internal static void ReplayPauseChangedInternal(bool paused) => InvokeSafe(onReplayPauseChanged, paused); - + internal static void ReplaySpeedChangedInternal(float time) => InvokeSafe(onSpeedChanged, time); internal static void OnPlaybackFrameInternal(Frame frame, Frame nextFrame) => InvokeSafe(OnPlaybackFrame, frame, nextFrame); internal static void OnRecordFrameInternal(Frame frame, bool isBuffer) => InvokeSafe(OnRecordFrame, frame, isBuffer); @@ -135,6 +151,8 @@ private static void InvokeSafe(Delegate action, params object[] args) internal static void ReplayDeletedInternal(string path) => InvokeSafe(onReplayDeleted, path); internal static void ReplayRenamedInternal(ReplaySerializer.ReplayHeader header, string newPath) => InvokeSafe(onReplayRenamed, header, newPath); + internal static void CloneSpawnedInternal(ReplayPlayback.Clone clone) => InvokeSafe(onCloneSpawned, clone); + /// /// Gets whether a recording is currently active. /// This is enabled when a user manually starts recording.