using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using YooAsset;
namespace AlicizaX.Resource.Runtime
{
///
/// 资源组件拓展。
///
public partial class ResourceExtComponent
{
private readonly Dictionary _subAssetsHandles = new Dictionary();
private readonly Dictionary _subSpriteReferences = new Dictionary();
public async UniTask SetSubSprite(Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default)
{
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
if (image == null)
{
Log.Warning($"SetSubAssets Image is null");
return;
}
image.sprite = subSprite;
if (setNativeSize)
{
image.SetNativeSize();
}
AddReference(image.gameObject, location);
}
public async UniTask SetSubSprite(SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default)
{
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
if (spriteRenderer == null)
{
Log.Warning($"SetSubAssets Image is null");
return;
}
spriteRenderer.sprite = subSprite;
AddReference(spriteRenderer.gameObject, location);
}
private async UniTask GetSubSpriteImp(string location, string spriteName, CancellationToken cancellationToken = default)
{
var assetInfo = YooAssets.GetAssetInfo(location);
if (assetInfo.IsInvalid)
{
throw new GameFrameworkException($"Invalid location: {location}");
}
await TryWaitingLoading(location);
if (!_subAssetsHandles.TryGetValue(location, out var subAssetsHandle))
{
subAssetsHandle = YooAssets.LoadSubAssetsAsync(location);
await subAssetsHandle.ToUniTask(cancellationToken: cancellationToken);
_subAssetsHandles[location] = subAssetsHandle;
}
var subSprite = subAssetsHandle.GetSubAssetObject(spriteName);
if (subSprite == null)
{
throw new GameFrameworkException($"Invalid sprite name: {spriteName}");
}
return subSprite;
}
private void AddReference(GameObject target, string location)
{
var subSpriteReference = target.GetComponent();
if (subSpriteReference == null)
{
subSpriteReference = target.AddComponent();
}
_subSpriteReferences[location] = _subSpriteReferences.TryGetValue(location, out var count) ? count + 1 : 1;
subSpriteReference.Reference(location);
}
internal void DeleteReference(string location)
{
if (string.IsNullOrEmpty(location))
{
return;
}
_subSpriteReferences[location] = _subSpriteReferences.TryGetValue(location, out var count) ? count - 1 : 0;
if (_subSpriteReferences[location] <= 0)
{
var subAssetsHandle = _subAssetsHandles[location];
subAssetsHandle.Dispose();
_subAssetsHandles.Remove(location);
_subSpriteReferences.Remove(location);
}
}
}
[DisallowMultipleComponent]
public class SubSpriteReference : MonoBehaviour
{
private string _location;
public void Reference(string location)
{
if (_location != null && _location != location)
{
ResourceExtComponent.Instance?.DeleteReference(_location);
}
_location = location;
}
private void OnDestroy()
{
if (_location != null)
{
ResourceExtComponent.Instance?.DeleteReference(_location);
}
}
}
}