diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/Implement/SetSpriteExtensions.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/Implement/SetSpriteExtensions.cs index a8448cf4..762e1803 100644 --- a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/Implement/SetSpriteExtensions.cs +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/Implement/SetSpriteExtensions.cs @@ -1,4 +1,5 @@ using System.Threading; +using Cysharp.Threading.Tasks; using TEngine; using UnityEngine; using UnityEngine.UI; @@ -27,4 +28,29 @@ public static class SetSpriteExtensions { ResourceExtComponent.Instance.SetAssetByResources(SetSpriteObject.Create(spriteRenderer, location, cancellationToken)).Forget(); } + + /// + /// 设置子图片。 + /// + /// UI/Image。 + /// 资源定位地址。 + /// 子图片名称。 + /// 是否使用原始分辨率。 + /// 取消设置资源的Token。 + public static void SetSubSprite(this Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default) + { + ResourceExtComponent.Instance.SetSubSprite(image, location, spriteName, setNativeSize, cancellationToken).Forget(); + } + + /// + /// 设置子图片。 + /// + /// 2D/SpriteRender。 + /// 资源定位地址。 + /// 子图片名称。 + /// 取消设置资源的Token。 + public static void SetSubSprite(this SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default) + { + ResourceExtComponent.Instance.SetSubSprite(spriteRenderer, location, spriteName, cancellationToken).Forget(); + } } \ No newline at end of file diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs new file mode 100644 index 00000000..5901b3f2 --- /dev/null +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Threading; +using Cysharp.Threading.Tasks; +using UnityEngine; +using UnityEngine.UI; +using YooAsset; + +namespace TEngine +{ + /// + /// 资源组件拓展。 + /// + internal 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); + } + } + } +} \ No newline at end of file diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs.meta b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs.meta new file mode 100644 index 00000000..54d93c74 --- /dev/null +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/Extension/ResourceExtComponent.SubSprite.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6ff32785e2bb42d085e53a36eb09038d +timeCreated: 1746582361 \ No newline at end of file