Files
back_cantanBuilding/Assets/Scripts/UI/UIManager.cs
2026-05-26 16:15:54 +08:00

1372 lines
45 KiB
C#

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<string, Sprite> spriteDict;
public SpriteAtlasCache()
{
atlas = null;
spriteDict = new Dictionary<string, Sprite>();
}
}
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<string, GameObject> _UIDict = new Dictionary<string, GameObject>();
Dictionary<string, GameObject> _UIDictABB = new Dictionary<string, GameObject>();
//非自动填充,具体业务需求填充
public Stack<UIType> panelStack = new Stack<UIType>();
Dictionary<string, SpriteAtlasCache> _atlasDict = new Dictionary<string, SpriteAtlasCache>();
Dictionary<string, Dictionary<string, Texture>> _textureDict = new Dictionary<string, Dictionary<string, Texture>>();
Dictionary<string, Dictionary<string, Sprite>> _spriteDict = new Dictionary<string, Dictionary<string, Sprite>>();
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<string, Action> _waitingBlockDict = new Dictionary<string, Action>();
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<GameObject>(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<UIManager>();
* Instance.screenType = screen_type;
* Instance.canvasScaler = main_ui.GetComponent<CanvasScaler>();
* Instance.WaitingTimeOutDefaultCallback = default_waiting_timeout_callback;
*
* var waiting_obj = main_ui.FindChildGameObject("WaitingBlock");
*
* if (waiting_obj != null)
* {
* var trans = waiting_obj.GetComponent<RectTransform>();
* 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<UIManager>();
Instance.screenType = screen_type;
Instance.canvasScaler = main_ui.GetComponent<CanvasScaler>();
Instance.WaitingTimeOutDefaultCallback = default_waiting_timeout_callback;
var waiting_obj = main_ui.FindChildGameObject("WaitingBlock");
if (waiting_obj != null)
{
var trans = waiting_obj.GetComponent<RectTransform>();
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<RectTransform>();
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<string> keys = new List<string>(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<CanvasGroup>().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<CanvasGroup>().alpha = 1;
}
UnblockInput();
}
void _ClearWaitingBlock()
{
if (WaitingPanel != null)
{
WaitingPanel.gameObject.SetActiveAsNeed(false);
WaitingPanel.GetComponent<CanvasGroup>().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<Canvas>();
//UICamera = UICanvas.renderMode == RenderMode.ScreenSpaceOverlay ? Camera.main : GetComponentInChildren<Camera>();
graphicRaycaster = GetComponent<GraphicRaycaster>();
RectTrans = GetComponent<RectTransform>();
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<Image>();
}
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<WaitingUI>();
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<GameObject> 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<GameObject> 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<RectTransform>(), 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;
}
/// <summary>
/// 已经确定提前下好 或不需要下载的Panel 走这个接口
/// 不显示Loading条
/// </summary>
/// <param name="ui_type"></param>
/// <returns></returns>
public async Task<GameObject> 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;
}
/// <summary>
/// 如果需要下载 并且不下载 就返回 Null
/// </summary>
/// <param name="ui_type"></param>
/// <returns></returns>
public async Task<GameObject> 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<ILoadResourceService>();
bool isCanEnter = await loadResourceService.Load(ui_type.Path);
if (!isCanEnter)
{
TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
var panel = await ShowUINotLoading(UITypes.DownLoadPopupPanel);
panel.GetComponent<DownLoadPopupPanel>().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;
}
/// <summary>
/// 不确定是否下载走这个接口 弹loading动画
/// </summary>
/// <param name="ui_type"></param>
/// <returns></returns>
public async Task<GameObject> 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<ILoadResourceService>();
bool isCanEnter = await loadResourceService.Load(ui_type.Path);
if (!isCanEnter)
{
TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
var panel = await ShowUINotLoading(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>().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;
}
/// <summary>
/// 请使用 ShowUILoad 并做好判空处理
/// 如果确定已经下载好或者不需要下载 请使用 ShowUINotLoading
/// </summary>
/// <param name="ui_type"></param>
/// <returns></returns>
public async Task<GameObject> 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<GameObject> LoadUIAssetAsync(UIType ui_type)
{
var add = await Addressables.LoadAssetAsync<GameObject>(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<RectTransform>(), 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();
}
}
/// <summary>
/// Clone the first Sprite in this atlas that matches the name packed in this atlas and return it.
/// Note: Using AssetBundle.GetAsset<Sprite> will not clone, and will be better.
/// </summary>
/// <param name="atlas_name"></param>
/// <param name="sprite_name"></param>
/// <returns></returns>
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<SpriteAtlas>(atlas_name);
var atlas = Addressables.LoadAssetAsync<SpriteAtlas>(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<string, Texture>();
_textureDict.Add(dicName, textures);
}
texture = await Addressables.LoadAssetAsync<Texture>(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;
}
}
}