using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using TEngine; using UnityEngine; namespace GameLogic { /// /// UI基类。 /// public class UIBase { /// /// UI类型。 /// public enum UIType { /// /// 类型无。 /// None, /// /// 类型Windows。 /// Window, /// /// 类型Widget。 /// Widget, } /// /// 所属UI父节点。 /// protected UIBase _parent = null; /// /// UI父节点。 /// public UIBase Parent => _parent; /// /// 自定义数据集。 /// protected System.Object[] _userDatas; /// /// 自定义数据。 /// public System.Object UserData { get { if (_userDatas != null && _userDatas.Length >= 1) { return _userDatas[0]; } else { return null; } } } /// /// 自定义数据集。 /// public System.Object[] UserDatas => _userDatas; /// /// 窗口的实例资源对象。 /// // ReSharper disable once InconsistentNaming public virtual GameObject gameObject { protected set; get; } /// /// 窗口位置组件。 /// // ReSharper disable once InconsistentNaming public virtual Transform transform { protected set; get; } /// /// 窗口矩阵位置组件。 /// // ReSharper disable once InconsistentNaming public virtual RectTransform rectTransform { protected set; get; } /// /// UI类型。 /// public virtual UIType Type => UIType.None; /// /// 资源是否准备完毕。 /// public bool IsPrepare { protected set; get; } /// /// UI子组件列表。 /// internal readonly List ListChild = new List(); /// /// 存在Update更新的UI子组件列表。 /// protected List _listUpdateChild = null; /// /// 是否持有Update行为。 /// protected bool _updateListValid = false; /// /// 代码自动生成绑定。 /// protected virtual void ScriptGenerator() { } /// /// 绑定UI成员元素。 /// protected virtual void BindMemberProperty() { } /// /// 注册事件。 /// protected virtual void RegisterEvent() { } /// /// 窗口创建。 /// protected virtual void OnCreate() { } /// /// 窗口刷新。 /// protected virtual void OnRefresh() { } /// /// 是否需要Update。 /// protected bool _hasOverrideUpdate = true; /// /// 窗口更新。 /// protected virtual void OnUpdate() { _hasOverrideUpdate = false; } internal void CallDestroy() { OnDestroy(); } /// /// 窗口销毁。 /// protected virtual void OnDestroy() { } /// /// 当触发窗口的层级排序。 /// protected virtual void OnSortDepth(int depth) { } /// /// 当因为全屏遮挡触或者窗口可见性触发窗口的显隐。 /// protected virtual void OnSetVisible(bool visible) { } internal void SetUpdateDirty() { _updateListValid = false; if (Parent != null) { Parent.SetUpdateDirty(); } } #region FindChildComponent public Transform FindChild(string path) { return FindChildImp(rectTransform, path); } public Transform FindChild(Transform trans, string path) { return FindChildImp(trans, path); } public T FindChildComponent(string path) where T : Component { return FindChildComponentImp(rectTransform, path); } public T FindChildComponent(Transform trans, string path) where T : Component { return FindChildComponentImp(trans, path); } private static Transform FindChildImp(Transform transform, string path) { var findTrans = transform.Find(path); return findTrans != null ? findTrans : null; } private static T FindChildComponentImp(Transform transform, string path) where T : Component { var findTrans = transform.Find(path); if (findTrans != null) { return findTrans.gameObject.GetComponent(); } return null; } #endregion #region UIEvent private GameEventMgr _eventMgr; protected GameEventMgr EventMgr { get { if (_eventMgr == null) { _eventMgr = MemoryPool.Acquire(); } return _eventMgr; } } public void AddUIEvent(int eventType, Action handler) { EventMgr.AddEvent(eventType, handler); } protected void AddUIEvent(int eventType, Action handler) { EventMgr.AddEvent(eventType, handler); } protected void AddUIEvent(int eventType, Action handler) { EventMgr.AddEvent(eventType, handler); } protected void AddUIEvent(int eventType, Action handler) { EventMgr.AddEvent(eventType, handler); } protected void AddUIEvent(int eventType, Action handler) { EventMgr.AddEvent(eventType, handler); } protected void RemoveAllUIEvent() { if (_eventMgr != null) { MemoryPool.Release(_eventMgr); } } #endregion #region UIWidget /// /// 创建UIWidget通过父UI位置节点。 /// 因为资源实例已经存在父物体所以不需要异步。 /// /// 父UI位置节点。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidget(string goPath, bool visible = true) where T : UIWidget, new() { var goRootTrans = FindChild(goPath); if (goRootTrans != null) { return CreateWidget(goRootTrans.gameObject, visible); } return null; } /// /// 创建UIWidget通过父UI位置节点。 /// 因为资源实例已经存在父物体所以不需要异步。 /// /// /// 父UI位置节点。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidget(Transform parentTrans, string goPath, bool visible = true) where T : UIWidget, new() { var goRootTrans = FindChild(parentTrans, goPath); if (goRootTrans != null) { return CreateWidget(goRootTrans.gameObject, visible); } return null; } /// /// 创建UIWidget通过游戏物体。 /// 因为资源实例已经存在父物体所以不需要异步。 /// /// 游戏物体。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidget(GameObject goRoot, bool visible = true) where T : UIWidget, new() { var widget = new T(); if (widget.Create(this, goRoot, visible)) { return widget; } return null; } /// /// 创建UIWidget通过资源定位地址。 /// /// 资源父节点。 /// 资源定位地址。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidgetByPath(Transform parentTrans, string assetLocation, bool visible = true) where T : UIWidget, new() { GameObject goInst = UIModule.Resource.LoadGameObject(assetLocation, parent: parentTrans); return CreateWidget(goInst, visible); } /// /// 创建UIWidget通过资源定位地址。 /// /// 资源父节点。 /// 资源定位地址。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public async UniTask CreateWidgetByPathAsync(Transform parentTrans, string assetLocation, bool visible = true) where T : UIWidget, new() { GameObject goInst = await UIModule.Resource.LoadGameObjectAsync(assetLocation, parentTrans, gameObject.GetCancellationTokenOnDestroy()); return CreateWidget(goInst, visible); } /// /// 根据prefab或者模版来创建新的 widget。 /// /// 资源创建副本。 /// 资源父节点。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidgetByPrefab(GameObject goPrefab, Transform parentTrans = null, bool visible = true) where T : UIWidget, new() { var widget = new T(); if (!widget.CreateByPrefab(this, goPrefab, parentTrans, visible)) { return null; } return widget; } /// /// 通过UI类型来创建widget。 /// /// 资源父节点。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public T CreateWidgetByType(Transform parentTrans, bool visible = true) where T : UIWidget, new() { return CreateWidgetByPath(parentTrans, typeof(T).Name, visible); } /// /// 通过UI类型来创建widget。 /// /// 资源父节点。 /// 是否可见。 /// UIWidget。 /// UIWidget实例。 public async UniTask CreateWidgetByTypeAsync(Transform parentTrans, bool visible = true) where T : UIWidget, new() { return await CreateWidgetByPathAsync(parentTrans, typeof(T).Name, visible); } /// /// 调整图标数量。 /// /// 常用于Icon创建。 /// 存放Icon的列表。 /// 创建数目。 /// 资源父节点。 /// 资产副本。 /// 资产地址。 /// 图标类型。 public void AdjustIconNum(List listIcon, int number, Transform parentTrans, GameObject prefab = null, string assetPath = "") where T : UIWidget, new() { if (listIcon == null) { listIcon = new List(); } if (listIcon.Count < number) { int needNum = number - listIcon.Count; for (int iconIdx = 0; iconIdx < needNum; iconIdx++) { T tmpT = prefab == null ? CreateWidgetByType(parentTrans) : CreateWidgetByPrefab(prefab, parentTrans); listIcon.Add(tmpT); } } else if (listIcon.Count > number) { RemoveUnUseItem(listIcon, number); } } /// /// 异步调整图标数量。 /// /// /// /// /// /// /// /// /// public void AsyncAdjustIconNum(List listIcon, int tarNum, Transform parentTrans, GameObject prefab = null, string assetPath = "", int maxNumPerFrame = 5, Action updateAction = null) where T : UIWidget, new() { AsyncAdjustIconNumInternal(listIcon, tarNum, parentTrans, maxNumPerFrame, updateAction, prefab, assetPath).Forget(); } /// /// 异步创建接口。 /// /// /// /// /// /// /// /// /// private async UniTaskVoid AsyncAdjustIconNumInternal(List listIcon, int tarNum, Transform parentTrans, int maxNumPerFrame, Action updateAction, GameObject prefab, string assetPath) where T : UIWidget, new() { if (listIcon == null) { listIcon = new List(); } int createCnt = 0; for (int i = 0; i < tarNum; i++) { T tmpT = null; if (i < listIcon.Count) { tmpT = listIcon[i]; } else { if (prefab == null) { tmpT = await CreateWidgetByPathAsync(parentTrans, assetPath); } else { tmpT = CreateWidgetByPrefab(prefab, parentTrans); } listIcon.Add(tmpT); } int index = i; if (updateAction != null) { updateAction(tmpT, index); } createCnt++; if (createCnt >= maxNumPerFrame) { createCnt = 0; await UniTask.Yield(); } } if (listIcon.Count > tarNum) { RemoveUnUseItem(listIcon, tarNum); } } private void RemoveUnUseItem(List listIcon, int tarNum) where T : UIWidget { var removeIcon = new List(); for (int iconIdx = 0; iconIdx < listIcon.Count; iconIdx++) { var icon = listIcon[iconIdx]; if (iconIdx >= tarNum) { removeIcon.Add(icon); } } for (var index = 0; index < removeIcon.Count; index++) { var icon = removeIcon[index]; listIcon.Remove(icon); icon.OnDestroy(); icon.OnDestroyWidget(); ListChild.Remove(icon); if (icon.gameObject != null) { UnityEngine.Object.Destroy(icon.gameObject); } } } #endregion } }