using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using Object = UnityEngine.Object; namespace AlicizaX.UI.Runtime { internal sealed partial class UIManager { private readonly Dictionary> mShowUIWindow = new Dictionary>((int)UILayer.All); private async UniTask ShowUIImplAsync(Type type, params System.Object[] userDatas) { var panelInfo = CreateUIClsInstance(type); panelInfo.UIBasePanel.RefreshParams(userDatas); if (panelInfo.PanelState == EPanelState.None && !panelInfo.UIBasePanel.IsLoaded) { await CreateUIResInstanceAsync(panelInfo); panelInfo.UIBasePanel.InternalInitlize(); Push(panelInfo); } else if (panelInfo.PanelState == EPanelState.Show) { Pop(panelInfo); Push(panelInfo); } else if (panelInfo.PanelState == EPanelState.Cache) { RemoveFromCache(panelInfo); Push(panelInfo); } BeforeShowUI(panelInfo).Forget(); return panelInfo.UIBasePanel; } public UIWindow ShowUIImpl(Type type, params System.Object[] userDatas) { var panelInfo = CreateUIClsInstance(type); panelInfo.UIBasePanel.RefreshParams(userDatas); if (panelInfo.PanelState == EPanelState.None && !panelInfo.UIBasePanel.IsLoaded) { CreateUIResInstance(panelInfo); panelInfo.UIBasePanel.InternalInitlize(); Push(panelInfo); } else if (panelInfo.PanelState == EPanelState.Show) { Pop(panelInfo); Push(panelInfo); } else if (panelInfo.PanelState == EPanelState.Cache) { RemoveFromCache(panelInfo); Push(panelInfo); } BeforeShowUI(panelInfo).Forget(); return panelInfo.UIBasePanel; } public void CloseUIImpl(Type type, bool force) { var panelInfo = GetWindowInfo(type); if (panelInfo.UIBasePanel == null) { return; } AfterCloseUI(panelInfo, force).Forget(); } private PanelInfo CreateUIClsInstance(Type type) { var info = GetWindowInfo(type); if (info.PanelState == EPanelState.None && info.UIBasePanel == null) { info.Reset((UIWindow)Activator.CreateInstance(info.UIClsType)); } else if (info.PanelState == EPanelState.Cache && info.UIBasePanel == null) { RemoveFromCache(info); } return info; } private async UniTask CreateUIResInstanceAsync(PanelInfo panelInfo) { if (panelInfo.UIResLoadType == EUIResLoadType.AssetBundle) { var uiInstance = await _resourceManager.LoadGameObjectAsync(panelInfo.Res, parent: GetLayerRect(panelInfo.UIPanelLayer)); panelInfo.UIBasePanel.InternalCreate(uiInstance); } else { var uiPrefab = Resources.Load(panelInfo.Res); var uiInstance = Object.Instantiate(uiPrefab, GetLayerRect(panelInfo.UIPanelLayer)); panelInfo.UIBasePanel.InternalCreate(uiInstance); } } private void CreateUIResInstance(PanelInfo panelInfo) { if (panelInfo.UIResLoadType == EUIResLoadType.AssetBundle) { var uiInstance = _resourceManager.LoadGameObject(panelInfo.Res, parent: GetLayerRect(panelInfo.UIPanelLayer)); panelInfo.UIBasePanel.InternalCreate(uiInstance); } else { var uiPrefab = Resources.Load(panelInfo.Res); var uiInstance = Object.Instantiate(uiPrefab, GetLayerRect(panelInfo.UIPanelLayer)); panelInfo.UIBasePanel.InternalCreate(uiInstance); } } private void Push(PanelInfo info) { // 如果已经存在 if (IsContains(info)) throw new System.Exception($"Window {info.Name} is exist."); var list = GetLayerPanelInfoList(info.UIPanelLayer); int insertIndex = -1; for (int i = 0; i < list.Count; i++) { if (info.UIPanelLayer == list[i].UIPanelLayer) { insertIndex = i + 1; } } // 如果没有所属层级,找到相邻层级 if (insertIndex == -1) { for (int i = 0; i < list.Count; i++) { if (info.UIPanelLayer > list[i].UIPanelLayer) { insertIndex = i + 1; } } } // 如果是空栈或没有找到插入位置 if (insertIndex == -1) { insertIndex = 0; } // 最后插入到堆栈 mShowUIWindow[info.UIPanelLayer].Insert(insertIndex, info); } private void Pop(PanelInfo info) { mShowUIWindow[info.UIPanelLayer].Remove(info); } private async UniTaskVoid BeforeShowUI(PanelInfo info) { info.SetPanelState(EPanelState.Show); SetPanelLayer(info, info.UIPanelLayer); info.UIBasePanel.InternalOpen(); SortWindowVisible(); SortWindowDepth(info); if (info.UIBasePanel is IUIOpenTween tweenUI) { await tweenUI.OnOpenTween(); } } private async UniTaskVoid AfterCloseUI(PanelInfo panelInfo, bool force) { if (panelInfo.UIBasePanel is IUICloseTween tweenUI) { await tweenUI.OnCloseTween(); } panelInfo.UIBasePanel.InternalClose(); Pop(panelInfo); SortWindowVisible(); if (force || panelInfo.DelayedClose == 0) { panelInfo.UIBasePanel.InternalDestroy(); panelInfo.Reset(null); panelInfo.SetPanelState(EPanelState.None); return; } CacheWindow(panelInfo); } private void SetPanelLayer(PanelInfo info, UILayer layer) { if (info.UIBasePanel != null) { info.UIBasePanel.transform.SetParent(GetLayerRect(layer)); } } private void SortWindowVisible() { //Panel TODO var list = GetLayerPanelInfoList(UILayer.UI); bool isHideNext = false; for (int i = list.Count - 1; i >= 0; i--) { PanelInfo panelInfo = list[i]; if (isHideNext == false) { panelInfo.UIBasePanel.Visible = true; if (panelInfo.UIBasePanel.IsLoaded && panelInfo.FullScreen) { isHideNext = true; } } else { panelInfo.UIBasePanel.Visible = false; } } } private void SortWindowDepth(PanelInfo info) { int depth = (int)info.UIPanelLayer * LAYER_DEEP; var _stack = GetLayerPanelInfoList(info.UIPanelLayer); for (int i = 0; i < _stack.Count; i++) { if (_stack[i].UIPanelLayer == info.UIPanelLayer) { _stack[i].UIBasePanel.Depth = depth; depth += WINDOW_DEEP; } } } private List GetLayerPanelInfoList(UILayer panelLayer) { return mShowUIWindow[panelLayer]; } private bool IsContains(PanelInfo info) { var list = GetLayerPanelInfoList(info.UIPanelLayer); for (int i = 0; i < list.Count; i++) { PanelInfo window = list[i]; if (window.Name == info.Name) { return true; } } return false; } private UIWindow GetUIInstance(Type type) { var info = GetWindowInfo(type); var list = GetLayerPanelInfoList(info.UIPanelLayer); for (int i = 0; i < list.Count; i++) { PanelInfo window = list[i]; if (window.Name == info.Name) { return window.UIBasePanel; } } return null; } } }