using System; using System.Collections; using System.Collections.Generic; using JetBrains.Annotations; using UnityEngine; using Object = UnityEngine.Object; namespace OCES { public class ResourceLoader : MonoBehaviour { readonly Dictionary m_cachedObjects = new(); readonly Dictionary>> m_pendingCallbacks = new(); IAssetProvider m_assetProvider; public void SetProvider(IAssetProvider assetProvider) { this.m_assetProvider = assetProvider; } [CanBeNull] internal T LoadSync(string path) where T : Object { if (this.m_cachedObjects.TryGetValue(path, out Object cachedObject)) { return cachedObject as T; } T newObject; if (this.m_assetProvider is not null) { newObject = this.m_assetProvider.Load(path); } else { newObject = Resources.Load(path); Debug.LogWarning($"[ResourceLoader] No IAssetProvider set, falling back to Resources.Load for '{path}'"); } this.m_cachedObjects.Add(path, newObject); return newObject; } internal void LoadAsync(string path, Action onComplete) where T : Object { if (this.m_cachedObjects.TryGetValue(path, out Object cachedObject)) { onComplete?.Invoke(cachedObject as T); return; } if (this.m_pendingCallbacks.TryGetValue(path, out List> callbacks)) { callbacks.Add(obj => onComplete?.Invoke(obj as T)); return; } this.m_pendingCallbacks[path] = new List> { obj => onComplete?.Invoke(obj as T) }; if (this.m_assetProvider is not null) { this.m_assetProvider.LoadAsync(path, this, asset => { OnAsyncAssetLoaded(path, asset as Object); }); } else { Debug.LogWarning($"[ResourceLoader] No IAssetProvider set, falling back to Resources.Load for '{path}'"); StartCoroutine(FallbackLoadAsyncCoroutine(path)); } } IEnumerator FallbackLoadAsyncCoroutine(string path) where T : Object { ResourceRequest request = Resources.LoadAsync(path); yield return request; OnAsyncAssetLoaded(path, request.asset); } void OnAsyncAssetLoaded(string path, Object asset) { if (asset) { this.m_cachedObjects[path] = asset; } if (this.m_pendingCallbacks.Remove(path, out List> callbacks)) { foreach (Action callback in callbacks) { callback?.Invoke(asset); } } } internal void PreloadAsync(string[] paths) { } internal void Release(string path) { } internal void ReleaseUnused() { } } }