FguiModule.GLoader.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using FairyGUI;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using XGame.Framework.Asyncs;
  5. namespace XGame.Framework.FGUI
  6. {
  7. /// <summary>
  8. /// 修复图集合批 参考链接:https://zhuanlan.zhihu.com/p/689636245
  9. /// </summary>
  10. internal partial class FguiModule : IGloaderHandle
  11. {
  12. public class LoadedAsset
  13. {
  14. public string addressable;
  15. public Sprite sprite;
  16. public NTexture nTexture;
  17. }
  18. /// <summary>
  19. /// 已加载过的资源
  20. /// </summary>
  21. private Dictionary<string, LoadedAsset> _loadedAssetsMap = new Dictionary<string, LoadedAsset>();
  22. /// <summary>
  23. /// key:sprite.texture
  24. /// value:NTexture 用作Sprite的root
  25. /// </summary>
  26. private Dictionary<Texture, NTexture> _textureRootMap = new Dictionary<Texture, NTexture>();
  27. IAsync IGloaderHandle.LoadNTexture(string addressableName)
  28. {
  29. if (_loadedAssetsMap.ContainsKey(addressableName))
  30. { // 已经加载完
  31. var asyncGroup = new AsyncGroup();
  32. asyncGroup.End();
  33. return asyncGroup;
  34. }
  35. //TODO 需要识别Sprite还是Texture
  36. var loadAsync = _assetModule.LoadAsync<Sprite>(addressableName);
  37. loadAsync.On(_ =>
  38. {
  39. var result = loadAsync.Result;
  40. if (result == null)
  41. {
  42. Log.Debug($"IGloaderHandle.LoadNTexture failed. addressable:{addressableName}");
  43. return;
  44. }
  45. if (CreateNTexture(addressableName, result) == false)
  46. { //已经有其他loader加载完成
  47. _assetModule.Recycle(result);
  48. }
  49. });
  50. return loadAsync;
  51. }
  52. NTexture IGloaderHandle.GetNTexture(string addressableName)
  53. {
  54. if (_loadedAssetsMap.TryGetValue(addressableName, out var asset))
  55. {
  56. return asset.nTexture;
  57. }
  58. // 可能是加载失败,也可能是没有加载过
  59. Log.Debug($"找不到NTexture,确认IGloaderHandle.LoadNTexture是否已经加载成功. Name:{addressableName}");
  60. return default;
  61. }
  62. private bool CreateNTexture(string addressable, Sprite sprite)
  63. {
  64. if (_loadedAssetsMap.ContainsKey(addressable))
  65. { // 已经有其他loader加载完成
  66. return false;
  67. }
  68. if (!_textureRootMap.TryGetValue(sprite.texture, out var root))
  69. {
  70. _textureRootMap[sprite.texture] = root = new NTexture(sprite.texture);
  71. root.destroyMethod = DestroyMethod.None;
  72. }
  73. Rect region = sprite.textureRect; //textureRect 会去掉边缘全透明的部分
  74. region.y = sprite.texture.height - region.yMax;
  75. var nTexture = new NTexture(root, region, false);
  76. //注册release事件,Gloader在Dispose时,只会触发 NGraphics.Dispose() => _texture.ReleaseRef();
  77. nTexture.onRelease += OnReleaseNTexture;
  78. nTexture.destroyMethod = DestroyMethod.None;
  79. var border = sprite.border; //<L, B, R, T>
  80. if (border != Vector4.zero)
  81. { // sprite.rect: 精灵的真实尺寸 sprite.texture 图集的贴图
  82. nTexture.spriteScale9Grid = new Rect(border.x, border.w, sprite.rect.width - border.x - border.z, sprite.rect.height - border.y - border.w);
  83. }
  84. //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}");
  85. _loadedAssetsMap.Add(addressable, new LoadedAsset()
  86. {
  87. addressable = addressable,
  88. sprite = sprite,
  89. nTexture = nTexture,
  90. });
  91. return true;
  92. }
  93. private bool TryGetLoadedAsset(NTexture nTexture, out LoadedAsset asset)
  94. {
  95. foreach (var item in _loadedAssetsMap)
  96. {
  97. if (item.Value.nTexture == nTexture)
  98. {
  99. asset = item.Value;
  100. return true;
  101. }
  102. }
  103. asset = default;
  104. return false;
  105. }
  106. private void OnReleaseNTexture(NTexture nTexture)
  107. {
  108. if (TryGetLoadedAsset(nTexture, out var asset))
  109. {
  110. //Log.Debug($"OnReleaseNTexture Addressable:{asset.addressable}");
  111. _loadedAssetsMap.Remove(asset.addressable);
  112. if (nTexture.root.refCount <= 0)
  113. {
  114. _textureRootMap.Remove(asset.sprite.texture);
  115. }
  116. _assetModule.Recycle(asset.sprite);
  117. }
  118. }
  119. /// <summary>
  120. /// 清空所有Gloader加载的资源
  121. /// </summary>
  122. /// <param name="assetModule"></param>
  123. public void ClearGloaderAssets()
  124. {
  125. foreach (var item in _loadedAssetsMap)
  126. {
  127. _assetModule.Recycle(item.Value.sprite);
  128. }
  129. _loadedAssetsMap.Clear();
  130. _textureRootMap.Clear();
  131. }
  132. }
  133. }