using asap.core; using System.Collections.Generic; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.U2D; using UnityEngine.UI; using UniRx; using System.Threading.Tasks; using game; using UnityEngine.ResourceManagement.AsyncOperations; public class GetSpriteEvent { public string spriteName; public string panelName; public Sprite sprite; public GetSpriteEvent() { } public GetSpriteEvent(string spriteName, string panelName = "") { this.spriteName = spriteName; this.panelName = panelName; } } public interface IShowImageData { public string spriteName { set; get; } public Image image { set; get; } public void SetImage(Sprite sprite); } public interface IUIService { Task LoadAtlas(); Task SetImageSprite(Image image, string spriteName, string panelName = ""); /// /// 同一个 image 组件 重复赋值,使用此方法 /// /// /// /// Task SetImageSprite(IShowImageData imageData, string panelName = ""); void ReleaseSpriteDic(string dicName); Task SetHeadImage(Image image, string spriteName); Sprite GetSprite(string spriteName, string panelName = ""); } public class AtlasReference { public AsyncOperationHandle handle; public SpriteAtlas spriteAtlas; public int referenceCount; } public class UIService : IUIService { private Dictionary> _spriteDict = new Dictionary>(); Dictionary atlasReference = new Dictionary(); SpriteAtlas atlasDic; string preloadAtlasName = "UIResAtlas"; string defaultAvatar; public async Task LoadAtlas() { cfg.Tables table = GContext.container.Resolve(); var tbAvatar = table.TbUserAvatar.GetOrDefault(table.TbGlobalConfig.InitAvatar); if (tbAvatar != null) { defaultAvatar = tbAvatar.Avatar; } else { defaultAvatar = table.TbUserAvatar.DataMap[0].Avatar; } if (atlasDic != null) { Addressables.Release(atlasDic); } var atlas = await Addressables.LoadAssetAsync(preloadAtlasName).Task; if (atlas != null) { atlasDic = atlas; } GContext.OnEvent().Subscribe(OnGetSprite); GetAvatarDataEvent getAvatarDataEvent = new GetAvatarDataEvent(); getAvatarDataEvent.url = GContext.container.Resolve().AvatarUrl; GContext.Publish(getAvatarDataEvent); } /// /// 设置头像 存在网图 /// /// Image 组件 /// 头像网址 或者本地名称 public async Task SetHeadImage(Image icon_head, string url) { if (icon_head == null) { Debug.LogError("SetHeadImage icon_head null"); return; } if (string.IsNullOrEmpty(url)) { url = defaultAvatar; } if (icon_head != null && url.Contains("http")) { icon_head.sprite = GetSprite(defaultAvatar); } GetAvatarDataEvent getAvatarDataEvent = new GetAvatarDataEvent(); getAvatarDataEvent.url = url; GContext.Publish(getAvatarDataEvent); var sprite = await getAvatarDataEvent.taskCompletionSource.Task; if (icon_head != null && sprite != null) { icon_head.sprite = sprite; } } void OnGetSprite(GetSpriteEvent getSpriteEvent) { if (!string.IsNullOrEmpty(getSpriteEvent.spriteName)) { getSpriteEvent.sprite = GetSprite(getSpriteEvent.spriteName, getSpriteEvent.panelName); } } public void ReleaseSpriteDic(string dicName) { if (string.IsNullOrEmpty(dicName) || !_spriteDict.TryGetValue(dicName, out var value)) { return; } foreach (var item in value) { string[] spriteNames = item.Key.Split('_'); if (spriteNames.Length > 1 && spriteNames[0] == "separate") { Addressables.Release(item.Value); } else if (spriteNames.Length > 2 && spriteNames[0] == "atlas") { if (atlasReference.TryGetValue(spriteNames[1], out var AR)) { AR.referenceCount--; if (AR.referenceCount == 0) { AR.spriteAtlas = null; Addressables.Release(AR.handle); atlasReference.Remove(spriteNames[1]); } } } } value.Clear(); _spriteDict.Remove(dicName); } public async Task SetImageSprite(Image image, string spriteName, string panelName = "") { if (image == null) { Debug.LogError($"image null spriteName {spriteName}"); return; } ShowImageData imageData = new ShowImageData(image, spriteName); await SetImageSprite(imageData, panelName); } public async Task SetImageSprite(IShowImageData imageData, string panelName = "") { if (imageData == null || imageData.image == null) { Debug.LogError($"image null spriteName {imageData?.spriteName}"); return; } if (string.IsNullOrEmpty(panelName)) { panelName = BasePanel.PanelName; } if (!string.IsNullOrEmpty(imageData.spriteName)) { try { await SetSprite(imageData, panelName); } catch (System.Exception e) { Debug.LogError($"SetImageSprite error: {e.Message}"); } } } /// /// 获取默认图集里面的图片 /// /// /// /// public Sprite GetSprite(string spriteName, string panelName = "") { if (string.IsNullOrEmpty(panelName)) { panelName = BasePanel.PanelName; } Sprite value; if (_spriteDict.TryGetValue(panelName, out var sprites)) { if (sprites.TryGetValue(spriteName, out value)) { return value; } } else { sprites = new Dictionary(); _spriteDict.Add(panelName, sprites); } value = atlasDic?.GetSprite(spriteName); if (value != null) { sprites[spriteName] = value; return value; } GameDebug.LogWarning("spriteName===>" + spriteName + " panelName===>" + panelName); return null; } async Task SetSprite(IShowImageData imageData, string panelName) { string spriteName = imageData.spriteName; string[] spriteNames = spriteName.Split('_'); if (spriteNames.Length > 1 && spriteNames[0] == "separate" && spriteNames[1] == "icon") { panelName = "icon"; } if (string.IsNullOrEmpty(panelName)) { panelName = "HomePanel"; } Sprite value; if (_spriteDict.TryGetValue(panelName, out var sprites)) { if (sprites.TryGetValue(spriteName, out value)) { imageData.SetImage(value); return; } } else { sprites = new Dictionary(); _spriteDict.Add(panelName, sprites); } if (spriteNames.Length > 1 && spriteNames[0] == "separate") { await LoadSprite(imageData, sprites); return; } else if (spriteNames.Length > 2 && spriteNames[0] == "atlas") { LoadSpriteAtlas(imageData, spriteNames[1], sprites); return; } else { value = atlasDic?.GetSprite(spriteName); if (value != null) { sprites[spriteName] = value; imageData.SetImage(value); return; } Debug.LogWarning("spriteName===>" + spriteName + " panelName===>" + panelName); } } async Task LoadSprite(IShowImageData imageData, Dictionary sprites) { string spriteName = imageData.spriteName; var sprite = await Addressables.LoadAssetAsync(spriteName).Task; if (sprite != null) { sprites[spriteName] = sprite; imageData.SetImage(sprite); } else { Debug.LogWarning("spriteName===>" + spriteName); } } void LoadSpriteAtlas(IShowImageData imageData, string sName, Dictionary sprites) { if (!atlasReference.TryGetValue(sName, out var AR)) { AR = new AtlasReference(); atlasReference.Add(sName, AR); AR.handle = Addressables.LoadAssetAsync("UIResAtlas_" + sName); AR.handle.Completed += (handle) => { if (handle.Status == AsyncOperationStatus.Succeeded) { if (AR.spriteAtlas == null) { AR.spriteAtlas = handle.Result; } SetSpriteSpriteName(imageData, AR, sprites); } else { Debug.LogError("ReleaseAtlas Load Failed ===>" + sName); Addressables.Release(AR.handle); atlasReference.Remove(sName); } }; } else { if (AR.spriteAtlas != null) { SetSpriteSpriteName(imageData, AR, sprites); } else { AR.handle.Completed += (handle) => { if (handle.Status == AsyncOperationStatus.Succeeded) { if (AR.spriteAtlas == null) { AR.spriteAtlas = handle.Result; } SetSpriteSpriteName(imageData, AR, sprites); } else { Debug.LogError("ReleaseAtlas Completed Failed ===>" + sName); } }; } } } void SetSpriteSpriteName(IShowImageData imageData, AtlasReference AR, Dictionary sprites) { string spriteName = imageData.spriteName; if (imageData.image != null) { if (!sprites.ContainsKey(spriteName)) { var value = AR.spriteAtlas.GetSprite(spriteName); if (value != null) { sprites[spriteName] = value; AR.referenceCount++; imageData.SetImage(sprites[spriteName]); } else { Debug.LogWarning("spriteName===>" + spriteName + " spriteAtlas===>" + AR.spriteAtlas.name); } } else { imageData.SetImage(sprites[spriteName]); } } } }