using System;
using System.Collections.Generic;
using System.Linq;
namespace UnityEngine.Rendering.HighDefinition
{
///
/// Persistent camera cache for a specific key.
///
/// Use this to have access to a stable HDCamera over frame. Usually you need this when the
/// history buffers of the HDCamera are used.
///
/// The type of the key.
class CameraCache : IDisposable
{
Dictionary m_Cache = new Dictionary();
K[] cameraKeysCache = new K[0];
/// Get or create a camera for the specified key
/// The key to look at.
///
/// The current frame count.
///
/// This frame count is assigned to the returned camera to know the age of its last use.
///
/// The type of camera to create if one does not exists.
///
/// The cached camera if the key was found,
/// otherwise a new camera that was inserted in the cache during the call.
///
public Camera GetOrCreate(K key, int frameCount, CameraType cameraType = CameraType.Game)
{
if (m_Cache == null)
throw new ObjectDisposedException(nameof(CameraCache));
if (!m_Cache.TryGetValue(key, out var camera) || camera.camera == null || camera.camera.Equals(null))
{
camera = (new GameObject().AddComponent(), frameCount);
camera.camera.cameraType = cameraType;
m_Cache[key] = camera;
}
else
{
camera.lastFrame = frameCount;
m_Cache[key] = camera;
}
return camera.camera;
}
/// Destroy all cameras that are unused more than .
/// The age of the cameras to keep.
/// The current frame count. Usually .
public void ClearCamerasUnusedFor(int frameWindow, int frameCount)
{
if (m_Cache == null)
throw new ObjectDisposedException(nameof(CameraCache));
// In case cameraKeysCache length does not matches the current cache length, we resize it:
if (cameraKeysCache.Length != m_Cache.Count)
cameraKeysCache = new K[m_Cache.Count];
// Copy keys to remove them from the dictionary (avoids collection modifed while iterating error)
m_Cache.Keys.CopyTo(cameraKeysCache, 0);
foreach (var key in cameraKeysCache)
{
if (m_Cache.TryGetValue(key, out var value))
{
if (Math.Abs(frameCount - value.lastFrame) > frameWindow)
{
if (value.camera != null)
{
CoreUtils.Destroy(value.camera.gameObject);
}
m_Cache.Remove(key);
}
}
}
}
/// Destroy all cameras in the cache.
public void Clear()
{
if (m_Cache == null)
throw new ObjectDisposedException(nameof(CameraCache));
foreach (var pair in m_Cache)
{
if (pair.Value.camera != null)
CoreUtils.Destroy(pair.Value.camera.gameObject);
}
m_Cache.Clear();
}
public void Dispose()
{
Clear();
m_Cache = null;
}
}
}