Skip to content

Commit 0c4b9d2

Browse files
committed
Refactor DeferBindingResolution to remove statics (ISX-1840)
- Consolidate functionality into DeferBindingResolutionContext class - Instantiate Context object as a non-static InputManager field exposed via InputManager methods
1 parent 538107a commit 0c4b9d2

File tree

4 files changed

+80
-57
lines changed

4 files changed

+80
-57
lines changed

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionMap.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,6 @@ private enum Flags
809809
BindingsForEachActionInitialized = 1 << 3,
810810
}
811811

812-
internal static int s_DeferBindingResolution;
813-
814812
internal struct DeviceArray
815813
{
816814
private bool m_HaveValue;
@@ -1206,7 +1204,7 @@ internal bool LazyResolveBindings(bool fullResolve)
12061204
needToResolveBindings = true;
12071205
bindingResolutionNeedsFullReResolve |= fullResolve;
12081206

1209-
if (s_DeferBindingResolution > 0)
1207+
if (InputSystem.manager.areDeferredBindingsToResolve)
12101208
return false;
12111209

12121210
// Have to do it straight away.
@@ -1225,7 +1223,7 @@ internal bool ResolveBindingsIfNecessary()
12251223
{
12261224
if (m_State != null && m_State.isProcessingControlStateChange)
12271225
{
1228-
Debug.Assert(s_DeferBindingResolution > 0, "While processing control state changes, binding resolution should be suppressed");
1226+
Debug.Assert(InputSystem.manager.areDeferredBindingsToResolve, "While processing control state changes, binding resolution should be suppressed");
12291227
return false;
12301228
}
12311229

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionRebindingExtensions.cs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,39 +2776,70 @@ public static RebindingOperation PerformInteractiveRebinding(this InputAction ac
27762776
return rebind;
27772777
}
27782778

2779+
internal static DeferBindingResolutionContext DeferBindingResolution()
2780+
{
2781+
return InputSystem.manager.DeferBindingResolution();
2782+
}
2783+
}
2784+
2785+
internal class DeferBindingResolutionContext : IDisposable
2786+
{
2787+
public int deferredCount => m_DeferredCount;
2788+
2789+
public void Acquire()
2790+
{
2791+
++m_DeferredCount;
2792+
}
2793+
2794+
public void Release()
2795+
{
2796+
if (m_DeferredCount > 0)
2797+
--m_DeferredCount;
2798+
if (m_DeferredCount == 0)
2799+
ExecuteDeferredResolutionOfBindings();
2800+
}
2801+
27792802
/// <summary>
2780-
/// Temporarily suspend immediate re-resolution of bindings.
2803+
/// Allows usage within using() blocks.
27812804
/// </summary>
2782-
/// <remarks>
2783-
/// When changing control setups, it may take multiple steps to get to the final setup but each individual
2784-
/// step may trigger bindings to be resolved again in order to update controls on actions (see <see cref="InputAction.controls"/>).
2785-
/// Using this struct, this can be avoided and binding resolution can be deferred to after the whole operation
2786-
/// is complete and the final binding setup is in place.
2787-
/// </remarks>
2788-
internal static DeferBindingResolutionWrapper DeferBindingResolution()
2805+
public void Dispose()
27892806
{
2790-
if (s_DeferBindingResolutionWrapper == null)
2791-
s_DeferBindingResolutionWrapper = new DeferBindingResolutionWrapper();
2792-
s_DeferBindingResolutionWrapper.Acquire();
2793-
return s_DeferBindingResolutionWrapper;
2807+
Release();
27942808
}
27952809

2796-
private static DeferBindingResolutionWrapper s_DeferBindingResolutionWrapper;
2797-
2798-
internal class DeferBindingResolutionWrapper : IDisposable
2810+
private void ExecuteDeferredResolutionOfBindings()
27992811
{
2800-
public void Acquire()
2812+
++m_DeferredCount;
2813+
try
28012814
{
2802-
++InputActionMap.s_DeferBindingResolution;
2803-
}
2815+
ref var globalList = ref InputActionState.s_GlobalState.globalList;
28042816

2805-
public void Dispose()
2817+
for (var i = 0; i < globalList.length; ++i)
2818+
{
2819+
var handle = globalList[i];
2820+
2821+
var state = handle.IsAllocated ? (InputActionState)handle.Target : null;
2822+
if (state == null)
2823+
{
2824+
// Stale entry in the list. State has already been reclaimed by GC. Remove it.
2825+
if (handle.IsAllocated)
2826+
globalList[i].Free();
2827+
globalList.RemoveAtWithCapacity(i);
2828+
--i;
2829+
continue;
2830+
}
2831+
2832+
for (var n = 0; n < state.totalMapCount; ++n)
2833+
state.maps[n].ResolveBindingsIfNecessary();
2834+
}
2835+
}
2836+
finally
28062837
{
2807-
if (InputActionMap.s_DeferBindingResolution > 0)
2808-
--InputActionMap.s_DeferBindingResolution;
2809-
if (InputActionMap.s_DeferBindingResolution == 0)
2810-
InputActionState.DeferredResolutionOfBindings();
2838+
--m_DeferredCount;
28112839
}
28122840
}
2841+
2842+
2843+
private int m_DeferredCount;
28132844
}
28142845
}

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4486,36 +4486,6 @@ internal static void OnDeviceChange(InputDevice device, InputDeviceChange change
44864486
}
44874487
}
44884488

