using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.U2D; using UnityEngine.EventSystems; using UnityEngine.AddressableAssets; using System.Threading.Tasks; using asap.core; using System.Linq; namespace GameCore { public class GetUIAsyncEvent { public string uIType; public bool show = true; } public enum ScreenType { INVALID, LANDSCAPE, PORTRAIT, } public class UIType { public string Path { get; private set; } public string Name { get; private set; } public int UIOffset { get; private set; } public UIType(string path) { Path = path; Name = path.Substring(path.LastIndexOf('/') + 1); UITypes.UITypesDic[Name] = this; } public UIType(string path, int uiOffset) { Path = path; Name = path.Substring(path.LastIndexOf('/') + 1); UIOffset = uiOffset; UITypes.UITypesDic[Name] = this; } public void SetType(string path) { Path = path; Name = path.Substring(path.LastIndexOf('/') + 1); UITypes.UITypesDic[Name] = this; } public override string ToString() { return string.Format("UIType {0}({1})", Name, Path); } public override bool Equals(object obj) { if (obj is UIType otherType) { if (this.Path == otherType.Path) { return true; } } return base.Equals(obj); } public override int GetHashCode() { return Path.GetHashCode(); } } class SpriteAtlasCache { public SpriteAtlas atlas; public Dictionary spriteDict; public SpriteAtlasCache() { atlas = null; spriteDict = new Dictionary(); } } public class UIManager : MonoBehaviour { public const int TIME_OUT_MS = 10000; public const int BLOCK_DELAY_MS = 1500; // in ms public const float TRANSITION_TIMER = 0.3f; public RectTransform WaitingPanel; public Image TransitionPanel; public Action WaitingTimeOutDefaultCallback; private RectTransform alertContainer; private UIType[] alertUIList; Dictionary _UIDict = new Dictionary(); Dictionary _UIDictABB = new Dictionary(); //非自动填充,具体业务需求填充 public Stack panelStack = new Stack(); Dictionary _atlasDict = new Dictionary(); Dictionary> _textureDict = new Dictionary>(); Dictionary> _spriteDict = new Dictionary>(); Transform _topSibling = null; // Assuming there's only one top sibling needed, make it a list otherwise int _waitingAnimShowingTimer = int.MaxValue; // in milliseconds int _waitingBlockTimeout = 0; // in milliseconds float _waitingBlockStartTime; WaitingUI waitingUI; CanvasScaler canvasScaler; public CanvasScaler CanvasScaler => canvasScaler; ScreenOrientation prevLandscape; // Save previous Landscape orientation, OS tend to restore this when auto-rotation is on and change screen from portrait to landscape Dictionary _waitingBlockDict = new Dictionary(); static public UIManager Instance { get; private set; } // public Camera UICamera { get; private set; } public Canvas UICanvas { get; private set; } GraphicRaycaster graphicRaycaster { get; set; } public RectTransform RectTrans { get; private set; } public ScreenType screenType { get; private set; } Rect safeArea; public Camera UI3DCamera { get; private set; } private float anchorMax; /* * public static void Init(UIType ui_type, ScreenType screen_type, Action default_waiting_timeout_callback = null) * { * if (Instance != null || ui_type == null) * { * return; * } * * GameObject prefab = AssetManager.LoadAsset(ui_type.Path); * * if (prefab != null) * { * GameObject main_ui = GameObject.Instantiate(prefab) as GameObject; * DontDestroyOnLoad(main_ui); * * if (main_ui != null) * { * main_ui.name = ui_type.Name; * } * * Instance = main_ui.AddComponent(); * Instance.screenType = screen_type; * Instance.canvasScaler = main_ui.GetComponent(); * Instance.WaitingTimeOutDefaultCallback = default_waiting_timeout_callback; * * var waiting_obj = main_ui.FindChildGameObject("WaitingBlock"); * * if (waiting_obj != null) * { * var trans = waiting_obj.GetComponent(); * Instance.InitWaitingPanel(trans); * waiting_obj.SetActiveAsNeed(false); * } * else * { * Debug.LogError("[UIManager]Init: Fail to find WaitingBlock GameObject"); * } * } * } */ public static async Task Init(UIType ui_type, ScreenType screen_type, Action default_waiting_timeout_callback = null) { if (Instance != null || ui_type == null) { return; } var main_ui = await Addressables.InstantiateAsync(ui_type.Path).Task; if (main_ui != null) { DontDestroyOnLoad(main_ui); main_ui.name = ui_type.Name; Instance = main_ui.AddComponent(); Instance.screenType = screen_type; Instance.canvasScaler = main_ui.GetComponent(); Instance.WaitingTimeOutDefaultCallback = default_waiting_timeout_callback; var waiting_obj = main_ui.FindChildGameObject("WaitingBlock"); if (waiting_obj != null) { var trans = waiting_obj.GetComponent(); Instance.InitWaitingPanel(trans); waiting_obj.SetActiveAsNeed(false); } else { Debug.LogError("[UIManager]Init: Fail to find WaitingBlock GameObject"); } var alertContainer = main_ui.FindChildGameObject("Alert"); if (alertContainer != null) { Instance.alertContainer = alertContainer.GetComponent(); Instance.alertUIList = new UIType[] { UITypes.NoticeConfirmPopupPanel }; } } } public static void SetUICamera(Camera camera, Camera ui3d) { if (Instance != null) { Instance.UI3DCamera = ui3d; Instance.UI3DCamera.gameObject.SetActive(false); Instance.UICanvas.worldCamera = camera; camera.orthographicSize = Screen.height * 0.5f; } } public static void Destroy() { Debug.Log("[UIManager]Destroy"); if (Instance != null) { List keys = new List(Instance._UIDict.Keys); foreach (var kv in keys) { Instance.DestroyUI(kv); //Addressables.ReleaseInstance(kv.Value); } GameObject.DestroyImmediate(Instance.gameObject); Instance = null; } } static EventSystem _eventSystem; static float _inputBlockTimer = -1f; static Action _onInputBlockTimeOut = null; public static void BlockInput(float block_timer = -1f, Action on_time_out = null) { if (EventSystem.current != null && EventSystem.current.gameObject != null) { Debug.Log("[UIManager]BlockInput"); _eventSystem = EventSystem.current; _eventSystem.enabled = false; _inputBlockTimer = block_timer; _onInputBlockTimeOut = on_time_out; } } public static void UnblockInput() { if (_eventSystem != null) { Debug.Log("[UIManager]UnblockInput"); _eventSystem.enabled = true; _eventSystem = null; _onInputBlockTimeOut = null; _inputBlockTimer = -1f; } } public static bool isInputBlocked() { return _eventSystem != null; } public static void RestoreInputBlock() { if (Instance._waitingBlockDict.Count > 0) { BlockInput(); } } public static bool IsShowingWaitingBlock(string message_id) { bool is_showing = false; if (Instance != null) { is_showing = Instance._IsShowingWaitingBlock(message_id); } return is_showing; } public static void ClearWaitingBlock() { if (Instance != null) { UnblockInput(); Debug.Log("[UIManager]ClearWaitingBlock"); Instance._ClearWaitingBlock(); } } public static IEnumerator ChangeScreenOrientation(ScreenType screen_type) { Debug.Log($"[UIManager]ChangeScreenOrientation: {screen_type}"); if (Instance == null || Instance.canvasScaler == null) { Debug.LogError($"[UIManager]ChangeScreenOrientation: Not found canvasScaler!"); yield break; } var current_width = Instance.RectTrans.rect.width; var current_height = Instance.RectTrans.rect.height; var target_width = current_height; var target_height = current_width; var ref_res = Instance.canvasScaler.referenceResolution; var target_ref_res = new Vector2(ref_res.y, ref_res.x); if (screen_type == ScreenType.PORTRAIT) { // Already in the right orientation, just ignore this if (!Application.isEditor) { if (Instance.screenType == ScreenType.PORTRAIT || Screen.orientation == ScreenOrientation.Portrait) { Debug.LogError( $"[UIManager]ChangeScreenOrientation: Already in the screenType = {Instance.screenType}, or Orientation = {Screen.orientation}!"); yield break; } } Instance.prevLandscape = Screen.orientation; var target_orientation = ScreenOrientation.Portrait; Screen.orientation = target_orientation; Instance.screenType = screen_type; if (!Application.isEditor) { yield return null; Instance.canvasScaler.referenceResolution = target_ref_res; yield return new WaitUntil(() => { return Instance.RectTrans.rect.width == target_width && Instance.RectTrans.rect.height == target_height; }); } Instance.canvasScaler.referenceResolution = target_ref_res; if (Instance.canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight) { Instance.canvasScaler.matchWidthOrHeight = 0; } } else if (screen_type == ScreenType.LANDSCAPE) { // Already in the right orientation, just ignore this if (!Application.isEditor) { if (Instance.screenType == ScreenType.LANDSCAPE || Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.LandscapeRight) { Debug.LogError( $"[UIManager]ChangeScreenOrientation: Already in the screenType = {Instance.screenType}, or Orientation = {Screen.orientation}!"); yield break; } } var target_orientation = ScreenOrientation.LandscapeLeft; if (Instance.prevLandscape == ScreenOrientation.LandscapeLeft || Instance.prevLandscape == ScreenOrientation.LandscapeRight) { target_orientation = Instance.prevLandscape; } if (Input.deviceOrientation == DeviceOrientation.LandscapeLeft) { target_orientation = ScreenOrientation.LandscapeLeft; } else if (Input.deviceOrientation == DeviceOrientation.LandscapeRight) { target_orientation = ScreenOrientation.LandscapeRight; } Screen.orientation = target_orientation; Instance.screenType = screen_type; if (!Application.isEditor) { yield return null; Instance.canvasScaler.referenceResolution = target_ref_res; yield return new WaitUntil(() => { return Instance.RectTrans.rect.width == target_width && Instance.RectTrans.rect.height == target_height; }); } Instance.canvasScaler.referenceResolution = target_ref_res; if (Instance.canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight) { Instance.canvasScaler.matchWidthOrHeight = 1; } Screen.autorotateToLandscapeLeft = true; Screen.autorotateToLandscapeRight = true; Screen.autorotateToPortrait = false; Screen.autorotateToPortraitUpsideDown = false; Screen.orientation = ScreenOrientation.AutoRotation; } else { Debug.LogError($"[UIManager]ChangeScreenOrientation: Not handle ScreenType {screen_type}"); } } bool _IsShowingWaitingBlock(string message_id) { bool is_found = false; if (Instance != null) { if (_waitingBlockDict.ContainsKey(message_id)) { is_found = true; } } return is_found; } public static void ShowWaitingBlock(string message_id, Action time_out_callback = null, int delay_time_ms = BLOCK_DELAY_MS, int timeout_ms = TIME_OUT_MS) { if (IsShowingWaitingBlock(message_id)) { return; } if (Instance != null) { Instance._ShowWaitingBlock(message_id, time_out_callback, delay_time_ms, timeout_ms); } } private static void ShowForceWaitingBlock() { if (Instance != null) { Instance.ShowWaitingBlock(-1); } } private static void HideForceWaitingBlock() { if (Instance != null) { Instance.HideWaitingBlock(); } } public static void HideWaitingBlock(string message_id) { if (!IsShowingWaitingBlock(message_id)) { return; } if (Instance != null) { Instance._HideWaitingBlock(message_id); } } void _ShowWaitingBlock(string message_id, Action time_out_callback = null, int delay_time_ms = BLOCK_DELAY_MS, int timeout_ms = TIME_OUT_MS) { if (Instance != null) { if (delay_time_ms > timeout_ms) { Debug.LogError( $"[UIManager]_ShowWaitingBlock: Delay timer {delay_time_ms} shouldn't bigger than timeout timer {timeout_ms}, will set it to timeout timer instead."); delay_time_ms = timeout_ms; } if (delay_time_ms < _waitingAnimShowingTimer) { _waitingAnimShowingTimer = delay_time_ms; } if (timeout_ms > _waitingBlockTimeout) { _waitingBlockTimeout = timeout_ms; } if (_waitingBlockDict.Count == 0) { _waitingBlockStartTime = Time.realtimeSinceStartup; } if (_waitingBlockDict.ContainsKey(message_id)) { _waitingBlockDict[message_id] = time_out_callback; return; } BlockInput(); //Debug.LogWithTrace("[UIManager]_ShowWaitingBlock: {0}, delay time {1}", message_id, delay_time_ms); Debug.LogFormat("[UIManager]_ShowWaitingBlock: {0}, delay time {1}", message_id, delay_time_ms); _waitingBlockDict.Add(message_id, time_out_callback); } } void _HideWaitingBlock(string message_id) { Debug.Log($"[UIManager]_HideWaitingBlock: {message_id}"); if (_waitingBlockDict.Count == 0) { return; } if (_waitingBlockDict.ContainsKey(message_id)) { _waitingBlockDict.Remove(message_id); } if (_waitingBlockDict.Count == 0) { if (WaitingPanel != null) { WaitingPanel.gameObject.SetActiveAsNeed(false); WaitingPanel.GetComponent().alpha = 1; } _waitingAnimShowingTimer = int.MaxValue; _waitingBlockTimeout = 0; _waitingBlockStartTime = 0; UnblockInput(); // Debug.Log("[UIManager]_HideWaitingBlock: No block any more!"); } else { if (Application.isEditor) { var etor = _waitingBlockDict.GetEnumerator(); while (etor.MoveNext()) { var item_key = etor.Current.Key; Debug.Log($"[UIManager]_HideWaitingBlock: {item_key} still waiting block"); } } } } bool isWaitingBlockShowing() { return WaitingPanel != null && WaitingPanel.gameObject.activeSelf; } // timeout_ms < 0 means keep showing and no time out trigger void ShowWaitingBlock(int timeout_ms) { if (WaitingPanel != null && !WaitingPanel.gameObject.activeSelf) { WaitingPanel.SetAsLastSibling(); WaitingPanel.gameObject.SetActiveAsNeed(true); } if (waitingUI != null) { waitingUI.Show(timeout_ms); } BlockInput(); } // Note: Only use this to hide force waiting block void HideWaitingBlock() { if (WaitingPanel != null) { WaitingPanel.gameObject.SetActiveAsNeed(false); WaitingPanel.GetComponent().alpha = 1; } UnblockInput(); } void _ClearWaitingBlock() { if (WaitingPanel != null) { WaitingPanel.gameObject.SetActiveAsNeed(false); WaitingPanel.GetComponent().alpha = 1; } _waitingBlockDict.Clear(); } void OnWaitingTimeOut() { Debug.LogError("[UIManager]OnWaitingTimeOut"); bool is_handled = false; var etor = _waitingBlockDict.GetEnumerator(); while (etor.MoveNext()) { Debug.LogError($"[UIManager]OnWaitingTimeOut: Handling waiting time out of {etor.Current.Key}"); var callback = etor.Current.Value; if (callback != null) { callback(); is_handled = true; } if (_waitingBlockDict.Count <= 0) { break; } } Debug.Log("[UIManager]OnWaitingTimeOut: No waiting lock any more."); UnblockInput(); _ClearWaitingBlock(); if (!is_handled) { if (WaitingTimeOutDefaultCallback != null) { WaitingTimeOutDefaultCallback.Invoke(); } } } IEnumerator CrossFadeAlpha(Image image, float alpha, float duration, Action on_complete = null) { image.CrossFadeAlpha(alpha, duration, true); yield return new WaitForSeconds(duration); on_complete?.Invoke(); } public void ShowTransitionPanel(Action on_complete = null) { if (TransitionPanel == null) { Debug.LogError("[UIManager]ShowTransitionPanel: TransitionPanel not found under UIRoot"); return; } Debug.Log("[UIManager]ShowTransitionPanel"); TransitionPanel.gameObject.SetActiveAsNeed(true); StartCoroutine(CrossFadeAlpha(TransitionPanel, 1f, TRANSITION_TIMER, on_complete)); BlockInput(); } public void HideTransitionPanel(Action on_complete = null) { if (TransitionPanel == null) { Debug.LogError("[UIManager]HideTransitionPanel: TransitionPanel not found under UIRoot"); return; } if (!TransitionPanel.gameObject.activeSelf) { Debug.Log("[UIManager]HideTransitionPanel: TransitionPanel already hidden"); return; } Debug.Log("[UIManager]HideTransitionPanel"); UnblockInput(); StartCoroutine(CrossFadeAlpha(TransitionPanel, 0f, TRANSITION_TIMER, () => { TransitionPanel.gameObject.SetActiveAsNeed(false); on_complete?.Invoke(); })); } void Awake() { Instance = this; UICanvas = GetComponent(); //UICamera = UICanvas.renderMode == RenderMode.ScreenSpaceOverlay ? Camera.main : GetComponentInChildren(); graphicRaycaster = GetComponent(); RectTrans = GetComponent(); safeArea = Screen.safeArea; Vector2 sizeDelta = RectTrans.sizeDelta; float resolutionRatioHeight = sizeDelta.y; float heightRatio = resolutionRatioHeight / Screen.height; anchorMax = (Screen.height - safeArea.size.y - safeArea.position.y) * heightRatio; var panel = gameObject.FindChildGameObject("TransitionPanel"); if (panel != null) { TransitionPanel = panel.GetComponent(); } if (WaitingPanel != null) { InitWaitingPanel(); } } void Start() { // Fix issues about pressing buttons. Sometime very small movements in finger touch can be interpreted as scrolling rather than a simple touch. if (EventSystem.current != null) { int defaultValue = EventSystem.current.pixelDragThreshold; EventSystem.current.pixelDragThreshold = Mathf.Max(defaultValue, (int)(defaultValue * Screen.dpi / 160f)); } } void InitWaitingPanel(RectTransform trans = null) { if (trans != null) { WaitingPanel = trans; } if (WaitingPanel != null) { waitingUI = WaitingPanel.gameObject.GetComponentInChildren(); if (waitingUI != null) { waitingUI.OnTimeOut = OnWaitingTimeOut; } } } void Update() { if (_waitingBlockDict.Count > 0 && !isWaitingBlockShowing()) { float current_time = Time.realtimeSinceStartup; var delta_time = current_time - _waitingBlockStartTime; if (delta_time > _waitingAnimShowingTimer * 0.001f) { ShowWaitingBlock(_waitingBlockTimeout); } } if (_eventSystem != null && _inputBlockTimer > 0) { _inputBlockTimer -= Time.unscaledDeltaTime; if (_inputBlockTimer < 0f) { if (_onInputBlockTimeOut != null) { _onInputBlockTimeOut(); _onInputBlockTimeOut = null; } UnblockInput(); } } } public bool IsShowingUI(UIType ui_type) { string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name) && null != _UIDict[ui_type_name] && _UIDict[ui_type_name].activeSelf) { return true; } else { return false; } } public bool ContainsUI(UIType ui_type) { string ui_type_name = ui_type.Name; return ContainsUI(ui_type_name); } public bool ContainsUI(string ui_type_name) { if (_UIDict.ContainsKey(ui_type_name) && null != _UIDict[ui_type_name]) { return true; } else { return false; } } public GameObject GetContainedUI(UIType ui_type) { GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name)) { ui_obj = _UIDict[ui_type_name]; if (ui_obj == null) { _UIDict.Remove(ui_type_name); } } return ui_obj; } public async void PreloadUI(UIType ui_type, Transform parent = null) { var obj = await GetUIAsync(ui_type, parent); if (obj != null) { obj.SetActiveAsNeed(false); } } public async Task GetUIAsync(UIType ui_type, Transform parent = null) { GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name)) { ui_obj = _UIDict[ui_type_name]; if (ui_obj == null) { _UIDict.Remove(ui_type_name); } } if (ui_obj == null && !_UIDict.ContainsKey(ui_type_name)) { graphicRaycaster.enabled = false; ui_obj = await LoadUIAssetAsync(ui_type); graphicRaycaster.enabled = true; } if (ui_type != UITypes.common_tips) { GetUIAsyncEvent(ui_type_name); } return ui_obj; } async void GetUIAsyncEvent(string ui_type_name, bool isShow = true) { if (ui_type_name.Contains("_tips") || ui_type_name == UITypes.GuidancePanel.Name || ui_type_name == UITypes.ToastPanel.Name) { return; } await Awaiters.NextFrame; GContext.Publish(new GetUIAsyncEvent() { uIType = ui_type_name, show = isShow }); } public void DestroyUI(UIType ui_type, int delay_ms = 0) { string ui_type_name = ui_type.Name; DestroyUI(ui_type_name, delay_ms); } public async void DestroyUI(string ui_type, int delay_ms = 0) { async void Release(GameObject obj, int ms) { await Task.Delay(ms); Addressables.Release(obj); } if (!_UIDict.ContainsKey(ui_type)) { //JJ.Debug.Log("[UIManager]_UIDict doesn't contain UIType : {0}", uiType); return; } if (_UIDict[ui_type] != null) { GameObject ui_obj = _UIDict[ui_type]; GameObject ui_obj_aab = _UIDictABB[ui_type]; if (ui_obj.transform == _topSibling) { _topSibling = null; } if (delay_ms > 0) { GameObject.Destroy(ui_obj, delay_ms * 0.001f); Release(ui_obj_aab, delay_ms); } else { GameObject.Destroy(ui_obj); Addressables.Release(ui_obj_aab); } } _UIDict.Remove(ui_type); _UIDictABB.Remove(ui_type); await Awaiters.NextFrame; GetUIAsyncEvent(ui_type, false); } public async Task RestartShowUI(UIType ui_type) { GameObject ui_obj; string ui_type_name = ui_type.Name; if (_UIDictABB.ContainsKey(ui_type_name)) { if (_UIDict.ContainsKey(ui_type_name)) { GameObject _ui_obj = _UIDict[ui_type_name]; GameObject.Destroy(_ui_obj); _UIDict.Remove(ui_type_name); } await Awaiters.NextFrame; GameObject _ui_obj_abb = _UIDictABB[ui_type_name]; ui_obj = Instantiate(_ui_obj_abb, transform); ui_obj.name = ui_type.Name; SetRectTransform(ui_obj.GetComponent(), ui_type.UIOffset); // Make sure top sibling always on top. if (_topSibling != null) { _topSibling.SetAsLastSibling(); } _UIDict[ui_type_name] = ui_obj; } else { ui_obj = await GetUIAsync(ui_type); } if (ui_obj != null && !ui_obj.activeSelf) { ui_obj.SetActive(true); } return ui_obj; } /// /// 已经确定提前下好 或不需要下载的Panel 走这个接口 /// 不显示Loading条 /// /// /// public async Task ShowUINotLoading(UIType ui_type) { GameObject ui_obj = await GetUIAsync(ui_type); if (ui_obj != null && !ui_obj.activeSelf) { ui_obj.SetActive(true); } await Awaiters.NextFrame; return ui_obj; } /// /// 如果需要下载 并且不下载 就返回 Null /// /// /// public async Task ShowUIPack(UIType ui_type) { GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name)) { ui_obj = _UIDict[ui_type_name]; if (ui_obj == null) { _UIDict.Remove(ui_type_name); } } if (ui_obj == null) { graphicRaycaster.enabled = false; ILoadResourceService loadResourceService = GContext.container.Resolve(); bool isCanEnter = await loadResourceService.Load(ui_type.Path); if (!isCanEnter) { TaskCompletionSource task = new TaskCompletionSource(); var panel = await ShowUINotLoading(UITypes.DownLoadPopupPanel); panel.GetComponent().SetBtn(() => { task.SetResult(true); }, () => { task.SetResult(false); }); graphicRaycaster.enabled = true; bool result = await task.Task; if (!result) { return null; } else { graphicRaycaster.enabled = false; } } ui_obj = await LoadUIAssetAsync(ui_type); graphicRaycaster.enabled = true; } if (ui_type != UITypes.common_tips) { GetUIAsyncEvent(ui_type.Name); } if (ui_obj != null && !ui_obj.activeSelf) { ui_obj.SetActive(true); } await Awaiters.NextFrame; return ui_obj; } /// /// 不确定是否下载走这个接口 弹loading动画 /// /// /// public async Task ShowUILoad(UIType ui_type) { GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name)) { ui_obj = _UIDict[ui_type_name]; if (ui_obj == null) { _UIDict.Remove(ui_type_name); } } if (ui_obj == null) { graphicRaycaster.enabled = false; ILoadResourceService loadResourceService = GContext.container.Resolve(); bool isCanEnter = await loadResourceService.Load(ui_type.Path); if (!isCanEnter) { TaskCompletionSource task = new TaskCompletionSource(); var panel = await ShowUINotLoading(UITypes.CloudTransitionPanel); panel.GetComponent().SetBtn(false, () => { task.SetResult(true); }, () => { task.SetResult(false); }); graphicRaycaster.enabled = true; bool result = await task.Task; if (!result) { return null; } else { graphicRaycaster.enabled = false; } } ui_obj = await LoadUIAssetAsync(ui_type); graphicRaycaster.enabled = true; } if (ui_type != UITypes.common_tips) { GetUIAsyncEvent(ui_type_name); } if (ui_obj != null && !ui_obj.activeSelf) { ui_obj.SetActive(true); } await Awaiters.NextFrame; return ui_obj; } /// /// 请使用 ShowUILoad 并做好判空处理 /// 如果确定已经下载好或者不需要下载 请使用 ShowUINotLoading /// /// /// public async Task ShowUI(UIType ui_type) { GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name)) { ui_obj = _UIDict[ui_type_name]; if (ui_obj == null) { _UIDict.Remove(ui_type_name); } } if (ui_obj == null) { graphicRaycaster.enabled = false; ui_obj = await LoadUIAssetAsync(ui_type); graphicRaycaster.enabled = true; } if (ui_type != UITypes.common_tips) { GetUIAsyncEvent(ui_type_name); } if (ui_obj != null && !ui_obj.activeSelf) { ui_obj.SetActive(true); } ui_obj.transform.SetAsLastSibling(); await Awaiters.NextFrame; return ui_obj; } void SetRectTransform(RectTransform rect, float UIOffset) { if (UIOffset > -1) { float min = 1.777778f; float aspect = (float)Screen.height / Screen.width; float offset = (Math.Clamp(aspect, min, 2.16f) - min) / (2.16f - min) * UIOffset; rect.offsetMin = new Vector2(0, offset + 20); float anchorMaxY = anchorMax > offset ? anchorMax : offset; rect.offsetMax = new Vector2(0, -anchorMaxY); } } async Task LoadUIAssetAsync(UIType ui_type) { var add = await Addressables.LoadAssetAsync(ui_type.Path).Task; GameObject ui_obj = null; string ui_type_name = ui_type.Name; if (add != null) { if (!_UIDict.ContainsKey(ui_type_name)) { var par = alertUIList.Contains(ui_type) ? alertContainer : transform; ui_obj = Instantiate(add, par); ui_obj.name = ui_type.Name; SetRectTransform(ui_obj.GetComponent(), ui_type.UIOffset); // Make sure top sibling always on top. if (_topSibling != null) { _topSibling.SetAsLastSibling(); } _UIDictABB[ui_type_name] = add; _UIDict.Add(ui_type_name, ui_obj); } else { ui_obj = _UIDict[ui_type_name]; Addressables.Release(add); } } return ui_obj; } public async void HideUI(UIType ui_type) { string ui_type_name = ui_type.Name; if (_UIDict.ContainsKey(ui_type_name) == false || _UIDict[ui_type_name] == null) { return; } GameObject ui_obj = _UIDict[ui_type_name]; if (ui_obj.transform == _topSibling) { _topSibling = null; } if (ui_obj.activeSelf) { ui_obj.SetActive(false); await Awaiters.NextFrame; GetUIAsyncEvent(ui_type_name, false); } } public void SetAlwaysTopSibling(Transform top_transform) { _topSibling = top_transform; } // public bool IsUIEnable() // { // return UICamera.enabled; // } // // public void ShowUI() // { // UICamera.enabled = true; // } // // public void HideUI() // { // UICamera.enabled = false; // } // Put the given object transform on top of all the UI public void PutOnTop(Transform ui_trans) { ui_trans.SetParent(RectTrans); ui_trans.SetAsLastSibling(); // Make sure top sibling always on top. if (_topSibling != null) { _topSibling.SetAsLastSibling(); } } /// /// Clone the first Sprite in this atlas that matches the name packed in this atlas and return it. /// Note: Using AssetBundle.GetAsset will not clone, and will be better. /// /// /// /// public Sprite GetSprite(string atlas_name, string sprite_name) { Sprite sprite_ret = null; if (_atlasDict.TryGetValue(atlas_name, out var atlas_cache)) { if (atlas_cache.spriteDict.ContainsKey(sprite_name)) { sprite_ret = atlas_cache.spriteDict[sprite_name]; } else { sprite_ret = atlas_cache.atlas.GetSprite(sprite_name); atlas_cache.spriteDict[sprite_name] = sprite_ret; } } else { //var atlas = AssetManager.LoadAsset(atlas_name); var atlas = Addressables.LoadAssetAsync(atlas_name).WaitForCompletion(); if (atlas != null) { var new_atlas_cache = new SpriteAtlasCache { atlas = atlas }; sprite_ret = atlas.GetSprite(sprite_name); new_atlas_cache.spriteDict[sprite_name] = sprite_ret; } } if (sprite_ret == null) { Debug.LogError($"[UIManager]GetSprite: Not found sprite {sprite_name} in Atlas {atlas_name}"); } return sprite_ret; } public void ClearAllUIAtlasRef() { _atlasDict.Clear(); } public void ReleaseSpriteDic(string dicName) { if (!string.IsNullOrEmpty(dicName) && _spriteDict.TryGetValue(dicName, out var sprites)) { foreach (var item in sprites) { Addressables.Release(item.Value); } _spriteDict.Remove(dicName); } } public async Task SetTexture(RawImage rawImage, string textureName, string dicName = "dicName") { Texture texture; if (_textureDict.TryGetValue(dicName, out var textures)) { if (textures.TryGetValue(textureName, out texture)) { rawImage.texture = texture; return; } } else { textures = new Dictionary(); _textureDict.Add(dicName, textures); } texture = await Addressables.LoadAssetAsync(textureName).Task; if (texture != null) { if (textures.ContainsKey(textureName)) { Addressables.Release(texture); rawImage.texture = textures[textureName]; } else { rawImage.texture = texture; textures[textureName] = texture; } } } public void ReleaseTextureDic(string dicName) { if (!string.IsNullOrEmpty(dicName) && _textureDict.TryGetValue(dicName, out var textures)) { foreach (var item in textures) { Addressables.Release(item.Value); } _textureDict.Remove(dicName); } } public Vector2 WorldToScreen(Vector3 worldPos) { Camera camera; if (UICanvas != null && UICanvas.worldCamera != null) camera = UICanvas.worldCamera; else camera = Camera.main; var screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, worldPos); var res = camera.ScreenToWorldPoint(screenPoint); return res; } } }