using FairyGUI;
using System.Collections.Generic;
using UnityEngine;
using XGame.Framework.Asyncs;
namespace XGame.Framework.FGUI
{
///
/// 修复图集合批 参考链接:https://zhuanlan.zhihu.com/p/689636245
///
internal partial class FguiModule : IGloaderHandle
{
public class LoadedAsset
{
public string addressable;
public Sprite sprite;
public NTexture nTexture;
}
///
/// 已加载过的资源
///
private Dictionary _loadedAssetsMap = new Dictionary();
///
/// key:sprite.texture
/// value:NTexture 用作Sprite的root
///
private Dictionary _textureRootMap = new Dictionary();
IAsync IGloaderHandle.LoadNTexture(string addressableName)
{
if (_loadedAssetsMap.ContainsKey(addressableName))
{ // 已经加载完
var asyncGroup = new AsyncGroup();
asyncGroup.End();
return asyncGroup;
}
//TODO 需要识别Sprite还是Texture
var loadAsync = _assetModule.LoadAsync(addressableName);
loadAsync.On(_ =>
{
var result = loadAsync.Result;
if (result == null)
{
Log.Debug($"IGloaderHandle.LoadNTexture failed. addressable:{addressableName}");
return;
}
if (CreateNTexture(addressableName, result) == false)
{ //已经有其他loader加载完成
_assetModule.Recycle(result);
}
});
return loadAsync;
}
NTexture IGloaderHandle.GetNTexture(string addressableName)
{
if (_loadedAssetsMap.TryGetValue(addressableName, out var asset))
{
return asset.nTexture;
}
// 可能是加载失败,也可能是没有加载过
Log.Debug($"找不到NTexture,确认IGloaderHandle.LoadNTexture是否已经加载成功. Name:{addressableName}");
return default;
}
private bool CreateNTexture(string addressable, Sprite sprite)
{
if (_loadedAssetsMap.ContainsKey(addressable))
{ // 已经有其他loader加载完成
return false;
}
if (!_textureRootMap.TryGetValue(sprite.texture, out var root))
{
_textureRootMap[sprite.texture] = root = new NTexture(sprite.texture);
root.destroyMethod = DestroyMethod.None;
}
Rect region = sprite.textureRect; //textureRect 会去掉边缘全透明的部分
region.y = sprite.texture.height - region.yMax;
var nTexture = new NTexture(root, region, false);
//注册release事件,Gloader在Dispose时,只会触发 NGraphics.Dispose() => _texture.ReleaseRef();
nTexture.onRelease += OnReleaseNTexture;
nTexture.destroyMethod = DestroyMethod.None;
var border = sprite.border; //
if (border != Vector4.zero)
{ // sprite.rect: 精灵的真实尺寸 sprite.texture 图集的贴图
nTexture.spriteScale9Grid = new Rect(border.x, border.w, sprite.rect.width - border.x - border.z, sprite.rect.height - border.y - border.w);
}
//Log.Info($"CreateNTexture Name:{addressable} width:{sprite.texture.width} height:{sprite.texture.height} rect:{sprite.rect} textureRect:{sprite.textureRect} border:{sprite.border} Scale9Grid:{nTexture.spriteScale9Grid}");
_loadedAssetsMap.Add(addressable, new LoadedAsset()
{
addressable = addressable,
sprite = sprite,
nTexture = nTexture,
});
return true;
}
private bool TryGetLoadedAsset(NTexture nTexture, out LoadedAsset asset)
{
foreach (var item in _loadedAssetsMap)
{
if (item.Value.nTexture == nTexture)
{
asset = item.Value;
return true;
}
}
asset = default;
return false;
}
private void OnReleaseNTexture(NTexture nTexture)
{
if (TryGetLoadedAsset(nTexture, out var asset))
{
//Log.Debug($"OnReleaseNTexture Addressable:{asset.addressable}");
_loadedAssetsMap.Remove(asset.addressable);
if (nTexture.root.refCount <= 0)
{
_textureRootMap.Remove(asset.sprite.texture);
}
_assetModule.Recycle(asset.sprite);
}
}
///
/// 清空所有Gloader加载的资源
///
///
public void ClearGloaderAssets()
{
foreach (var item in _loadedAssetsMap)
{
_assetModule.Recycle(item.Value.sprite);
}
_loadedAssetsMap.Clear();
_textureRootMap.Clear();
}
}
}