4489-
internal static void DeferredResolutionOfBindings()
4490-
{
4491-
++InputActionMap.s_DeferBindingResolution;
4492-
try
4493-
{
4494-
for (var i = 0; i < s_GlobalState.globalList.length; ++i)
4495-
{
4496-
var handle = s_GlobalState.globalList[i];
4497-
4498-
var state = handle.IsAllocated ? (InputActionState)handle.Target : null;
4499-
if (state == null)
4500-
{
4501-
// Stale entry in the list. State has already been reclaimed by GC. Remove it.
4502-
if (handle.IsAllocated)
4503-
s_GlobalState.globalList[i].Free();
4504-
s_GlobalState.globalList.RemoveAtWithCapacity(i);
4505-
--i;
4506-
continue;
4507-
}
4508-
4509-
for (var n = 0; n < state.totalMapCount; ++n)
4510-
state.maps[n].ResolveBindingsIfNecessary();
4511-
}
4512-
}
4513-
finally
4514-
{
4515-
--InputActionMap.s_DeferBindingResolution;
4516-
}
4517-
}
4518-
45194489
internal static void DisableAllActions()
45204490
{
45214491
for (var i = 0; i < s_GlobalState.globalList.length; ++i)

Packages/com.unity.inputsystem/InputSystem/InputManager.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public static InputManager CreateAndInitialize(IInputRuntime runtime, InputSetti
6565
{
6666
var newInst = new InputManager();
6767

68+
// Not directly used by InputManager, but we need a single instance that's used in a variety of places without a static field
69+
newInst.m_DeferBindingResolutionContext = new DeferBindingResolutionContext();
70+
6871
// If settings object wasn't provided, create a temporary settings object for now
6972
if (settings == null)
7073
{
@@ -2070,6 +2073,25 @@ internal void UninstallGlobals()
20702073
}
20712074
}
20722075

2076+
/// <summary>
2077+
/// Acquires a temporary "lock" to suspend immediate re-resolution of bindings.
2078+
/// </summary>
2079+
/// <remarks>
2080+
/// When changing control setups, it may take multiple steps to get to the final setup but each individual
2081+
/// step may trigger bindings to be resolved again in order to update controls on actions (see <see cref="InputAction.controls"/>).
2082+
/// Using Acquire/Release semantics via the returned context object, binding resolution can be deferred until the entire operation
2083+
/// is complete and the final binding setup is in place.
2084+
///
2085+
/// NOTE: Returned DeferBindingResolutionContext object is used globally for all ActionMaps.
2086+
/// </remarks>
2087+
internal DeferBindingResolutionContext DeferBindingResolution()
2088+
{
2089+
m_DeferBindingResolutionContext.Acquire();
2090+
return m_DeferBindingResolutionContext;
2091+
}
2092+
2093+
internal bool areDeferredBindingsToResolve => m_DeferBindingResolutionContext.deferredCount > 0;
2094+
20732095
[Serializable]
20742096
internal struct AvailableDevice
20752097
{
@@ -2159,6 +2181,8 @@ internal struct AvailableDevice
21592181
internal IInputDiagnostics m_Diagnostics;
21602182
#endif
21612183

2184+
private DeferBindingResolutionContext m_DeferBindingResolutionContext;
2185+
21622186
////REVIEW: Make it so that device names *always* have a number appended? (i.e. Gamepad1, Gamepad2, etc. instead of Gamepad, Gamepad1, etc)
21632187

21642188
private void MakeDeviceNameUnique(InputDevice device)

0 commit comments

Comments
 (0)