JD2022-TU1/main/phone_apps/JDCompanionApp/Assets/Scripts/ResourceLoading/Loader.cs

132 lines
No EOL
4.5 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Network;
using UnityEngine;
namespace ResourceLoading
{
internal class Loader
{
private LoadingCoroutineFactory _loaderFactory = new LoadingCoroutineFactory();
private Queue<LoadingResourceData> _pendingLoading = new Queue<LoadingResourceData>();
private List<UnloadingResourceData> _pendingUnloading = new List<UnloadingResourceData>();
private ConsoleServer _resourceServer = null;
private const int UNLOAD_DELAY = 100; // in frames
private Queue<LoadWorker> _idleLoadWorkers = new Queue<LoadWorker>();
private List<LoadWorker> _busyLoadWorkers = new List<LoadWorker>();
internal void LoadResource(Resource resource)
{
resource.State = Resource.EState.Loading;
ILoadingCoroutine loader = _loaderFactory.NewLoadingCoroutineFromType(resource.Type, resource.URI);
LoadingResourceData loadingData = new LoadingResourceData { _resource = resource, _loadingCoroutine = loader, _useDiskCache = true };
_pendingLoading.Enqueue(loadingData);
}
internal void UnloadResource(Resource resource)
{
resource.State = Resource.EState.Unloading;
UnloadingResourceData data = new UnloadingResourceData{ _resource = resource, _unloadDelay = UNLOAD_DELAY };
_pendingUnloading.Add(data);
}
internal void AddWorker(LoadWorker loadWorker)
{
_idleLoadWorkers.Enqueue(loadWorker);
}
internal void Update()
{
ProcessLoading();
ProcessUnloading();
}
internal ConsoleServer ResourceServer
{
get { return _resourceServer; }
set { _resourceServer = value; }
}
private void ProcessLoading()
{
// process busy workers
var finished = _busyLoadWorkers.Where(worker => worker.Loader.IsDone).ToList();
foreach(var worker in finished)
{
worker.LoadingResource.UnityResource = worker.Loader.Resource;
if (worker.LoadingResource.UnityResource != null)
{
worker.LoadingResource.State = Resource.EState.Idle;
}
else
{
worker.LoadingResource.State = Resource.EState.Error;
}
worker.Reset();
_busyLoadWorkers.Remove(worker);
_idleLoadWorkers.Enqueue(worker);
}
finished.Clear();
// start new jobs if possible
while (_pendingLoading.Count > 0 && _idleLoadWorkers.Count > 0)
{
var loadingData = _pendingLoading.Dequeue();
var worker = _idleLoadWorkers.Dequeue();
worker.Load(loadingData._resource, _resourceServer, loadingData._loadingCoroutine, loadingData._useDiskCache);
_busyLoadWorkers.Add(worker);
}
}
private void ProcessUnloading()
{
// update unloading list
foreach(var item in _pendingUnloading)
{
if (item._resource.LoadCount == 0)
{
--item._unloadDelay;
// delay expired?
if (item._unloadDelay <= 0)
{
if (item._resource.URI.StartsWith("local://"))
UnityEngine.Resources.UnloadAsset(item._resource.UnityResource);
else
Object.Destroy(item._resource.UnityResource);
item._resource.UnityResource = null;
item._resource.State = Resource.EState.Idle;
}
}
else
{
// while unloading, someone requested loading, pass to idle state
item._resource.State = Resource.EState.Idle;
}
}
// remove from unloading all for which are not unloading anymore or unload delay has expired
_pendingUnloading.RemoveAll(item => (item._resource.LoadCount != 0 || item._unloadDelay <= 0));
}
private class LoadingResourceData
{
public Resource _resource;
public ILoadingCoroutine _loadingCoroutine;
public bool _useDiskCache;
}
private class UnloadingResourceData
{
public Resource _resource;
public int _unloadDelay;
}
}
} // namespace JDCompanionApp.Resources