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);
}
}
}