using System;
using System.Collections.Generic;
namespace UnityEngine.XR.Interaction.Toolkit.Utilities
{
///
///
///
///
///
///
///
/// This is a variation of that can be used when changes in registration
/// is done infrequently. This class is also smaller in size since it does not have fields
/// which are more useful when the number of registered items is large and when registration changes happens
/// more frequently.
///
///
///
class SmallRegistrationList : BaseRegistrationList
{
bool m_BufferChanges = true;
///
/// Whether this list should buffer changes, the default value is .
/// Assign a value to make all changes take effect immediately. This is useful when
/// changes should be buffered only when the list is being processed.
///
///
/// When assign a value, and if needed, this property automatically calls to guarantee the
/// order of buffered changes.
///
public bool bufferChanges
{
get => m_BufferChanges;
set
{
if (m_BufferChanges && value == false)
{
m_BufferChanges = false;
Flush();
}
else
{
m_BufferChanges = value;
}
}
}
///
public override bool IsRegistered(T item) => (bufferedAddCount > 0 && m_BufferedAdd.Contains(item)) ||
(registeredSnapshot.Count > 0 && registeredSnapshot.Contains(item) && IsStillRegistered(item));
///
public override bool IsStillRegistered(T item) => bufferedRemoveCount == 0 || !m_BufferedRemove.Contains(item);
///
public override bool Register(T item)
{
if (!bufferChanges)
{
if (registeredSnapshot.Contains(item))
return false;
registeredSnapshot.Add(item);
return true;
}
if (bufferedAddCount > 0 && m_BufferedAdd.Contains(item))
return false;
var snapshotContainsItem = registeredSnapshot.Contains(item);
if ((bufferedRemoveCount > 0 && RemoveFromBufferedRemove(item)) || !snapshotContainsItem)
{
if (!snapshotContainsItem)
AddToBufferedAdd(item);
return true;
}
return false;
}
///
public override bool Unregister(T item)
{
if (!bufferChanges)
return registeredSnapshot.Remove(item);
if (bufferedRemoveCount > 0 && m_BufferedRemove.Contains(item))
return false;
if (bufferedAddCount > 0 && RemoveFromBufferedAdd(item))
return true;
if (registeredSnapshot.Contains(item))
{
AddToBufferedRemove(item);
return true;
}
return false;
}
///
public override void Flush()
{
// This method is called multiple times each frame,
// so additional explicit Count checks are done for
// performance.
if (bufferedRemoveCount > 0)
{
foreach (var item in m_BufferedRemove)
{
registeredSnapshot.Remove(item);
}
ClearBufferedRemove();
}
if (bufferedAddCount > 0)
{
foreach (var item in m_BufferedAdd)
{
if (!registeredSnapshot.Contains(item))
{
registeredSnapshot.Add(item);
}
}
ClearBufferedAdd();
}
}
///
public override void GetRegisteredItems(List results)
{
if (results == null)
throw new ArgumentNullException(nameof(results));
results.Clear();
EnsureCapacity(results, flushedCount);
foreach (var item in registeredSnapshot)
{
if (bufferedRemoveCount > 0 && m_BufferedRemove.Contains(item))
continue;
results.Add(item);
}
if (bufferedAddCount > 0)
results.AddRange(m_BufferedAdd);
}
///
public override T GetRegisteredItemAt(int index)
{
if (index < 0 || index >= flushedCount)
throw new ArgumentOutOfRangeException(nameof(index), "Index was out of range. Must be non-negative and less than the size of the registration collection.");
if (bufferedRemoveCount == 0 && bufferedAddCount == 0)
return registeredSnapshot[index];
if (index >= registeredSnapshot.Count - bufferedRemoveCount)
return m_BufferedAdd[index - (registeredSnapshot.Count - bufferedRemoveCount)];
var effectiveIndex = 0;
foreach (var item in registeredSnapshot)
{
if (bufferedRemoveCount > 0 && m_BufferedRemove.Contains(item))
continue;
if (effectiveIndex == index)
return registeredSnapshot[index];
++effectiveIndex;
}
// Unreachable code
throw new ArgumentOutOfRangeException(nameof(index), "Index was out of range. Must be non-negative and less than the size of the registration collection.");
}
}
}