biography-of-lijie/Assets/GameMain/Scripts/CustomComponent/SpriteCacheComponent.cs

206 lines
6.5 KiB
C#

using System;
using System.Collections.Generic;
using CustomUtility;
using Definition;
using GameFramework.Resource;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace CustomComponent
{
public class SpriteCacheComponent : GameFrameworkComponent
{
[SerializeField] private float _pixelsPerUnit = 100f;
[SerializeField] private Vector2 _defaultPivot = new(0.5f, 0.5f);
private Dictionary<string, Sprite> _spriteCache;
private Dictionary<string, List<Action<Sprite>>> _pendingCallbacks;
private HashSet<string> _loadingSpriteAssets;
private ResourceComponent _resource;
void Start()
{
EnsureRuntimeCaches();
}
private void EnsureRuntimeCaches()
{
_spriteCache ??= new Dictionary<string, Sprite>();
_pendingCallbacks ??= new Dictionary<string, List<Action<Sprite>>>();
_loadingSpriteAssets ??= new HashSet<string>();
_resource ??= GameEntry.Resource;
}
public bool TryGetCachedSprite(string assetName, out Sprite sprite)
{
EnsureRuntimeCaches();
if (string.IsNullOrWhiteSpace(assetName))
{
sprite = null;
return false;
}
return _spriteCache.TryGetValue(assetName, out sprite);
}
public void GetSprite(string assetName, Action<Sprite> callback)
{
EnsureRuntimeCaches();
if (string.IsNullOrWhiteSpace(assetName))
{
callback?.Invoke(null);
return;
}
if (_spriteCache.TryGetValue(assetName, out var sprite))
{
callback?.Invoke(sprite);
return;
}
if (callback != null)
{
AddPendingCallback(assetName, callback);
}
if (_loadingSpriteAssets.Contains(assetName))
{
return;
}
_loadingSpriteAssets.Add(assetName);
StartLoadSprite(assetName);
}
public void PreloadSprite(string assetName)
{
EnsureRuntimeCaches();
if (string.IsNullOrWhiteSpace(assetName) || _spriteCache.ContainsKey(assetName) ||
_loadingSpriteAssets.Contains(assetName))
{
return;
}
_loadingSpriteAssets.Add(assetName);
StartLoadSprite(assetName);
}
public void PreloadSprites(IEnumerable<string> assetNames)
{
EnsureRuntimeCaches();
if (assetNames == null)
{
return;
}
foreach (string assetName in assetNames)
{
PreloadSprite(assetName);
}
}
public void RegisterSprite(string assetName, Sprite sprite, bool overwrite = true)
{
EnsureRuntimeCaches();
if (string.IsNullOrWhiteSpace(assetName) || sprite == null)
{
return;
}
if (!overwrite && _spriteCache.ContainsKey(assetName))
{
return;
}
_spriteCache[assetName] = sprite;
InvokeAndClearPendingCallbacks(assetName, sprite);
_loadingSpriteAssets.Remove(assetName);
}
private void StartLoadSprite(string assetName)
{
EnsureRuntimeCaches();
if (_resource == null)
{
InvokeAndClearPendingCallbacks(assetName, null);
_loadingSpriteAssets.Remove(assetName);
return;
}
_resource.LoadAsset
(
AssetUtility.GetUISpriteAsset(assetName),
Constant.AssetPriority.UIFormAsset,
new LoadAssetCallbacks(
(resourcePath, asset, duration, userData) =>
{
Texture2D texture = asset as Texture2D;
Sprite loadedSprite = null;
if (texture != null)
{
loadedSprite = Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
_defaultPivot,
_pixelsPerUnit);
_spriteCache[assetName] = loadedSprite;
}
else
{
Log.Warning("Load sprite succeeded but asset is not Texture2D. AssetName='{0}', Path='{1}'.",
assetName, resourcePath);
}
InvokeAndClearPendingCallbacks(assetName, loadedSprite);
_loadingSpriteAssets.Remove(assetName);
},
(resourcePath, status, errorMessage, userData) =>
{
Log.Error("Can not load icon '{0}' from '{1}' with error message '{2}'.",
assetName,
resourcePath,
errorMessage);
InvokeAndClearPendingCallbacks(assetName, null);
_loadingSpriteAssets.Remove(assetName);
}
)
);
}
private void AddPendingCallback(string assetName, Action<Sprite> callback)
{
EnsureRuntimeCaches();
if (!_pendingCallbacks.TryGetValue(assetName, out List<Action<Sprite>> callbackList))
{
callbackList = new List<Action<Sprite>>();
_pendingCallbacks.Add(assetName, callbackList);
}
callbackList.Add(callback);
}
private void InvokeAndClearPendingCallbacks(string assetName, Sprite sprite)
{
EnsureRuntimeCaches();
if (!_pendingCallbacks.TryGetValue(assetName, out List<Action<Sprite>> callbackList))
{
return;
}
_pendingCallbacks.Remove(assetName);
for (int i = 0; i < callbackList.Count; i++)
{
callbackList[i]?.Invoke(sprite);
}
}
private void OnDestroy()
{
_spriteCache?.Clear();
_pendingCallbacks?.Clear();
_loadingSpriteAssets?.Clear();
_resource = null;
}
}
}