using System; using System.Collections.Generic; using UnityEngine; namespace UnityGLTF.Cache { /// /// A ref-counted cache data object containing lists of Unity objects that were created for the sake of a GLTF scene/node. /// This supports counting the amount of refcounts that will dispose of itself /// public class RefCountedCacheData { private bool _isDisposed = false; /// /// Ref count for this cache data. /// /// /// Initialized to 0. When assigning the cache data to an instantiated GLTF /// object the count will increase. /// private int _refCount = 0; private readonly object _refCountLock = new object(); /// /// Meshes used by this GLTF node. /// public MeshCacheData[] MeshCache { get; private set; } /// /// Materials used by this GLTF node. /// public MaterialCacheData[] MaterialCache { get; private set; } /// /// Textures used by this GLTF node. /// public TextureCacheData[] TextureCache { get; private set; } /// /// Animations used by this GLTF node. /// public AnimationCacheData[] AnimationCache { get; private set; } /// /// Textures from the AssetCache that might need to be cleaned up /// public Texture2D[] ImageCache { get; private set; } public RefCountedCacheData(MaterialCacheData[] materialCache, MeshCacheData[] meshCache, TextureCacheData[] textureCache, Texture2D[] imageCache, AnimationCacheData[] animationCache) { MaterialCache = materialCache; MeshCache = meshCache; TextureCache = textureCache; ImageCache = imageCache; AnimationCache = animationCache; } public void IncreaseRefCount() { if (_isDisposed) { throw new InvalidOperationException("Cannot inscrease the ref count on disposed cache data."); } lock (_refCountLock) { _refCount++; } } public void DecreaseRefCount() { if (_isDisposed) { throw new InvalidOperationException("Cannot decrease the ref count on disposed cache data."); } lock (_refCountLock) { if (_refCount <= 0) { throw new InvalidOperationException("Cannot decrease the cache data ref count below zero."); } _refCount--; } if (_refCount <= 0) { DestroyCachedData(); } } private void DestroyCachedData() { // Destroy the cached meshes for (int i = 0; i < MeshCache.Length; i++) { MeshCache[i]?.Dispose(); MeshCache[i] = null; } // Destroy the cached textures for (int i = 0; i < TextureCache.Length; i++) { TextureCache[i]?.Dispose(); TextureCache[i] = null; } // Destroy the cached materials for (int i = 0; i < MaterialCache.Length; i++) { MaterialCache[i]?.Dispose(); MaterialCache[i] = null; } // Destroy the cached images for (int i = 0; i < ImageCache.Length; i++) { if (ImageCache[i] != null) { UnityEngine.Object.Destroy(ImageCache[i]); ImageCache[i] = null; } } // Destroy the cached animations for (int i = 0; i < AnimationCache.Length; i++) { if (AnimationCache[i] != null) { UnityEngine.Object.Destroy(AnimationCache[i].LoadedAnimationClip); AnimationCache[i] = null; } } _isDisposed = true; } } }