Skip to content

Commit 9343b0a

Browse files
committed
Links ReplayController to InputManager
Bit of logics to track replay controllers and bridge with InputManager.
1 parent 0011dc4 commit 9343b0a

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

Packages/com.unity.inputsystem/InputSystem/Events/InputEventTrace.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,8 @@ public class ReplayController : IDisposable
10721072
private double m_StartTimeAsPerRuntime;
10731073
private int m_AllEventsByTimeIndex = 0;
10741074
private List<InputEventPtr> m_AllEventsByTime;
1075+
private bool m_ReplayBypassActive;
1076+
private Action m_ClearReplayBypassCallback;
10751077

10761078
internal ReplayController(InputEventTrace trace)
10771079
{
@@ -1088,12 +1090,52 @@ public void Dispose()
10881090
{
10891091
InputSystem.onBeforeUpdate -= OnBeginFrame;
10901092
finished = true;
1093+
EndReplayBypass();
10911094

10921095
foreach (var device in m_CreatedDevices)
10931096
InputSystem.RemoveDevice(device);
10941097
m_CreatedDevices = default;
10951098
}
10961099

1100+
// Signals InputManager to treat events as if game view has focus, bypassing
1101+
// editor focus routing that would otherwise defer pointer/keyboard events to
1102+
// editor updates where they reach the editor UI instead of the game.
1103+
private void BeginReplayBypass()
1104+
{
1105+
if (!m_ReplayBypassActive)
1106+
{
1107+
m_ReplayBypassActive = true;
1108+
++InputSystem.s_Manager.m_ActiveReplayCount;
1109+
}
1110+
}
1111+
1112+
// Schedules the bypass to be cleared after the current OnUpdate finishes processing
1113+
// events (via onAfterUpdate). This ensures events already queued in the native buffer
1114+
// are still processed with the bypass active before it is removed.
1115+
private void ScheduleEndReplayBypass()
1116+
{
1117+
if (!m_ReplayBypassActive)
1118+
return;
1119+
1120+
if (m_ClearReplayBypassCallback == null)
1121+
m_ClearReplayBypassCallback = EndReplayBypass;
1122+
InputSystem.onAfterUpdate += m_ClearReplayBypassCallback;
1123+
}
1124+
1125+
private void EndReplayBypass()
1126+
{
1127+
if (m_ClearReplayBypassCallback != null)
1128+
{
1129+
InputSystem.onAfterUpdate -= m_ClearReplayBypassCallback;
1130+
m_ClearReplayBypassCallback = null;
1131+
}
1132+
if (m_ReplayBypassActive)
1133+
{
1134+
m_ReplayBypassActive = false;
1135+
--InputSystem.s_Manager.m_ActiveReplayCount;
1136+
}
1137+
}
1138+
10971139
/// <summary>
10981140
/// Replay events recorded from <paramref name="recordedDevice"/> on device <paramref name="playbackDevice"/>.
10991141
/// </summary>
@@ -1249,6 +1291,7 @@ public ReplayController Rewind()
12491291
public ReplayController PlayAllFramesOneByOne()
12501292
{
12511293
finished = false;
1294+
BeginReplayBypass();
12521295
InputSystem.onBeforeUpdate += OnBeginFrame;
12531296
return this;
12541297
}
@@ -1267,6 +1310,7 @@ public ReplayController PlayAllFramesOneByOne()
12671310
public ReplayController PlayAllEvents()
12681311
{
12691312
finished = false;
1313+
BeginReplayBypass();
12701314
try
12711315
{
12721316
while (MoveNext(true, out var eventPtr))
@@ -1311,6 +1355,7 @@ public ReplayController PlayAllEventsAccordingToTimestamps()
13111355

13121356
// Start playback.
13131357
finished = false;
1358+
BeginReplayBypass();
13141359
m_StartTimeAsPerFirstEvent = -1;
13151360
m_AllEventsByTimeIndex = -1;
13161361
InputSystem.onBeforeUpdate += OnBeginFrame;
@@ -1381,6 +1426,9 @@ private void Finished()
13811426
{
13821427
finished = true;
13831428
InputSystem.onBeforeUpdate -= OnBeginFrame;
1429+
// Schedule bypass removal for after the next OnUpdate, so any events already
1430+
// queued into the native buffer this frame are still processed with the bypass active.
1431+
ScheduleEndReplayBypass();
13841432
m_OnFinished?.Invoke();
13851433
}
13861434

0 commit comments

Comments
 (0)