using System; using System.Collections; using System.Collections.Generic; using JetBrains.Annotations; using OCES.Audio; 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) }; ResourceRequest newRequest; if (this.m_assetProvider is not null) { newRequest = this.m_assetProvider.LoadAsync(path); } else { newRequest = Resources.LoadAsync(path); Debug.LogWarning($"[ResourceLoader] No IAssetProvider set, falling back to Resources.Load for '{path}'"); } StartCoroutine(HandleAsyncLoadCompletion(path, newRequest)); } IEnumerator HandleAsyncLoadCompletion(string path, ResourceRequest request) { yield return request; if (request.asset) { this.m_cachedObjects[path] = request.asset; } if (this.m_pendingCallbacks.Remove(path, out List> callbacks)) { foreach (Action callback in callbacks) { callback?.Invoke(request.asset); } } } internal void PreloadAsync(string[] paths) { } internal void Release(string path) { } internal void ReleaseUnused() { } } }