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; } } }