mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Init TEngine4.0.0
Init TEngine4.0.0
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2885c31816f64323ab3d3e803f41d0fc
|
||||
timeCreated: 1695196700
|
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class ErrorLogger
|
||||
{
|
||||
public ErrorLogger()
|
||||
{
|
||||
Application.logMessageReceived += LogHandler;
|
||||
}
|
||||
|
||||
~ErrorLogger()
|
||||
{
|
||||
Application.logMessageReceived -= LogHandler;
|
||||
}
|
||||
|
||||
private void LogHandler(string condition, string stacktrace, LogType type)
|
||||
{
|
||||
if (type == LogType.Exception)
|
||||
{
|
||||
string des = $"客户端报错, \n#内容#:---{condition} \n#位置#:---{stacktrace}";
|
||||
GameModule.UI.ShowUIAsync<LogUI>(des);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ccc9fc5faf14d93baec285acaa97907
|
||||
timeCreated: 1681807720
|
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
[Window(UILayer.System,fromResources:true)]
|
||||
class LogUI : UIWindow
|
||||
{
|
||||
private Stack<string> _errorTextString = new Stack<string>();
|
||||
|
||||
#region 脚本工具生成的代码
|
||||
private Text m_textError;
|
||||
private Button m_btnClose;
|
||||
public override void ScriptGenerator()
|
||||
{
|
||||
m_textError = FindChildComponent<Text>("m_textError");
|
||||
m_btnClose = FindChildComponent<Button>("m_btnClose");
|
||||
m_btnClose.onClick.AddListener(OnClickCloseBtn);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
private void OnClickCloseBtn()
|
||||
{
|
||||
PopErrorLog().Forget();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override void OnRefresh()
|
||||
{
|
||||
_errorTextString.Push(UserData.ToString());
|
||||
m_textError.text = UserData.ToString();
|
||||
}
|
||||
|
||||
private async UniTaskVoid PopErrorLog()
|
||||
{
|
||||
if (_errorTextString.Count <= 0)
|
||||
{
|
||||
await UniTask.Yield();
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
string error = _errorTextString.Pop();
|
||||
m_textError.text = error;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: faa647c543e54de9b2d55e189aef0eff
|
||||
timeCreated: 1681807986
|
@@ -0,0 +1,44 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UI行为接口。
|
||||
/// </summary>
|
||||
public interface IUIBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动生成代码绑定。
|
||||
/// </summary>
|
||||
void ScriptGenerator();
|
||||
|
||||
/// <summary>
|
||||
/// 绑定自定义UI元素。
|
||||
/// </summary>
|
||||
void BindMemberProperty();
|
||||
|
||||
/// <summary>
|
||||
/// 注册UI事件。
|
||||
/// <remarks>方法=>AddUIEvent 在面板Destroy的时候会自动移除监听。</remarks>
|
||||
/// </summary>
|
||||
void RegisterEvent();
|
||||
|
||||
/// <summary>
|
||||
/// 面板创建成功。
|
||||
/// </summary>
|
||||
void OnCreate();
|
||||
|
||||
/// <summary>
|
||||
/// 面板刷新。
|
||||
/// </summary>
|
||||
void OnRefresh();
|
||||
|
||||
/// <summary>
|
||||
/// 面板轮询。
|
||||
/// </summary>
|
||||
void OnUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// 面板销毁。
|
||||
/// </summary>
|
||||
void OnDestroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dacc243d8184148b8dfedbf13368024
|
||||
timeCreated: 1680514817
|
@@ -0,0 +1,86 @@
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 打开窗口操作句柄。
|
||||
/// </summary>
|
||||
public class OpenWindowOperation : GameAsyncOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly AssetOperationHandle _handle;
|
||||
private ESteps _steps = ESteps.None;
|
||||
public UIWindow Window { get; private set; }
|
||||
|
||||
internal OpenWindowOperation(UIWindow uiWindow)
|
||||
{
|
||||
if (uiWindow == null)
|
||||
{
|
||||
throw new GameFrameworkException($"OpenWindowOperation .ctor uiWindow is null.");
|
||||
}
|
||||
_handle = uiWindow.Handle;
|
||||
Window = uiWindow;
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_handle == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
if (_handle.IsValid == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle)} is invalid.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handle.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_handle.AssetObject == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle.AssetObject)} is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步实例化结束
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (_handle != null)
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
_handle.WaitForAsyncComplete();
|
||||
OnUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ebdde8ab5014a73983249d935b415e4
|
||||
timeCreated: 1680520779
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 755c32b47dc831e468fa81b117d6865a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,358 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2683445925571829816
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2683445925571829817}
|
||||
- component: {fileID: 2683445925571829820}
|
||||
- component: {fileID: 2683445925571829822}
|
||||
m_Layer: 5
|
||||
m_Name: LogUI
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2683445925571829817
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445925571829816}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 2683445927021212027}
|
||||
- {fileID: 2683445926897574365}
|
||||
- {fileID: 6164213652418733423}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!223 &2683445925571829820
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445925571829816}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &2683445925571829822
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445925571829816}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 55
|
||||
--- !u!1 &2683445926897574364
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2683445926897574365}
|
||||
- component: {fileID: 2683445926897574339}
|
||||
- component: {fileID: 2683445926897574338}
|
||||
m_Layer: 5
|
||||
m_Name: m_textError
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2683445926897574365
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445926897574364}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2683445925571829817}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -10}
|
||||
m_SizeDelta: {x: -40, y: -60}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2683445926897574339
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445926897574364}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2683445926897574338
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445926897574364}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 1, b: 0.25490198, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 24
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 2
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 0
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text:
|
||||
--- !u!1 &2683445927021212026
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2683445927021212027}
|
||||
- component: {fileID: 2683445927021212025}
|
||||
- component: {fileID: 2683445927021212024}
|
||||
m_Layer: 5
|
||||
m_Name: Panel
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2683445927021212027
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445927021212026}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2683445925571829817}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2683445927021212025
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445927021212026}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2683445927021212024
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2683445927021212026}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 0.34901962}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &4229713281919198382
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6164213652418733423}
|
||||
- component: {fileID: 9023329926868908831}
|
||||
- component: {fileID: 5643637730633076069}
|
||||
- component: {fileID: 6030240422437967231}
|
||||
m_Layer: 5
|
||||
m_Name: m_btnClose
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6164213652418733423
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4229713281919198382}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2683445925571829817}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &9023329926868908831
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4229713281919198382}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &5643637730633076069
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4229713281919198382}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 0.007843138}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &6030240422437967231
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4229713281919198382}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 5643637730633076069}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b00e982fe4450248b4c7b9b62148cb2
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
740
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIBase.cs
Normal file
740
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIBase.cs
Normal file
@@ -0,0 +1,740 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UI类型。
|
||||
/// </summary>
|
||||
public enum UIBaseType
|
||||
{
|
||||
/// <summary>
|
||||
/// 类型无。
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 类型Windows。
|
||||
/// </summary>
|
||||
Window,
|
||||
|
||||
/// <summary>
|
||||
/// 类型Widget。
|
||||
/// </summary>
|
||||
Widget,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UI基类。
|
||||
/// </summary>
|
||||
public class UIBase : IUIBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属UI父节点。
|
||||
/// </summary>
|
||||
protected UIBase parent = null;
|
||||
|
||||
/// <summary>
|
||||
/// UI父节点。
|
||||
/// </summary>
|
||||
public UIBase Parent => parent;
|
||||
|
||||
/// <summary>
|
||||
/// 自动逸数据集。
|
||||
/// </summary>
|
||||
protected System.Object[] userDatas;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口的实例资源对象。
|
||||
/// </summary>
|
||||
public virtual GameObject gameObject { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口位置组件。
|
||||
/// </summary>
|
||||
public virtual Transform transform { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口矩阵位置组件。
|
||||
/// </summary>
|
||||
public virtual RectTransform rectTransform { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// UI类型。
|
||||
/// </summary>
|
||||
public virtual UIBaseType BaseType => UIBaseType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 资源操作句柄。
|
||||
/// </summary>
|
||||
public AssetOperationHandle Handle { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源引用数据。
|
||||
/// </summary>
|
||||
public AssetReference AssetReference { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源是否准备完毕。
|
||||
/// </summary>
|
||||
public bool IsPrepare { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// UI子组件列表。
|
||||
/// </summary>
|
||||
public List<UIWidget> ListChild = new List<UIWidget>();
|
||||
|
||||
/// <summary>
|
||||
/// 存在Update更新的UI子组件列表。
|
||||
/// </summary>
|
||||
protected List<UIWidget> m_listUpdateChild = null;
|
||||
|
||||
/// <summary>
|
||||
/// 是否持有Update行为。
|
||||
/// </summary>
|
||||
protected bool m_updateListValid = false;
|
||||
|
||||
/// <summary>
|
||||
/// 代码自动生成绑定。
|
||||
/// </summary>
|
||||
public virtual void ScriptGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绑定UI成员元素。
|
||||
/// </summary>
|
||||
public virtual void BindMemberProperty()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件。
|
||||
/// </summary>
|
||||
public virtual void RegisterEvent()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口创建。
|
||||
/// </summary>
|
||||
public virtual void OnCreate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口刷新
|
||||
/// </summary>
|
||||
public virtual void OnRefresh()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要Update
|
||||
/// </summary>
|
||||
protected bool HasOverrideUpdate = true;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口更新
|
||||
/// </summary>
|
||||
public virtual void OnUpdate()
|
||||
{
|
||||
HasOverrideUpdate = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口销毁
|
||||
/// </summary>
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当触发窗口的层级排序
|
||||
/// </summary>
|
||||
protected virtual void OnSortDepth(int depth)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当因为全屏遮挡触发窗口的显隐
|
||||
/// </summary>
|
||||
protected virtual void OnSetVisible(bool visible)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#region FindChildComponent
|
||||
|
||||
public Transform FindChild(string path)
|
||||
{
|
||||
return UnityExtension.FindChild(rectTransform, path);
|
||||
}
|
||||
|
||||
public Transform FindChild(Transform trans, string path)
|
||||
{
|
||||
return UnityExtension.FindChild(trans, path);
|
||||
}
|
||||
|
||||
public T FindChildComponent<T>(string path) where T : Component
|
||||
{
|
||||
return rectTransform.FindChildComponent<T>(path);
|
||||
}
|
||||
|
||||
public T FindChildComponent<T>(Transform trans, string path) where T : Component
|
||||
{
|
||||
return trans.FindChildComponent<T>(path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UIEvent
|
||||
|
||||
private GameEventMgr _eventMgr;
|
||||
|
||||
protected GameEventMgr EventMgr
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_eventMgr == null)
|
||||
{
|
||||
_eventMgr = MemoryPool.Acquire<GameEventMgr>();
|
||||
}
|
||||
|
||||
return _eventMgr;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddUIEvent(int eventType, Action handler)
|
||||
{
|
||||
EventMgr.AddUIEvent(eventType, handler);
|
||||
}
|
||||
|
||||
protected void AddUIEvent<T>(int eventType, Action<T> handler)
|
||||
{
|
||||
EventMgr.AddUIEvent(eventType, handler);
|
||||
}
|
||||
|
||||
protected void AddUIEvent<T, U>(int eventType, Action<T, U> handler)
|
||||
{
|
||||
EventMgr.AddUIEvent(eventType, handler);
|
||||
}
|
||||
|
||||
protected void AddUIEvent<T, U, V>(int eventType, Action<T, U, V> handler)
|
||||
{
|
||||
EventMgr.AddUIEvent(eventType, handler);
|
||||
}
|
||||
|
||||
protected void AddUIEvent<T, U, V, W>(int eventType, Action<T, U, V, W> handler)
|
||||
{
|
||||
EventMgr.AddUIEvent(eventType, handler);
|
||||
}
|
||||
|
||||
protected void RemoveAllUIEvent()
|
||||
{
|
||||
if (_eventMgr != null)
|
||||
{
|
||||
MemoryPool.Release(_eventMgr);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UIWidget
|
||||
|
||||
/// <summary>
|
||||
/// 创建UIWidget通过父UI位置节点。
|
||||
/// <remarks>因为资源示例已经存在父物体所以不需要异步。</remarks>
|
||||
/// </summary>
|
||||
/// <param name="goPath">父UI位置节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidget<T>(string goPath, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
var goRootTrans = FindChild(goPath);
|
||||
|
||||
if (goRootTrans != null)
|
||||
{
|
||||
return CreateWidget<T>(goRootTrans.gameObject, visible);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建UIWidget通过父UI位置节点。
|
||||
/// <remarks>因为资源示例已经存在父物体所以不需要异步。</remarks>
|
||||
/// </summary>
|
||||
/// <param name="parentTrans"></param>
|
||||
/// <param name="goPath">父UI位置节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidget<T>(Transform parentTrans, string goPath, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
var goRootTrans = FindChild(parentTrans, goPath);
|
||||
if (goRootTrans != null)
|
||||
{
|
||||
return CreateWidget<T>(goRootTrans.gameObject, visible);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建UIWidget通过游戏物体。
|
||||
/// <remarks>因为资源示例已经存在父物体所以不需要异步。</remarks>
|
||||
/// </summary>
|
||||
/// <param name="goRoot">游戏物体。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidget<T>(GameObject goRoot, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
var widget = new T();
|
||||
if (widget.Create(this, goRoot, visible))
|
||||
{
|
||||
return widget;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建UIWidget通过资源定位地址。
|
||||
/// </summary>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="assetLocation">资源定位地址。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidgetByPath<T>(Transform parentTrans, string assetLocation, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"CreateWidgetByPath Failed => {this}.AssetReference is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
GameObject goInst = AssetReference.LoadAsset<GameObject>(assetLocation, parentTrans);
|
||||
return CreateWidget<T>(goInst, visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建UIWidget通过资源定位地址。
|
||||
/// </summary>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="assetLocation">资源定位地址。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public async UniTask<T> CreateWidgetByPathAsync<T>(Transform parentTrans, string assetLocation, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"CreateWidgetByPath Failed => {this}.AssetReference is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
GameObject goInst = await AssetReference.LoadAssetAsync<GameObject>(assetLocation, gameObject.GetCancellationTokenOnDestroy());
|
||||
goInst.transform.SetParent(parentTrans);
|
||||
return CreateWidget<T>(goInst, visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据prefab或者模版来创建新的 widget。
|
||||
/// </summary>
|
||||
/// <param name="goPrefab">资源创建副本。</param>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidgetByPrefab<T>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过UI类型来创建widget。
|
||||
/// </summary>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public T CreateWidgetByType<T>(Transform parentTrans, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
return CreateWidgetByPath<T>(parentTrans, typeof(T).Name, visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过UI类型来创建widget。
|
||||
/// </summary>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <typeparam name="T">UIWidget。</typeparam>
|
||||
/// <returns>UIWidget实例。</returns>
|
||||
public async UniTask<T> CreateWidgetByTypeAsync<T>(Transform parentTrans, bool visible = true) where T : UIWidget, new()
|
||||
{
|
||||
return await CreateWidgetByPathAsync<T>(parentTrans, typeof(T).Name, visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调整图标数量。
|
||||
/// </summary>
|
||||
/// <remarks>常用于Icon创建。</remarks>
|
||||
/// <param name="listIcon">存放Icon的列表。</param>
|
||||
/// <param name="number">创建数目。</param>
|
||||
/// <param name="parentTrans">资源父节点。</param>
|
||||
/// <param name="prefab">资产副本。</param>
|
||||
/// <param name="assetPath">资产地址。</param>
|
||||
/// <typeparam name="T">图标类型。</typeparam>
|
||||
public void AdjustIconNum<T>(List<T> listIcon, int number, Transform parentTrans, GameObject prefab = null, string assetPath = "")
|
||||
where T : UIWidget, new()
|
||||
{
|
||||
if (listIcon == null)
|
||||
{
|
||||
listIcon = new List<T>();
|
||||
}
|
||||
|
||||
if (listIcon.Count < number)
|
||||
{
|
||||
int needNum = number - listIcon.Count;
|
||||
for (int iconIdx = 0; iconIdx < needNum; iconIdx++)
|
||||
{
|
||||
T tmpT = prefab == null ? CreateWidgetByType<T>(parentTrans) : CreateWidgetByPrefab<T>(prefab, parentTrans);
|
||||
listIcon.Add(tmpT);
|
||||
}
|
||||
}
|
||||
else if (listIcon.Count > number)
|
||||
{
|
||||
RemoveUnUseItem<T>(listIcon, number);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步调整图标数量。
|
||||
/// </summary>
|
||||
/// <param name="listIcon"></param>
|
||||
/// <param name="tarNum"></param>
|
||||
/// <param name="parentTrans"></param>
|
||||
/// <param name="prefab"></param>
|
||||
/// <param name="assetPath"></param>
|
||||
/// <param name="maxNumPerFrame"></param>
|
||||
/// <param name="updateAction"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public void AsyncAdjustIconNum<T>(List<T> listIcon, int tarNum, Transform parentTrans, GameObject prefab = null,
|
||||
string assetPath = "", int maxNumPerFrame = 5,
|
||||
Action<T, int> updateAction = null) where T : UIWidget, new()
|
||||
{
|
||||
AsyncAdjustIconNumInternal(listIcon, tarNum, parentTrans, maxNumPerFrame, updateAction, prefab, assetPath).Forget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步创建接口。
|
||||
/// </summary>
|
||||
/// <param name="listIcon"></param>
|
||||
/// <param name="tarNum"></param>
|
||||
/// <param name="parentTrans"></param>
|
||||
/// <param name="maxNumPerFrame"></param>
|
||||
/// <param name="updateAction"></param>
|
||||
/// <param name="prefab"></param>
|
||||
/// <param name="assetPath"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
private async UniTaskVoid AsyncAdjustIconNumInternal<T>(List<T> listIcon, int tarNum, Transform parentTrans, int maxNumPerFrame,
|
||||
Action<T, int> updateAction, GameObject prefab, string assetPath) where T : UIWidget, new()
|
||||
{
|
||||
if (listIcon == null)
|
||||
{
|
||||
listIcon = new List<T>();
|
||||
}
|
||||
|
||||
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<T>(parentTrans, assetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpT = CreateWidgetByPrefab<T>(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<T>(List<T> listIcon, int tarNum) where T : UIWidget
|
||||
{
|
||||
var removeIcon = new List<T>();
|
||||
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
|
||||
|
||||
#region AssetRefrence Methods
|
||||
|
||||
/// <summary>
|
||||
/// 引用资源数据到资源组内。
|
||||
/// </summary>
|
||||
/// <param name="handle">资源操作句柄。</param>
|
||||
/// <param name="assetTag">资源标识。</param>
|
||||
/// <returns>是否注册成功。</returns>
|
||||
public bool Reference(AssetOperationHandle handle, string assetTag = "")
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"Reference Failed => {this}.AssetReference is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return AssetReference.Reference(handle, assetTag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 引用资源数据到资源组内。
|
||||
/// </summary>
|
||||
/// <param name="address">资源定位地址。</param>
|
||||
/// <param name="handle">资源操作句柄。</param>
|
||||
/// <param name="assetTag">资源标识。</param>
|
||||
/// <returns>是否注册成功。</returns>
|
||||
public bool Reference(string address, AssetOperationHandle handle, string assetTag = "")
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"Reference Failed => {this}.AssetReference is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return AssetReference.Reference(address, handle, assetTag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从资源组内释放资源数据。
|
||||
/// </summary>
|
||||
/// <param name="assetTag"></param>
|
||||
/// <returns></returns>
|
||||
public bool ReleaseByTag(string assetTag)
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"Release Failed => {this}.AssetReference is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return AssetReference.ReleaseByTag(assetTag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从资源组内释放资源数据。
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <returns></returns>
|
||||
public bool Release(AssetOperationHandle handle)
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"Release Failed => {this}.AssetReference is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return AssetReference.Release(handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从资源组内释放资源数据。
|
||||
/// </summary>
|
||||
/// <param name="address">资源定位地址。</param>
|
||||
/// <returns>是否释放成功。</returns>
|
||||
public bool Release(string address)
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"Release Failed => {this}.AssetReference is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return AssetReference.Release(address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
public T LoadAsset<T>(string assetName) where T : UnityEngine.Object
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"LoadAsset Failed => {this}.AssetReference is null");
|
||||
return default;
|
||||
}
|
||||
|
||||
return AssetReference.LoadAsset<T>(assetName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <param name="parentTrans">父节点位置。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
public T LoadAsset<T>(string assetName, Transform parentTrans) where T : UnityEngine.Object
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"LoadAsset Failed => {this}.AssetReference is null");
|
||||
return default;
|
||||
}
|
||||
|
||||
return AssetReference.LoadAsset<T>(assetName, parentTrans);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载资源实例。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载的实例名称。</param>
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <returns>资源实实例。</returns>
|
||||
public async UniTask<T> LoadAssetAsync<T>(string assetName, CancellationToken cancellationToken)
|
||||
where T : UnityEngine.Object
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"LoadAssetAsync Failed => {this}.AssetReference is null");
|
||||
return default;
|
||||
}
|
||||
|
||||
return await AssetReference.LoadAssetAsync<T>(assetName, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载游戏物体。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载的游戏物体名称。</param>
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <returns>异步游戏物体实例。</returns>
|
||||
public async UniTask<GameObject> LoadGameObjectAsync(string assetName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (AssetReference == null)
|
||||
{
|
||||
Log.Fatal($"LoadAssetAsync Failed => {this}.AssetReference is null");
|
||||
return default;
|
||||
}
|
||||
|
||||
return await AssetReference.LoadGameObjectAsync(assetName, cancellationToken);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UIElement
|
||||
|
||||
/// <summary>
|
||||
/// UI元素节点。
|
||||
/// </summary>
|
||||
protected UIElement UIElement;
|
||||
|
||||
/// <summary>
|
||||
/// 检测UI元素节点。
|
||||
/// </summary>
|
||||
protected virtual void CheckUIElement()
|
||||
{
|
||||
if (rectTransform != null)
|
||||
{
|
||||
UIElement = rectTransform.GetComponent<UIElement>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取子节点。
|
||||
/// </summary>
|
||||
/// <param name="childName">子节点名称。</param>
|
||||
/// <returns>子节点位置实例。</returns>
|
||||
protected Transform FChild(string childName)
|
||||
{
|
||||
if (UIElement != null)
|
||||
{
|
||||
var child = UIElement.Get(childName);
|
||||
if (child != null)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return FindChild(childName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取子节点脚本。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">子节点类型。</typeparam>
|
||||
/// <param name="childName">子节点名称。</param>
|
||||
/// <returns>子节点脚本实例。</returns>
|
||||
protected T FChild<T>(string childName) where T : Component
|
||||
{
|
||||
var child = FChild(childName);
|
||||
return child == null ? null : child.GetComponent<T>();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa3dc52076b14039bc355c825c7f29de
|
||||
timeCreated: 1680526167
|
@@ -0,0 +1,50 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UI元素节点。
|
||||
/// <remarks>通过mono序列化来绑定ui节点的元素换取查找与ui的稳定性。</remarks>
|
||||
/// </summary>
|
||||
public class UIElement : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// UI元素。
|
||||
/// </summary>
|
||||
[SerializeField] protected SerializableDictionary<string, Transform> elements = new SerializableDictionary<string, Transform>();
|
||||
|
||||
/// <summary>
|
||||
/// UI元素。
|
||||
/// </summary>
|
||||
public SerializableDictionary<string, Transform> Elements => elements;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UI元素。
|
||||
/// </summary>
|
||||
/// <param name="uiID">ui元素标识。</param>
|
||||
/// <returns>UI元素。</returns>
|
||||
public Transform Get(string uiID)
|
||||
{
|
||||
elements.TryGetValue(uiID, out var uiTransform);
|
||||
return uiTransform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取UI元素。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">ui元素类型。</typeparam>
|
||||
/// <param name="uiID">ui元素标识。</param>
|
||||
/// <returns>ui元素标识。</returns>
|
||||
public T Get<T>(string uiID) where T : Component
|
||||
{
|
||||
var uiTransform = Get(uiID);
|
||||
return uiTransform == null ? null : uiTransform.GetComponent<T>();
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
elements.Clear();
|
||||
elements = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcd11033283847ee8f7c71eedd9a4771
|
||||
timeCreated: 1696656961
|
514
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIModule.cs
Normal file
514
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIModule.cs
Normal file
@@ -0,0 +1,514 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UI模块。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public sealed partial class UIModule : Module
|
||||
{
|
||||
[SerializeField] private Transform m_InstanceRoot = null;
|
||||
|
||||
[SerializeField] private bool m_dontDestroyUIRoot = true;
|
||||
|
||||
[SerializeField] private bool m_enableErrorLog = true;
|
||||
|
||||
[SerializeField] private Camera m_UICamera = null;
|
||||
|
||||
private readonly List<UIWindow> _stack = new List<UIWindow>(100);
|
||||
|
||||
public const int LAYER_DEEP = 2000;
|
||||
public const int WINDOW_DEEP = 100;
|
||||
public const int WINDOW_HIDE_LAYER = 2; // Ignore Raycast
|
||||
public const int WINDOW_SHOW_LAYER = 5; // UI
|
||||
|
||||
/// <summary>
|
||||
/// UI根节点。
|
||||
/// </summary>
|
||||
public Transform UIRoot => m_InstanceRoot;
|
||||
|
||||
public static Transform UIRootStatic;
|
||||
|
||||
/// <summary>
|
||||
/// UI根节点。
|
||||
/// </summary>
|
||||
public Camera UICamera => m_UICamera;
|
||||
|
||||
private UIModuleImpl _uiModuleImpl;
|
||||
|
||||
private ErrorLogger _errorLogger;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RootModule rootModule = ModuleSystem.GetModule<RootModule>();
|
||||
if (rootModule == null)
|
||||
{
|
||||
Log.Fatal("Base component is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_uiModuleImpl = ModuleImpSystem.GetModule<UIModuleImpl>();
|
||||
_uiModuleImpl.Initialize(_stack);
|
||||
|
||||
if (m_InstanceRoot == null)
|
||||
{
|
||||
m_InstanceRoot = new GameObject("UI Form Instances").transform;
|
||||
m_InstanceRoot.SetParent(gameObject.transform);
|
||||
m_InstanceRoot.localScale = Vector3.one;
|
||||
}
|
||||
else if (m_dontDestroyUIRoot)
|
||||
{
|
||||
DontDestroyOnLoad(m_InstanceRoot.parent != null ? m_InstanceRoot.parent : m_InstanceRoot);
|
||||
}
|
||||
|
||||
m_InstanceRoot.gameObject.layer = LayerMask.NameToLayer("UI");
|
||||
UIRootStatic = m_InstanceRoot;
|
||||
if (m_enableErrorLog)
|
||||
{
|
||||
_errorLogger = new ErrorLogger();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CloseAll();
|
||||
}
|
||||
|
||||
#region 设置安全区域
|
||||
|
||||
/// <summary>
|
||||
/// 设置屏幕安全区域(异形屏支持)。
|
||||
/// </summary>
|
||||
/// <param name="safeRect">安全区域</param>
|
||||
public static void ApplyScreenSafeRect(Rect safeRect)
|
||||
{
|
||||
CanvasScaler scaler = UIRootStatic.GetComponentInParent<CanvasScaler>();
|
||||
if (scaler == null)
|
||||
{
|
||||
Log.Error($"Not found {nameof(CanvasScaler)} !");
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert safe area rectangle from absolute pixels to UGUI coordinates
|
||||
float rateX = scaler.referenceResolution.x / Screen.width;
|
||||
float rateY = scaler.referenceResolution.y / Screen.height;
|
||||
float posX = (int)(safeRect.position.x * rateX);
|
||||
float posY = (int)(safeRect.position.y * rateY);
|
||||
float width = (int)(safeRect.size.x * rateX);
|
||||
float height = (int)(safeRect.size.y * rateY);
|
||||
|
||||
float offsetMaxX = scaler.referenceResolution.x - width - posX;
|
||||
float offsetMaxY = scaler.referenceResolution.y - height - posY;
|
||||
|
||||
// 注意:安全区坐标系的原点为左下角
|
||||
var rectTrans = UIRootStatic.transform as RectTransform;
|
||||
if (rectTrans != null)
|
||||
{
|
||||
rectTrans.offsetMin = new Vector2(posX, posY); //锚框状态下的屏幕左下角偏移向量
|
||||
rectTrans.offsetMax = new Vector2(-offsetMaxX, -offsetMaxY); //锚框状态下的屏幕右上角偏移向量
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟IPhoneX异形屏
|
||||
/// </summary>
|
||||
public static void SimulateIPhoneXNotchScreen()
|
||||
{
|
||||
Rect rect;
|
||||
if (Screen.height > Screen.width)
|
||||
{
|
||||
// 竖屏Portrait
|
||||
float deviceWidth = 1125;
|
||||
float deviceHeight = 2436;
|
||||
rect = new Rect(0f / deviceWidth, 102f / deviceHeight, 1125f / deviceWidth, 2202f / deviceHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 横屏Landscape
|
||||
float deviceWidth = 2436;
|
||||
float deviceHeight = 1125;
|
||||
rect = new Rect(132f / deviceWidth, 63f / deviceHeight, 2172f / deviceWidth, 1062f / deviceHeight);
|
||||
}
|
||||
|
||||
Rect safeArea = new Rect(Screen.width * rect.x, Screen.height * rect.y, Screen.width * rect.width, Screen.height * rect.height);
|
||||
ApplyScreenSafeRect(safeArea);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有层级下顶部的窗口名称。
|
||||
/// </summary>
|
||||
public string GetTopWindow()
|
||||
{
|
||||
if (_stack.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
UIWindow topWindow = _stack[^1];
|
||||
return topWindow.WindowName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定层级下顶部的窗口名称。
|
||||
/// </summary>
|
||||
public string GetTopWindow(int layer)
|
||||
{
|
||||
UIWindow lastOne = null;
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
if (_stack[i].WindowLayer == layer)
|
||||
lastOne = _stack[i];
|
||||
}
|
||||
|
||||
if (lastOne == null)
|
||||
return string.Empty;
|
||||
|
||||
return lastOne.WindowName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有任意窗口正在加载。
|
||||
/// </summary>
|
||||
public bool IsAnyLoading()
|
||||
{
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
var window = _stack[i];
|
||||
if (window.IsLoadDone == false)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询窗口是否存在。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">界面类型。</typeparam>
|
||||
/// <returns>是否存在。</returns>
|
||||
public bool HasWindow<T>()
|
||||
{
|
||||
return HasWindow(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询窗口是否存在。
|
||||
/// </summary>
|
||||
/// <param name="type">界面类型。</param>
|
||||
/// <returns>是否存在。</returns>
|
||||
public bool HasWindow(Type type)
|
||||
{
|
||||
return IsContains(type.FullName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步打开窗口。
|
||||
/// </summary>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
/// <returns>打开窗口操作句柄。</returns>
|
||||
public OpenWindowOperation ShowUIAsync<T>(params System.Object[] userDatas) where T : UIWindow
|
||||
{
|
||||
return ShowUIAsync(typeof(T), userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步打开窗口。
|
||||
/// </summary>
|
||||
/// <param name="type">界面类型。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
/// <returns>打开窗口操作句柄。</returns>
|
||||
public OpenWindowOperation ShowUIAsync(Type type, params System.Object[] userDatas)
|
||||
{
|
||||
string windowName = type.FullName;
|
||||
|
||||
// 如果窗口已经存在
|
||||
if (IsContains(windowName))
|
||||
{
|
||||
UIWindow window = GetWindow(windowName);
|
||||
Pop(window); //弹出窗口
|
||||
Push(window); //重新压入
|
||||
window.TryInvoke(OnWindowPrepare, userDatas);
|
||||
var operation = new OpenWindowOperation(window);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
UIWindow window = CreateInstance(type);
|
||||
Push(window); //首次压入
|
||||
window.InternalLoad(window.AssetName, OnWindowPrepare, userDatas);
|
||||
var operation = new OpenWindowOperation(window);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步打开窗口。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">窗口类。</typeparam>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
/// <returns>打开窗口操作句柄。</returns>
|
||||
public OpenWindowOperation ShowUI<T>(params System.Object[] userDatas) where T : UIWindow
|
||||
{
|
||||
var operation = ShowUIAsync(typeof(T), userDatas);
|
||||
operation.WaitForAsyncComplete();
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步打开窗口。
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="userDatas"></param>
|
||||
/// <returns>打开窗口操作句柄。</returns>
|
||||
public OpenWindowOperation ShowUI(Type type, params System.Object[] userDatas)
|
||||
{
|
||||
var operation = ShowUIAsync(type, userDatas);
|
||||
operation.WaitForAsyncComplete();
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭窗口
|
||||
/// </summary>
|
||||
public void CloseWindow<T>() where T : UIWindow
|
||||
{
|
||||
CloseWindow(typeof(T));
|
||||
}
|
||||
|
||||
public void CloseWindow(Type type)
|
||||
{
|
||||
string windowName = type.FullName;
|
||||
UIWindow window = GetWindow(windowName);
|
||||
if (window == null)
|
||||
return;
|
||||
|
||||
window.InternalDestroy();
|
||||
Pop(window);
|
||||
OnSortWindowDepth(window.WindowLayer);
|
||||
OnSetWindowVisible();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭所有窗口。
|
||||
/// </summary>
|
||||
public void CloseAll()
|
||||
{
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
window.InternalDestroy();
|
||||
}
|
||||
|
||||
_stack.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭所有窗口除了。
|
||||
/// </summary>
|
||||
public void CloseAllWithOut(UIWindow withOut)
|
||||
{
|
||||
for (int i = _stack.Count - 1; i >= 0; i--)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
if (window == withOut)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
window.InternalDestroy();
|
||||
_stack.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭所有窗口除了。
|
||||
/// </summary>
|
||||
public void CloseAllWithOut<T>() where T : UIWindow
|
||||
{
|
||||
for (int i = _stack.Count - 1; i >= 0; i--)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
if (window.GetType() == typeof(T))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
window.InternalDestroy();
|
||||
_stack.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWindowPrepare(UIWindow window)
|
||||
{
|
||||
OnSortWindowDepth(window.WindowLayer);
|
||||
window.InternalCreate();
|
||||
window.InternalRefresh();
|
||||
OnSetWindowVisible();
|
||||
}
|
||||
|
||||
private void OnSortWindowDepth(int layer)
|
||||
{
|
||||
int depth = layer * LAYER_DEEP;
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
if (_stack[i].WindowLayer == layer)
|
||||
{
|
||||
_stack[i].Depth = depth;
|
||||
depth += WINDOW_DEEP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSetWindowVisible()
|
||||
{
|
||||
bool isHideNext = false;
|
||||
for (int i = _stack.Count - 1; i >= 0; i--)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
if (isHideNext == false)
|
||||
{
|
||||
window.Visible = true;
|
||||
if (window.IsPrepare && window.FullScreen)
|
||||
{
|
||||
isHideNext = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
window.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UIWindow CreateInstance(Type type)
|
||||
{
|
||||
UIWindow window = Activator.CreateInstance(type) as UIWindow;
|
||||
WindowAttribute attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
|
||||
|
||||
if (window == null)
|
||||
throw new Exception($"Window {type.FullName} create instance failed.");
|
||||
if (attribute == null)
|
||||
throw new Exception($"Window {type.FullName} not found {nameof(WindowAttribute)} attribute.");
|
||||
|
||||
string assetName = string.IsNullOrEmpty(attribute.Location) ? type.Name : attribute.Location;
|
||||
window.Init(type.FullName, attribute.WindowLayer, attribute.FullScreen, assetName, attribute.FromResources);
|
||||
return window;
|
||||
}
|
||||
|
||||
private UIWindow GetWindow(string windowName)
|
||||
{
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
if (window.WindowName == windowName)
|
||||
{
|
||||
return window;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsContains(string windowName)
|
||||
{
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
UIWindow window = _stack[i];
|
||||
if (window.WindowName == windowName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Push(UIWindow window)
|
||||
{
|
||||
// 如果已经存在
|
||||
if (IsContains(window.WindowName))
|
||||
throw new System.Exception($"Window {window.WindowName} is exist.");
|
||||
|
||||
// 获取插入到所属层级的位置
|
||||
int insertIndex = -1;
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
if (window.WindowLayer == _stack[i].WindowLayer)
|
||||
{
|
||||
insertIndex = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有所属层级,找到相邻层级
|
||||
if (insertIndex == -1)
|
||||
{
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
if (window.WindowLayer > _stack[i].WindowLayer)
|
||||
{
|
||||
insertIndex = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是空栈或没有找到插入位置
|
||||
if (insertIndex == -1)
|
||||
{
|
||||
insertIndex = 0;
|
||||
}
|
||||
|
||||
// 最后插入到堆栈
|
||||
_stack.Insert(insertIndex, window);
|
||||
}
|
||||
|
||||
private void Pop(UIWindow window)
|
||||
{
|
||||
// 从堆栈里移除
|
||||
_stack.Remove(window);
|
||||
}
|
||||
}
|
||||
|
||||
[UpdateModule]
|
||||
internal sealed partial class UIModuleImpl : ModuleImp
|
||||
{
|
||||
private List<UIWindow> _stack;
|
||||
|
||||
internal void Initialize(List<UIWindow> stack)
|
||||
{
|
||||
_stack = stack;
|
||||
}
|
||||
|
||||
internal override void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Update(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
if (_stack == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int count = _stack.Count;
|
||||
for (int i = 0; i < _stack.Count; i++)
|
||||
{
|
||||
if (_stack.Count != count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var window = _stack[i];
|
||||
window.InternalUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9497504d71104685ad1464b42219c763
|
||||
timeCreated: 1680511581
|
301
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIWidget.cs
Normal file
301
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIWidget.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public abstract class UIWidget : UIBase, IUIBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 窗口组件的实例资源对象。
|
||||
/// </summary>
|
||||
public override GameObject gameObject { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口组件矩阵位置组件。
|
||||
/// </summary>
|
||||
public override RectTransform rectTransform { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口位置组件。
|
||||
/// </summary>
|
||||
public override Transform transform { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口组件名称。
|
||||
/// </summary>
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string name { private set; get; } = nameof(UIWidget);
|
||||
|
||||
/// <summary>
|
||||
/// UI类型。
|
||||
/// </summary>
|
||||
public override UIBaseType BaseType => UIBaseType.Widget;
|
||||
|
||||
/// <summary>
|
||||
/// 所属的窗口。
|
||||
/// </summary>
|
||||
public UIWindow OwnerWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
var parentUI = base.parent;
|
||||
while (parentUI != null)
|
||||
{
|
||||
if (parentUI.BaseType == UIBaseType.Window)
|
||||
{
|
||||
return parentUI as UIWindow;
|
||||
}
|
||||
|
||||
parentUI = parentUI.Parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool InternalUpdate()
|
||||
{
|
||||
if (!IsPrepare)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<UIWidget> listNextUpdateChild = null;
|
||||
if (ListChild != null && ListChild.Count > 0)
|
||||
{
|
||||
listNextUpdateChild = m_listUpdateChild;
|
||||
var updateListValid = m_updateListValid;
|
||||
List<UIWidget> listChild = null;
|
||||
if (!updateListValid)
|
||||
{
|
||||
if (listNextUpdateChild == null)
|
||||
{
|
||||
listNextUpdateChild = new List<UIWidget>();
|
||||
m_listUpdateChild = listNextUpdateChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
listNextUpdateChild.Clear();
|
||||
}
|
||||
|
||||
listChild = ListChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
listChild = listNextUpdateChild;
|
||||
}
|
||||
|
||||
for (int i = 0; i < listChild.Count; i++)
|
||||
{
|
||||
var uiWidget = listChild[i];
|
||||
|
||||
TProfiler.BeginSample(uiWidget.name);
|
||||
var needValid = uiWidget.InternalUpdate();
|
||||
TProfiler.EndSample();
|
||||
|
||||
if (!updateListValid && needValid)
|
||||
{
|
||||
listNextUpdateChild.Add(uiWidget);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateListValid)
|
||||
{
|
||||
m_updateListValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
TProfiler.BeginSample("OnUpdate");
|
||||
|
||||
bool needUpdate = false;
|
||||
if (listNextUpdateChild == null || listNextUpdateChild.Count <= 0)
|
||||
{
|
||||
HasOverrideUpdate = true;
|
||||
OnUpdate();
|
||||
needUpdate = HasOverrideUpdate;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnUpdate();
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
TProfiler.EndSample();
|
||||
|
||||
return needUpdate;
|
||||
}
|
||||
|
||||
#region Create
|
||||
|
||||
/// <summary>
|
||||
/// 创建窗口内嵌的界面。
|
||||
/// </summary>
|
||||
/// <param name="parentUI">父节点UI。</param>
|
||||
/// <param name="widgetRoot">组件根节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <returns></returns>
|
||||
public bool Create(UIBase parentUI, GameObject widgetRoot, bool visible = true)
|
||||
{
|
||||
return CreateImp(parentUI, widgetRoot, false, visible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据资源名创建
|
||||
/// </summary>
|
||||
/// <param name="resPath"></param>
|
||||
/// <param name="parentUI"></param>
|
||||
/// <param name="parentTrans"></param>
|
||||
/// <param name="visible"></param>
|
||||
/// <returns></returns>
|
||||
public bool CreateByPath(string resPath, UIBase parentUI, Transform parentTrans = null, bool visible = true)
|
||||
{
|
||||
GameObject goInst = parentUI.AssetReference.LoadAsset<GameObject>(resPath, parentTrans);
|
||||
if (goInst == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Create(parentUI, goInst, visible))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
goInst.transform.localScale = Vector3.one;
|
||||
goInst.transform.localPosition = Vector3.zero;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据prefab或者模版来创建新的 widget。
|
||||
/// <remarks>存在父物体得资源故不需要异步加载。</remarks>
|
||||
/// </summary>
|
||||
/// <param name="parentUI">父物体UI。</param>
|
||||
/// <param name="goPrefab">实例化预制体。</param>
|
||||
/// <param name="parentTrans">实例化父节点。</param>
|
||||
/// <param name="visible">是否可见。</param>
|
||||
/// <returns>是否创建成功。</returns>
|
||||
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)
|
||||
{
|
||||
if (!CreateBase(widgetRoot, bindGo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AssetReference == null)
|
||||
{
|
||||
AssetReference = AssetReference.BindAssetReference(widgetRoot, parent: parentUI.AssetReference);
|
||||
}
|
||||
|
||||
RestChildCanvas(parentUI);
|
||||
parent = parentUI;
|
||||
Parent.ListChild.Add(this);
|
||||
ScriptGenerator();
|
||||
BindMemberProperty();
|
||||
RegisterEvent();
|
||||
OnCreate();
|
||||
IsPrepare = true;
|
||||
|
||||
if (!visible)
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool CreateBase(GameObject go, bool bindGo)
|
||||
{
|
||||
if (go == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
transform = go.GetComponent<Transform>();
|
||||
rectTransform = transform as RectTransform;
|
||||
gameObject = go;
|
||||
Log.Assert(rectTransform != null, $"{go.name} ui base element need to be RectTransform");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void RestChildCanvas(UIBase parentUI)
|
||||
{
|
||||
if (parentUI == null || parentUI.gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Canvas parentCanvas = parentUI.gameObject.GetComponentInParent<Canvas>();
|
||||
if (parentCanvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameObject != null)
|
||||
{
|
||||
var listCanvas = gameObject.GetComponentsInChildren<Canvas>(true);
|
||||
for (var index = 0; index < listCanvas.Length; index++)
|
||||
{
|
||||
var childCanvas = listCanvas[index];
|
||||
childCanvas.sortingOrder = parentCanvas.sortingOrder + childCanvas.sortingOrder % UIModule.WINDOW_DEEP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
|
||||
/// <summary>
|
||||
/// 组件被销毁调用。
|
||||
/// <remarks>请勿手动调用!</remarks>
|
||||
/// </summary>
|
||||
internal void OnDestroyWidget()
|
||||
{
|
||||
RemoveAllUIEvent();
|
||||
|
||||
foreach (var uiChild in ListChild)
|
||||
{
|
||||
uiChild.OnDestroy();
|
||||
uiChild.OnDestroyWidget();
|
||||
}
|
||||
|
||||
if (Handle != null)
|
||||
{
|
||||
if (AssetReference != null && AssetReference.Parent != null)
|
||||
{
|
||||
AssetReference.Parent.Release(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (gameObject != null)
|
||||
{
|
||||
Object.Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主动销毁组件。
|
||||
/// </summary>
|
||||
public void Destroy()
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
parent.ListChild.Remove(this);
|
||||
OnDestroy();
|
||||
OnDestroyWidget();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 497ec3b265be4f81aead015ca3aa91d7
|
||||
timeCreated: 1680526019
|
449
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIWindow.cs
Normal file
449
UnityProject/Assets/TEngine/Runtime/Modules/UIModule/UIWindow.cs
Normal file
@@ -0,0 +1,449 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using YooAsset;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public abstract class UIWindow : UIBase
|
||||
{
|
||||
#region Propreties
|
||||
|
||||
private System.Action<UIWindow> _prepareCallback;
|
||||
|
||||
private bool _isCreate = false;
|
||||
|
||||
private GameObject _panel;
|
||||
|
||||
private Canvas _canvas;
|
||||
|
||||
private Canvas[] _childCanvas;
|
||||
|
||||
private GraphicRaycaster _raycaster;
|
||||
|
||||
private GraphicRaycaster[] _childRaycaster;
|
||||
|
||||
public override UIBaseType BaseType => UIBaseType.Window;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口位置组件。
|
||||
/// </summary>
|
||||
public override Transform transform => _panel.transform;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口矩阵位置组件。
|
||||
/// </summary>
|
||||
public override RectTransform rectTransform => _panel.transform as RectTransform;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口的实例资源对象。
|
||||
/// </summary>
|
||||
public override GameObject gameObject => _panel;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口名称。
|
||||
/// </summary>
|
||||
public string WindowName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 窗口层级。
|
||||
/// </summary>
|
||||
public int WindowLayer { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址。
|
||||
/// </summary>
|
||||
public string AssetName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为全屏窗口
|
||||
/// </summary>
|
||||
public bool FullScreen { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是内部资源无需AB加载。
|
||||
/// </summary>
|
||||
public bool FromResources { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义数据。
|
||||
/// </summary>
|
||||
public System.Object UserData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (userDatas != null && userDatas.Length >= 1)
|
||||
{
|
||||
return userDatas[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义数据集。
|
||||
/// </summary>
|
||||
public System.Object[] UserDatas => userDatas;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口深度值
|
||||
/// </summary>
|
||||
public int Depth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_canvas != null)
|
||||
{
|
||||
return _canvas.sortingOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_canvas != null)
|
||||
{
|
||||
if (_canvas.sortingOrder == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置父类
|
||||
_canvas.sortingOrder = value;
|
||||
|
||||
// 设置子类
|
||||
int depth = value;
|
||||
for (int i = 0; i < _childCanvas.Length; i++)
|
||||
{
|
||||
var canvas = _childCanvas[i];
|
||||
if (canvas != _canvas)
|
||||
{
|
||||
depth += 5; //注意递增值
|
||||
canvas.sortingOrder = depth;
|
||||
}
|
||||
}
|
||||
|
||||
// 虚函数
|
||||
if (_isCreate)
|
||||
{
|
||||
OnSortDepth(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口可见性
|
||||
/// </summary>
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_canvas != null)
|
||||
{
|
||||
return _canvas.gameObject.layer == UIModule.WINDOW_SHOW_LAYER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_canvas != null)
|
||||
{
|
||||
int setLayer = value ? UIModule.WINDOW_SHOW_LAYER : UIModule.WINDOW_HIDE_LAYER;
|
||||
if (_canvas.gameObject.layer == setLayer)
|
||||
return;
|
||||
|
||||
// 显示设置
|
||||
_canvas.gameObject.layer = setLayer;
|
||||
for (int i = 0; i < _childCanvas.Length; i++)
|
||||
{
|
||||
_childCanvas[i].gameObject.layer = setLayer;
|
||||
}
|
||||
|
||||
// 交互设置
|
||||
Interactable = value;
|
||||
|
||||
// 虚函数
|
||||
if (_isCreate)
|
||||
{
|
||||
OnSetVisible(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口交互性
|
||||
/// </summary>
|
||||
private bool Interactable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_raycaster != null)
|
||||
{
|
||||
return _raycaster.enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_raycaster != null)
|
||||
{
|
||||
_raycaster.enabled = value;
|
||||
for (int i = 0; i < _childRaycaster.Length; i++)
|
||||
{
|
||||
_childRaycaster[i].enabled = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否加载完毕。
|
||||
/// </summary>
|
||||
internal bool IsLoadDone => Handle.IsDone;
|
||||
|
||||
#endregion
|
||||
|
||||
public void Init(string name, int layer, bool fullScreen, string assetName, bool fromResources)
|
||||
{
|
||||
WindowName = name;
|
||||
WindowLayer = layer;
|
||||
FullScreen = fullScreen;
|
||||
AssetName = assetName;
|
||||
FromResources = fromResources;
|
||||
}
|
||||
|
||||
internal void TryInvoke(System.Action<UIWindow> prepareCallback, System.Object[] userDatas)
|
||||
{
|
||||
base.userDatas = userDatas;
|
||||
if (IsPrepare)
|
||||
{
|
||||
prepareCallback?.Invoke(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_prepareCallback = prepareCallback;
|
||||
}
|
||||
}
|
||||
|
||||
internal void InternalLoad(string location, System.Action<UIWindow> prepareCallback, System.Object[] userDatas)
|
||||
{
|
||||
if (Handle != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prepareCallback = prepareCallback;
|
||||
this.userDatas = userDatas;
|
||||
if (!FromResources)
|
||||
{
|
||||
Handle = YooAssets.LoadAssetAsync<GameObject>(location);
|
||||
Handle.Completed += Handle_Completed;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject panel = Object.Instantiate(Resources.Load<GameObject>(location), UIModule.UIRootStatic);
|
||||
Handle_Completed(panel);
|
||||
}
|
||||
}
|
||||
|
||||
internal void InternalCreate()
|
||||
{
|
||||
if (_isCreate == false)
|
||||
{
|
||||
_isCreate = true;
|
||||
ScriptGenerator();
|
||||
BindMemberProperty();
|
||||
RegisterEvent();
|
||||
OnCreate();
|
||||
}
|
||||
}
|
||||
|
||||
internal void InternalRefresh()
|
||||
{
|
||||
OnRefresh();
|
||||
}
|
||||
|
||||
internal bool InternalUpdate()
|
||||
{
|
||||
if (!IsPrepare || !Visible)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<UIWidget> listNextUpdateChild = null;
|
||||
if (ListChild != null && ListChild.Count > 0)
|
||||
{
|
||||
listNextUpdateChild = m_listUpdateChild;
|
||||
var updateListValid = m_updateListValid;
|
||||
List<UIWidget> listChild = null;
|
||||
if (!updateListValid)
|
||||
{
|
||||
if (listNextUpdateChild == null)
|
||||
{
|
||||
listNextUpdateChild = new List<UIWidget>();
|
||||
m_listUpdateChild = listNextUpdateChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
listNextUpdateChild.Clear();
|
||||
}
|
||||
|
||||
listChild = ListChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
listChild = listNextUpdateChild;
|
||||
}
|
||||
|
||||
for (int i = 0; i < listChild.Count; i++)
|
||||
{
|
||||
var uiWidget = listChild[i];
|
||||
|
||||
TProfiler.BeginSample(uiWidget.name);
|
||||
var needValid = uiWidget.InternalUpdate();
|
||||
TProfiler.EndSample();
|
||||
|
||||
if (!updateListValid && needValid)
|
||||
{
|
||||
listNextUpdateChild.Add(uiWidget);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateListValid)
|
||||
{
|
||||
m_updateListValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
TProfiler.BeginSample("OnUpdate");
|
||||
|
||||
bool needUpdate = false;
|
||||
if (listNextUpdateChild == null || listNextUpdateChild.Count <= 0)
|
||||
{
|
||||
HasOverrideUpdate = true;
|
||||
OnUpdate();
|
||||
needUpdate = HasOverrideUpdate;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnUpdate();
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
TProfiler.EndSample();
|
||||
|
||||
return needUpdate;
|
||||
}
|
||||
|
||||
internal void InternalDestroy()
|
||||
{
|
||||
_isCreate = false;
|
||||
|
||||
RemoveAllUIEvent();
|
||||
|
||||
for (int i = 0; i < ListChild.Count; i++)
|
||||
{
|
||||
var uiChild = ListChild[i];
|
||||
uiChild.OnDestroy();
|
||||
uiChild.OnDestroyWidget();
|
||||
}
|
||||
|
||||
// 注销回调函数
|
||||
_prepareCallback = null;
|
||||
|
||||
// 卸载面板资源
|
||||
if (Handle != null)
|
||||
{
|
||||
Handle.Release();
|
||||
Handle = null;
|
||||
}
|
||||
|
||||
OnDestroy();
|
||||
|
||||
// 销毁面板对象
|
||||
if (_panel != null)
|
||||
{
|
||||
Object.Destroy(_panel);
|
||||
_panel = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理资源加载完成回调。
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private void Handle_Completed(AssetOperationHandle handle)
|
||||
{
|
||||
if (handle.AssetObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 实例化对象
|
||||
var panel = handle.InstantiateSync(UIModule.UIRootStatic);
|
||||
Handle_Completed(panel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理资源加载完成回调。
|
||||
/// </summary>
|
||||
/// <param name="panel">面板资源实例。</param>
|
||||
private void Handle_Completed(GameObject panel)
|
||||
{
|
||||
if (panel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_panel = panel;
|
||||
_panel.transform.localPosition = Vector3.zero;
|
||||
|
||||
// 绑定引用
|
||||
AssetReference = AssetReference.BindAssetReference(_panel);
|
||||
|
||||
// 获取组件
|
||||
_canvas = _panel.GetComponent<Canvas>();
|
||||
if (_canvas == null)
|
||||
{
|
||||
throw new Exception($"Not found {nameof(Canvas)} in panel {WindowName}");
|
||||
}
|
||||
|
||||
_canvas.overrideSorting = true;
|
||||
_canvas.sortingOrder = 0;
|
||||
_canvas.sortingLayerName = "Default";
|
||||
|
||||
// 获取组件
|
||||
_raycaster = _panel.GetComponent<GraphicRaycaster>();
|
||||
_childCanvas = _panel.GetComponentsInChildren<Canvas>(true);
|
||||
_childRaycaster = _panel.GetComponentsInChildren<GraphicRaycaster>(true);
|
||||
|
||||
// 通知UI管理器
|
||||
IsPrepare = true;
|
||||
_prepareCallback?.Invoke(this);
|
||||
}
|
||||
|
||||
protected virtual void Close()
|
||||
{
|
||||
GameModule.UI.CloseWindow(this.GetType());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f7074455af14e94807e155b7cf32dd3
|
||||
timeCreated: 1680514258
|
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UI层级枚举。
|
||||
/// </summary>
|
||||
public enum UILayer : int
|
||||
{
|
||||
Bottom = 0,
|
||||
UI = 1,
|
||||
Top = 2,
|
||||
Tips = 3,
|
||||
System = 4,
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class WindowAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 窗口层级
|
||||
/// </summary>
|
||||
public readonly int WindowLayer;
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址。
|
||||
/// </summary>
|
||||
public readonly string Location;
|
||||
|
||||
/// <summary>
|
||||
/// 全屏窗口标记。
|
||||
/// </summary>
|
||||
public readonly bool FullScreen;
|
||||
|
||||
/// <summary>
|
||||
/// 是内部资源无需AB加载。
|
||||
/// </summary>
|
||||
public readonly bool FromResources;
|
||||
|
||||
public WindowAttribute(int windowLayer, string location = "", bool fullScreen = false)
|
||||
{
|
||||
WindowLayer = windowLayer;
|
||||
Location = location;
|
||||
FullScreen = fullScreen;
|
||||
}
|
||||
|
||||
public WindowAttribute(UILayer windowLayer, string location = "", bool fullScreen = false)
|
||||
{
|
||||
WindowLayer = (int)windowLayer;
|
||||
Location = location;
|
||||
FullScreen = fullScreen;
|
||||
}
|
||||
|
||||
public WindowAttribute(UILayer windowLayer, bool fromResources, bool fullScreen = false)
|
||||
{
|
||||
WindowLayer = (int)windowLayer;
|
||||
FromResources = fromResources;
|
||||
}
|
||||
|
||||
public WindowAttribute(UILayer windowLayer, bool fromResources, string location, bool fullScreen = false)
|
||||
{
|
||||
WindowLayer = (int)windowLayer;
|
||||
FromResources = fromResources;
|
||||
Location = location;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e40418539074f688c82a8ab107e968e
|
||||
timeCreated: 1680511434
|
Reference in New Issue
Block a user