using System; using System.Collections.Generic; using System.Linq; using FairyGUI; using NBC.Asset; using UnityEngine; namespace NBC { public class UIManager : EventDispatcher { /// /// 所有UI /// private readonly Dictionary _uiArray = new Dictionary(); private GGraph _modalLayer; private GRoot _uiRoot; private UIComponentLanguagePack _uiLanguageConfig; // 新增 Tween 配置 private UIComponentTweenPack _uiTweenConfig; public void Start() { Log.Info("UI 模块初始化"); _uiRoot = GRoot.inst; MonoManager.Inst.OnUpdate += Update; UICommand.Init(this); } public void Quit() { MonoManager.Inst.OnUpdate -= Update; } void Update() { UIRunner.Update(); foreach (var panel in _uiArray.Values) { if (panel != null && panel.IsShowing) { panel.Update(); } } } #region 内部方法 internal void ShowUI(string uiName, object param = null) { IUIPanel panel = GetUI(uiName); panel.SetData(param); if (panel.IsShowing) { panel.Refresh(); } else { ApplyPanelRootTween(panel); // 根动效设置为 ShowAnim panel.Show(); } } internal void RemoveUI(string uiName) { IUIPanel wind = GetUI(uiName); if (wind == null) { Log.Warning($"要删除的界面不存在:{uiName}"); return; } if (!wind.IsDotDel) { wind.Dispose(); _uiArray.Remove(uiName); } } private void CreateModalLayer() { var modalLayerColor = UIConfig.modalLayerColor; if (_modalLayer != null) { _modalLayer.onClick.Clear(); } _modalLayer = new GGraph(); _modalLayer.DrawRect(_uiRoot.width, _uiRoot.height, 0, Color.white, modalLayerColor); _modalLayer.AddRelation(_uiRoot, RelationType.Size); _modalLayer.name = _modalLayer.gameObjectName = "ModalLayer"; _modalLayer.SetHome(_uiRoot); } #endregion #region 动画 public void SetUITween() where T : UIComponentTweenPack { _uiTweenConfig = Activator.CreateInstance(); } public void TryPlayComponentTween(GComponent component) { _uiTweenConfig?.TryPlayComponentTween(component); } public void TryPlayPanelTween(GComponent component) { _uiTweenConfig?.TryPlayPanelTween(component); } private void ApplyPanelRootTween(IUIPanel panel) { if (panel?.ContentPane == null || _uiTweenConfig == null) return; var url = panel.ContentPane.resourceURL; if (string.IsNullOrEmpty(url)) return; var tweenName = _uiTweenConfig.GetRootTween(url); if (string.IsNullOrEmpty(tweenName)) return; if (panel is not UIPanel upPanel) return; // 需要具体 UIPanel 才能设置 ShowAnim if (upPanel.ShowAnim != null) return; switch (tweenName) { case "Fade": upPanel.ShowAnim = UIPanelAnimation.GetFade(upPanel); break; case "Scale": upPanel.ShowAnim = UIPanelAnimation.GetCenterScaleBig(upPanel); break; case "Pop": upPanel.ShowAnim = UIPanelAnimation.GetCenterPopScaleFade(upPanel); break; case "SlideInL": upPanel.ShowAnim = UIPanelAnimation.GetLeftToSlideFade(upPanel); break; case "SlideInR": upPanel.ShowAnim = UIPanelAnimation.GetRightToSlideFade(upPanel); break; case "SlideInT": upPanel.ShowAnim = UIPanelAnimation.GetUpToSlideFade(upPanel); break; case "SlideInB": upPanel.ShowAnim = UIPanelAnimation.GetDownToSlideFade(upPanel); break; case "Bounce": upPanel.ShowAnim = UIPanelAnimation.GetBounceVertical(upPanel); break; case "Rotate": upPanel.ShowAnim = UIPanelAnimation.GetRotate(upPanel); break; case "Shake": upPanel.ShowAnim = UIPanelAnimation.GetShake(upPanel); break; default: break; } } #endregion public void OpenUI(object param = null) { Type type = typeof(T); OpenUI(type.Name, type, param); } public void OpenUI(Type type, object param = null) { OpenUI(type.Name, type, param); } public void OpenUI(string uiName, object param = null, Action callback = null) { Type type = typeof(T); OpenUI(uiName, type, param, callback); } public void OpenUI(string uiName, Type type, object param = null, Action callback = null) { UICommand.GetCmd(UICmdType.Show).SetUIData(type, uiName, param).SetCallback(callback).Run(); } internal void AddUI(string uiName, IUIPanel panel) { if (_uiArray.ContainsKey(uiName)) { Log.Error("AddUI重复添加"); } _uiArray.Add(uiName, panel); } public T GetUI() where T : class { IUIPanel wind = null; Type type = typeof(T); var uiName = type.Name; foreach (var name in _uiArray.Keys) { if (name != uiName) continue; wind = _uiArray[name]; break; } return wind as T; } public IUIPanel GetUI(Type type) { return GetUI(type.Name); } public IUIPanel GetUI(string uiName) { IUIPanel wind = null; foreach (var name in _uiArray.Keys) { if (name != uiName) continue; wind = _uiArray[name]; break; } return wind; } public IUIPanel[] GetAllUI() { return _uiArray.Values.ToArray(); } public List GetAllUIName() { return _uiArray.Keys.ToList(); } public void HideUI(Type type) { HideUI(type.Name); } public void HideUI() { Type type = typeof(T); HideUI(type.Name); } public void HideUI(string uiName) { UICommand.GetCmd(UICmdType.Hide).SetUIData(null, uiName, null).Run(); } /// /// 隐藏所有窗口 /// public void HideAllUI(bool isDotDel = false) { var names = GetAllUIName(); foreach (var uiName in names) { IUIPanel panel = GetUI(uiName); if (panel.IsShowing) { if (!panel.IsDotDel || isDotDel) { HideUI(uiName); } } } } /// /// 删除所有打开的窗口 /// public void DeleteAllUI() { var names = GetAllUIName(); foreach (var uiName in names) { DestroyUI(uiName); } } public void DestroyUI() { Type type = typeof(T); DestroyUI(type.Name); } public void DestroyUI(Type type) { DestroyUI(type.Name); } public void DestroyUI(string uiName) { UICommand.GetCmd(UICmdType.Del).SetUIData(null, uiName, null).Run(); } public void BringToFront(IUIPanel uiPanel) { var uiRoot = GRoot.inst; var contentPane = uiPanel.ContentPane; if (contentPane.parent != uiRoot) { Log.Error("不在root内,无法置顶=="); return; } var cnt = uiRoot.numChildren; var i = 0; if (_modalLayer != null && _modalLayer.parent != null && !uiPanel.IsModal) { i = uiRoot.GetChildIndex(_modalLayer); } else { i = cnt - 1; } if (i >= 0) { uiRoot.SetChildIndex(contentPane, i); } } public bool IsTop(IUIPanel uiPanel) { var parent = uiPanel.ContentPane.parent; if (parent == null) return false; var sortingOrder = uiPanel.ContentPane.sortingOrder; var maxIndex = -1; var panels = _uiArray.Values; foreach (var panel in panels) { if (panel.IsShowing && panel.ContentPane.sortingOrder == sortingOrder) { //只判断同层级的 var index = parent.GetChildIndex(panel.ContentPane); if (index > maxIndex) { maxIndex = index; } } } var uiIndex = parent.GetChildIndex(uiPanel.ContentPane); return uiIndex >= maxIndex; } public void AdjustModalLayer() { if (_modalLayer == null || _modalLayer.isDisposed) { CreateModalLayer(); } var showDic = new Dictionary(); var panels = _uiArray.Values; foreach (var panel in panels) { if (panel.IsShowing) { showDic[panel.ContentPane] = panel; } } var cnt = _uiRoot.numChildren; for (var i = cnt - 1; i >= 0; i--) { var g = _uiRoot.GetChildAt(i); if (showDic.TryGetValue(g, out var panel)) { if (panel.IsModal) { if (_modalLayer.parent == null) _uiRoot.AddChildAt(_modalLayer, i); else { _uiRoot.SetChildIndexBefore(_modalLayer, i); } return; } } } if (_modalLayer != null && _modalLayer.parent != null) { _uiRoot.RemoveChild(_modalLayer); } } public bool IsOpen(string uiName) { IUIPanel wind = GetUI(uiName); return wind != null && wind.IsShowing; } public void AddPackage(string assetPath) { AddPackage(UIConst.UIPackRootUrl, assetPath); } public void AddPackage(string root, string assetPath) { var path = root + assetPath; if (path.StartsWith("Assets/")) { UIPackage.AddPackage(path, (string name, string extension, Type type, out DestroyMethod method) => { method = DestroyMethod.None; var pro = Assets.LoadAsset(name.Replace("\\", "/") + extension, type); return pro?.Asset; }); } else { UIPackage.AddPackage(path); } // UIPackage.AddPackage(path); } public void OpenSafeArea() { UIConst.OpenSafeArea = true; } public void SetSafeArea(Rect rect) { UIConst.SafeArea = rect; } public Rect GetSafeArea() { return UIConst.SafeArea; } public void SetUILanguage() where T : UIComponentLanguagePack { _uiLanguageConfig = Activator.CreateInstance(); } public void TrySetComponentLanguage(GComponent component) { _uiLanguageConfig.TrySetComponentLanguage(component); } public void TrySetPanelLanguage(GComponent component) { _uiLanguageConfig.TrySetPanelLanguage(component); } } }