diff --git a/Assets/TEngine/Runtime/GameFramework/UI/UIBase.cs b/Assets/TEngine/Runtime/GameFramework/UI/UIBase.cs index 7b5e72ce..a69fab6c 100644 --- a/Assets/TEngine/Runtime/GameFramework/UI/UIBase.cs +++ b/Assets/TEngine/Runtime/GameFramework/UI/UIBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Cysharp.Threading.Tasks; using UnityEngine; using YooAsset; @@ -14,71 +15,78 @@ namespace TEngine /// 类型无。 /// None, + /// /// 类型Windows。 /// Window, + /// /// 类型Widget。 /// Widget, } - + /// /// UI基类。 /// - public class UIBase:IUIBehaviour + public class UIBase : IUIBehaviour { /// /// 所属UI父节点。 /// protected UIBase parent = null; - + /// /// UI父节点。 /// public UIBase Parent => parent; - + /// /// 窗口的实例资源对象。 /// public virtual GameObject gameObject { protected set; get; } - + /// /// 窗口矩阵位置组件。 /// - public virtual RectTransform rectTransform { protected set; get; } - + public virtual RectTransform rectTransform { protected set; get; } + /// /// UI类型。 /// public virtual UIBaseType BaseType => UIBaseType.None; - + /// /// 资源操作句柄。 /// public AssetOperationHandle Handle { protected set; get; } - + + /// + /// 资源组数据。 + /// + public AssetGroup AssetGroup { protected set; get; } + /// /// 资源是否准备完毕。 /// public bool IsPrepare { protected set; get; } - + /// /// UI子组件列表。 /// public List ListChild = new List(); - + /// /// 存在Update更新的UI子组件列表。 /// protected List m_listUpdateChild = null; - + /// /// 是否持有Update行为。 /// protected bool m_updateListValid = false; - + /// /// 代码自动生成绑定。 /// @@ -118,6 +126,7 @@ namespace TEngine /// 是否需要Update /// protected bool HasOverrideUpdate = true; + /// /// 窗口更新 /// @@ -132,7 +141,7 @@ namespace TEngine public virtual void OnDestroy() { } - + /// /// 当触发窗口的层级排序 /// @@ -146,8 +155,8 @@ namespace TEngine protected virtual void OnSetVisible(bool visible) { } - - + + #region FindChildComponent public Transform FindChild(string path) @@ -225,7 +234,8 @@ namespace TEngine #endregion #region UIWidget - public T CreateWidget(string goPath, bool visible = true) where T : UIWidget,new() + + public T CreateWidget(string goPath, bool visible = true) where T : UIWidget, new() { var goRootTrans = FindChild(goPath); @@ -236,8 +246,8 @@ namespace TEngine return null; } - - public T CreateWidget(GameObject goRoot, bool visible = true) where T : UIWidget,new() + + public T CreateWidget(GameObject goRoot, bool visible = true) where T : UIWidget, new() { var widget = new T(); if (widget.Create(this, goRoot, visible)) @@ -248,6 +258,163 @@ namespace TEngine return null; } + 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; + } + + public T CreateWidgetByPath(Transform parentTrans, string assetPath, bool visible = true) where T : UIWidget, new() + { + if (AssetGroup == null) + { + AssetGroup = AssetGroup.Alloc(); + } + + GameObject goInst = AssetGroup.LoadAsset(assetPath, parentTrans); + return CreateWidget(goInst, visible); + } + + 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; + } + + public T CreateWidgetByType(Transform parentTrans, bool visible = true) where T : UIWidget, new() + { + return CreateWidgetByPath(parentTrans, typeof(T).Name, visible); + } + + /// + /// 调整图标数量。 + /// + public void AdjustIconNum(List listIcon, int tarNum, Transform parent, GameObject prefab = null, string assetPath = "") where T : UIWidget, new() + { + if (listIcon == null) + { + listIcon = new List(); + } + + if (listIcon.Count < tarNum) + { + int needNum = tarNum - listIcon.Count; + for (int iconIdx = 0; iconIdx < needNum; iconIdx++) + { + T tmpT = prefab == null ? CreateWidgetByType(parent) : CreateWidgetByPrefab(prefab, parent); + listIcon.Add(tmpT); + } + } + else if (listIcon.Count > tarNum) + { + RemoveUnUseItem(listIcon, tarNum); + } + } + + /// + /// 异步调整图标数量。 + /// + /// + /// + /// + /// + /// + /// + /// + /// + 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 = CreateWidgetByPath(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(); + ListChild.Remove(icon); + UnityEngine.Object.Destroy(icon.gameObject); + } + } + #endregion } } \ No newline at end of file diff --git a/Assets/TEngine/Runtime/GameFramework/UI/UIWidget.cs b/Assets/TEngine/Runtime/GameFramework/UI/UIWidget.cs index 59c6ec58..75c7bccf 100644 --- a/Assets/TEngine/Runtime/GameFramework/UI/UIWidget.cs +++ b/Assets/TEngine/Runtime/GameFramework/UI/UIWidget.cs @@ -131,6 +131,22 @@ namespace TEngine return CreateImp(parentUI, widgetRoot, false, visible); } + /// + /// 根据prefab或者模版来创建新的 widget。 + /// + /// + /// + /// + /// + /// + public bool CreateByPrefab(UIBase parentUI, GameObject goPrefab, Transform parentTrans, bool visible = true) + { + if (parentTrans == null) + { + parentTrans = parentUI.rectTransform; + } + return CreateImp(parentUI, Object.Instantiate(goPrefab, parentTrans), true, visible); + } private bool CreateImp(UIBase parentUI, GameObject widgetRoot, bool bindGo, bool visible = true) { @@ -171,11 +187,15 @@ namespace TEngine { return; } - var listCanvas = gameObject.GetComponentsInChildren(true); - for (var index = 0; index < listCanvas.Length; index++) + + if (gameObject != null) { - var childCanvas = listCanvas[index]; - childCanvas.sortingOrder = parentCanvas.sortingOrder + childCanvas.sortingOrder % UIModule.WINDOW_DEEP; + var listCanvas = gameObject.GetComponentsInChildren(true); + for (var index = 0; index < listCanvas.Length; index++) + { + var childCanvas = listCanvas[index]; + childCanvas.sortingOrder = parentCanvas.sortingOrder + childCanvas.sortingOrder % UIModule.WINDOW_DEEP; + } } } #endregion diff --git a/Assets/TEngine/Runtime/GameFramework/UI/UIWindow.cs b/Assets/TEngine/Runtime/GameFramework/UI/UIWindow.cs index 6f2756f0..2e7dc899 100644 --- a/Assets/TEngine/Runtime/GameFramework/UI/UIWindow.cs +++ b/Assets/TEngine/Runtime/GameFramework/UI/UIWindow.cs @@ -248,6 +248,9 @@ namespace TEngine if (_isCreate == false) { _isCreate = true; + ScriptGenerator(); + BindMemberProperty(); + RegisterEvent(); OnCreate(); } } @@ -334,6 +337,11 @@ namespace TEngine RemoveAllUIEvent(); + for (int i = 0; i < ListChild.Count; i++) + { + ListChild[i].OnDestroy(); + } + // 注销回调函数 _prepareCallback = null; @@ -344,6 +352,12 @@ namespace TEngine Handle = null; } + if (AssetGroup != null) + { + AssetGroup.Release(AssetGroup); + AssetGroup = null; + } + // 销毁面板对象 if (_panel != null) {