using System.Collections.Generic;
using UnityEngine.Assertions;
namespace Unity.Cinemachine
{
/// Keeps track of CinemachineCameras. Sorts them by priority, and
/// by nesting level, so cameras can get updated leafmost-first.
sealed class VirtualCameraRegistry
{
/// List of all active ICinemachineCameras.
readonly List m_ActiveCameras = new ();
// Registry of all vcams that are present, active or not
readonly List> m_AllCameras = new();
bool m_ActiveCamerasAreSorted;
int m_ActivationSequence;
///
/// All cameras (active or not) sorted by nesting level. This is to enable
/// processing in leaf-first order. Level 0 is root.
///
public List> AllCamerasSortedByNestingLevel => m_AllCameras;
///
/// List of all active CinemachineCameras for all brains.
/// This list is kept sorted by priority.
///
public int ActiveCameraCount => m_ActiveCameras.Count;
/// Access the priority-sorted array of active ICinemachineCamera in the scene
/// without generating garbage
/// Index of the camera to access, range 0-VirtualCameraCount
/// The virtual camera at the specified index
public CinemachineVirtualCameraBase GetActiveCamera(int index)
{
if (!m_ActiveCamerasAreSorted && m_ActiveCameras.Count > 1)
{
m_ActiveCameras.Sort((x, y) =>
x.Priority.Value == y.Priority.Value
? y.ActivationId.CompareTo(x.ActivationId)
: y.Priority.Value.CompareTo(x.Priority.Value));
m_ActiveCamerasAreSorted = true;
}
return m_ActiveCameras[index];
}
/// Called when a CinemachineCamera is enabled.
public void AddActiveCamera(CinemachineVirtualCameraBase vcam)
{
Assert.IsFalse(m_ActiveCameras.Contains(vcam));
vcam.ActivationId = m_ActivationSequence++;
m_ActiveCameras.Add(vcam);
m_ActiveCamerasAreSorted = false;
}
/// Called when a CinemachineCamera is disabled.
public void RemoveActiveCamera(CinemachineVirtualCameraBase vcam)
{
if (m_ActiveCameras.Contains(vcam))
m_ActiveCameras.Remove(vcam);
}
/// Called when a CinemachineCamera is destroyed.
public void CameraDestroyed(CinemachineVirtualCameraBase vcam)
{
if (m_ActiveCameras.Contains(vcam))
m_ActiveCameras.Remove(vcam);
}
/// Called when a vcam is enabled.
public void CameraEnabled(CinemachineVirtualCameraBase vcam)
{
int parentLevel = 0;
for (var p = vcam.ParentCamera; p != null; p = p.ParentCamera)
++parentLevel;
while (m_AllCameras.Count <= parentLevel)
m_AllCameras.Add(new List());
m_AllCameras[parentLevel].Add(vcam);
}
/// Called when a vcam is disabled.
public void CameraDisabled(CinemachineVirtualCameraBase vcam)
{
for (int i = 0; i < m_AllCameras.Count; ++i)
m_AllCameras[i].Remove(vcam);
}
}
}