IndieGame/client/Packages/com.unity.inputsystem@1.7.0/InputSystem/Utilities/CallbackArray.cs

79 lines
2.6 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00
namespace UnityEngine.InputSystem.Utilities
{
// Keeps a copy of the callback list while executing so that the callback list can safely
// be mutated from within callbacks.
internal struct CallbackArray<TDelegate>
where TDelegate : System.Delegate
{
private bool m_CannotMutateCallbacksArray;
private InlinedArray<TDelegate> m_Callbacks;
private InlinedArray<TDelegate> m_CallbacksToAdd;
private InlinedArray<TDelegate> m_CallbacksToRemove;
public int length => m_Callbacks.length;
public TDelegate this[int index] => m_Callbacks[index];
public void Clear()
{
m_Callbacks.Clear();
m_CallbacksToAdd.Clear();
m_CallbacksToRemove.Clear();
}
public void AddCallback(TDelegate dlg)
{
if (m_CannotMutateCallbacksArray)
{
if (m_CallbacksToAdd.Contains(dlg))
return;
var removeIndex = m_CallbacksToRemove.IndexOf(dlg);
if (removeIndex != -1)
m_CallbacksToRemove.RemoveAtByMovingTailWithCapacity(removeIndex);
m_CallbacksToAdd.AppendWithCapacity(dlg);
return;
}
if (!m_Callbacks.Contains(dlg))
m_Callbacks.AppendWithCapacity(dlg, capacityIncrement: 4);
}
public void RemoveCallback(TDelegate dlg)
{
if (m_CannotMutateCallbacksArray)
{
if (m_CallbacksToRemove.Contains(dlg))
return;
var addIndex = m_CallbacksToAdd.IndexOf(dlg);
if (addIndex != -1)
m_CallbacksToAdd.RemoveAtByMovingTailWithCapacity(addIndex);
m_CallbacksToRemove.AppendWithCapacity(dlg);
return;
}
var index = m_Callbacks.IndexOf(dlg);
if (index >= 0)
m_Callbacks.RemoveAtWithCapacity(index);
}
public void LockForChanges()
{
m_CannotMutateCallbacksArray = true;
}
public void UnlockForChanges()
{
m_CannotMutateCallbacksArray = false;
// Process mutations that have happened while we were executing callbacks.
for (var i = 0; i < m_CallbacksToRemove.length; ++i)
RemoveCallback(m_CallbacksToRemove[i]);
for (var i = 0; i < m_CallbacksToAdd.length; ++i)
AddCallback(m_CallbacksToAdd[i]);
m_CallbacksToAdd.Clear();
m_CallbacksToRemove.Clear();
}
}
}