Kursach_StealthAction/Assets/Tremble/AssetLoading/Adaptors/AddressablesLoaderAdaptor.cs
2026-10-11 19:16:11 +03:00

159 lines
4.1 KiB
C#

//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
#if ADDRESSABLES_INSTALLED
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
namespace TinyGoose.Tremble
{
public class AddressablesLoaderAdaptor : IAssetLoaderAdaptor
{
public bool SupportsPreloading => true;
private readonly List<AsyncOperationHandle> m_OwnedHandles = new(1024);
private readonly Dictionary<string, object> m_LoadedAssets = new(1024);
public string[] FindAssetPaths(Type type, string name = "")
{
return TrembleAssetLoader.FindAssetDataMany(a => a.Path.ContainsInvariant(name))
.Where(a => a.FullTypeName.EqualsInvariant(type.FullName))
.Select(a => a.Path)
.ToArray();
}
public TAsset LoadAssetByPath<TAsset>(string path) where TAsset : Object
{
if (path.IsNullOrEmpty())
return null;
if (!TrembleAssetLoader.TryGetAssetDataFromPath(path, out AssetMetadata assetData))
{
Debug.LogError($"Not loading invalid addressable: {path}");
return null;
}
if (m_LoadedAssets.TryGetValue(assetData.AddressableName, out object existingAsset) &&
existingAsset is TAsset tAsset)
{
return tAsset;
}
AsyncOperationHandle<TAsset> handle = Addressables.LoadAssetAsync<TAsset>(assetData.AddressableName);
TAsset asset = handle.WaitForCompletion();
if (!asset)
{
Addressables.Release(handle);
return null;
}
m_OwnedHandles.Add(handle);
m_LoadedAssets[path] = handle;
return asset;
}
public async Task PreloadAssetsByPaths(IList<string> paths)
{
if (paths.Count == 0)
return;
List<string> addresses = new(paths.Count);
// First, remove dupes, invalid and ones we already loaded
for (int i = 0; i < paths.Count; i++)
{
string path = paths[i];
if (path.IsNullOrEmpty() || !TrembleAssetLoader.TryGetAssetDataFromPath(path, out AssetMetadata assetData))
{
Debug.LogError($"Not loading invalid addressable: {path}");
paths.RemoveAt(i--);
continue;
}
if (m_LoadedAssets.ContainsKey(assetData.AddressableName))
{
paths.RemoveAt(i--);
continue;
}
if (paths.IndexOf(path) != i)
{
paths.RemoveAt(i--);
continue;
}
// This is valid - add to list of addresses
addresses.Add(assetData.AddressableName);
}
if (addresses.Count == 0)
return;
AsyncOperationHandle<IList<Object>> resultsHandle = Addressables.LoadAssetsAsync<Object>(addresses, null, Addressables.MergeMode.Union);
await resultsHandle.Task;
for (int i = 0; i < paths.Count; i++)
{
string path = paths[i];
if (TrembleAssetLoader.TryGetAssetDataFromPath(path, out AssetMetadata assetData))
{
m_LoadedAssets[assetData.AddressableName] = resultsHandle.Result[i];
}
}
m_OwnedHandles.Add(resultsHandle);
}
public string GetPath(Object obj)
{
Debug.LogError("GetPath is not implemented in Addressables (yet!)");
return null;
}
public TrembleSyncSettings LoadSyncSettings()
{
return Addressables
.LoadAssetAsync<TrembleSyncSettings>(TrembleSyncSettings.ADDRESSABLE_KEY)
.WaitForCompletion();
}
public Material LoadClipMaterial()
{
return Addressables.LoadAssetAsync<Material>("M_NullRender").WaitForCompletion();
}
public void ReleaseAll()
{
foreach (AsyncOperationHandle handle in m_OwnedHandles)
{
Addressables.Release(handle);
}
m_OwnedHandles.Clear();
}
private static bool IsAddressablePathValid(string path)
{
if (path == null)
return false;
AsyncOperationHandle<IList<IResourceLocation>> locationLoadOperation = Addressables.LoadResourceLocationsAsync(path);
IList<IResourceLocation> results = locationLoadOperation.WaitForCompletion();
bool isValidPath = results is { Count: > 0 };
Addressables.Release(locationLoadOperation);
return isValidPath;
}
}
}
#endif