using UnityEngine.XR.Interaction.Toolkit.Utilities.Internal;
namespace UnityEngine.XR.Interaction.Toolkit.Utilities
{
///
/// A cache for a Unity Object reference that is used to avoid the overhead of the Unity Object alive check
/// every time the reference is accessed after the first time.
///
/// The type of the serialized field.
class UnityObjectReferenceCache where T : Object
{
T m_CapturedField;
T m_FieldOrNull;
///
/// A fast but unsafe method for getting the field without doing a Unity Object alive check after the first time.
/// The purpose is to avoid the overhead of the Unity Object alive check when it is known that the reference is alive,
/// but does not have the rigor of detecting when the Object is deleted or destroyed after the first check, which should be very rare.
/// This will handle the user modifying the field in the Inspector window by invalidating the cached version.
///
/// The serialized field to get.
/// The Unity Object or actual .
/// Returns if the reference is not null. Otherwise, returns .
public bool TryGet(T field, out T fieldOrNull)
{
if (ReferenceEquals(m_CapturedField, field))
{
fieldOrNull = m_FieldOrNull;
#pragma warning disable UNT0029 // bypass Unity Object alive check
return m_FieldOrNull is not null;
#pragma warning restore UNT0029
}
m_CapturedField = field;
if (field != null)
{
m_FieldOrNull = field;
fieldOrNull = field;
return true;
}
m_FieldOrNull = null;
fieldOrNull = null;
return false;
}
}
///
/// A cache for a serialized Unity Object reference that represents an interface type.
///
/// Interface that the reference Unity Object should implement.
/// Serialized field type, usually Unity .
///
class UnityObjectReferenceCache where TInterface : class where TObject : Object
{
TObject m_CapturedObject;
TInterface m_Interface;
///
/// Gets the interface-typed Object reference.
///
/// The serialized field to get.
/// Returns the interface-typed Object reference, which may be .
public TInterface Get(TObject field)
{
if (ReferenceEquals(m_CapturedObject, field))
return m_Interface;
m_CapturedObject = field;
m_Interface = field as TInterface;
return m_Interface;
}
///
/// Sets the Object reference to the interface-typed reference.
///
/// The serialized field to set.
/// The interface-typed value.
// ReSharper disable once RedundantAssignment -- ref field is used to update the serialized field with the new value
public void Set(ref TObject field, TInterface value)
{
field = value as TObject;
m_CapturedObject = field;
m_Interface = value;
}
}
}