UniversalViewer/Assets/Scripts/ModelViewerBase/AssetLibrary.cs

160 lines
4.8 KiB
C#

using System.Linq;
using UnityEngine;
using System.Collections;
using Newtonsoft.Json.Linq;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using System.Collections.Generic;
using UnityEngine.ResourceManagement.ResourceLocations;
using System.IO;
using UnityEngine.UI;
public class AssetLibrary : MonoBehaviour
{
protected static AssetLibrary _mainInstance;
public ResourceLocationMap AddressableResourceMap;
public List<Shader> Shaders;
public string LocalFilesPath;
private List<string> _addressableKeys;
public Dictionary<string, AssetBundle> LoadedAssets = new Dictionary<string, AssetBundle>();
protected virtual void Awake()
{
_mainInstance = this;
}
public static T GetInstance<T>() where T : AssetLibrary
{
return _mainInstance as T;
}
public List<string> GetAddressableKeys()
{
if (_addressableKeys == null)
{
_addressableKeys = AddressableResourceMap.Keys.Select(k=>k.ToString()).ToList();
}
return _addressableKeys.ToList();
}
/// <summary>
/// Load catalog.json from games that use addressables
/// </summary>
/// <param name="catalogPath"></param>
/// <returns></returns>
public IEnumerator LoadAddressableCatalog(string catalogPath)
{
var opHandle = Addressables.LoadContentCatalogAsync(catalogPath);
yield return opHandle;
if (opHandle.Status == AsyncOperationStatus.Succeeded)
{
Debug.Log(opHandle.Result.GetType());
AddressableResourceMap = opHandle.Result as ResourceLocationMap;
}
else
{
throw opHandle.OperationException;
}
}
public string GetResourcePath(string resourceName, out List<string> dependencies)
{
dependencies = new List<string>();
var locator = AddressableResourceMap.Locations[resourceName][0]; // AddressableResourceMap.Locations[resourceName][0].Dependencies[0].Data as AssetBundleRequestOptions;
if (locator.HasDependencies)
{
GatherDependencies(locator, dependencies);
var data = locator.Dependencies[0].Data as AssetBundleRequestOptions;
var filePath = data.BundleName + "/" + data.Hash + "/" + "__data";
dependencies.Remove(filePath);
return filePath;
}
else
{
var data = locator.Data as AssetBundleRequestOptions;
var filePath = data.BundleName + "/" + data.Hash + "/" + "__data";
return filePath;
}
}
private void GatherDependencies(IResourceLocation resource, List<string> dependencies)
{
if (!resource.HasDependencies)
{
var data = resource.Data as AssetBundleRequestOptions;
var filePath = data.BundleName + "/" + data.Hash + "/" + "__data";
if (!dependencies.Contains(filePath))
{
dependencies.Add(filePath);
}
}
else
{
foreach (var dep in resource.Dependencies)
{
GatherDependencies(dep, dependencies);
}
}
}
public IEnumerator LoadAssets(List<string> paths)
{
var progressBar = ModelViewerInterface.GetInstance().ProgressBar;
for (int i = paths.Count - 1; i >= 0; i--)
{
if (!File.Exists(paths[i]))
{
paths.RemoveAt(i);
}
}
List<AssetBundleCreateRequest> routines = new List<AssetBundleCreateRequest>();
foreach(var path in paths)
{
routines.Add(AssetBundle.LoadFromFileAsync(path));
}
while (routines.Any(r => !r.isDone))
{
int finished = routines.Count(r => r.isDone);
progressBar?.SetProgress($"Reading files ({finished}/{routines.Count})", (float)finished / routines.Count);
yield return 0;
}
for (int i = 0; i < routines.Count; i++)
{
LoadedAssets.Add(paths[i], routines[i].assetBundle);
}
progressBar?.SetProgress("", 1);
}
public static AssetBundle LoadFromFile(string path)
{
var bundle = AssetBundle.LoadFromFile(path);
_mainInstance.LoadedAssets.Add(path, bundle);
return bundle;
}
public void UnloadAssets(List<string> paths)
{
for (int i = 0; i < paths.Count; i++)
{
UnloadAsset(paths[i]);
}
}
public void UnloadAsset(string path)
{
if (LoadedAssets.ContainsKey(path))
{
LoadedAssets[path].Unload(false);
LoadedAssets.Remove(path);
}
}
}