继续重构调整(UI)

- 引入 UniTask 和异步版本的 UIModule
- 调整 Runtime/UIBase 和 Presentation 下的脚本命名空间到 SepCore.UI
- 将原来的 5 层 UI 迁移到异步实现
- 规范各层的 UI 脚本命名
This commit is contained in:
SepComet
2026-06-03 09:58:37 +08:00
parent 6b8a6a8789
commit 7bba8bbb80
552 changed files with 83648 additions and 2726 deletions
@@ -1,9 +1,13 @@
namespace UI
using Cysharp.Threading.Tasks;
namespace SepCore.UI
{
public interface IUIFormController
{
int? OpenUI(object userData = null);
void CloseUI();
UniTask<int?> OpenUIAsync(object userData = null, float timeout = 30f);
UniTask CloseUIAsync(object userData = null, float timeout = 30f);
void BindUseCase(IUIUseCase useCase);
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 08145adf06b2b2c4b9d61d3ef6d39cfc
guid: 66fa704224e65f54584adec043702f21
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,10 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UI
namespace SepCore.UI
{
public interface IUIUseCase
{
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8b527e4ad6d6207418137211caa179d5
guid: 277ebfa2eef59b448b093625c15ecaad
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,11 +1,4 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using StarForce;
using TMPro;
@@ -13,7 +6,7 @@ using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
namespace SepCore.UI
{
public abstract class UGuiForm : UIFormLogic
{
@@ -9,7 +9,7 @@ using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
namespace SepCore.UI
{
/// <summary>
/// uGUI 界面组辅助器。
@@ -1,10 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UI
namespace SepCore.UI
{
public class UIContext
{
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7ac4a8b30b5b7684ca58f70386314a4b
guid: aacfc86c69a60264b82af0d0b457eb96
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,112 @@
using Cysharp.Threading.Tasks;
using SepCore.Definition;
using UnityGameFramework.Runtime;
using UnityGameFramework.Runtime.AsyncTask;
namespace SepCore.UI
{
public abstract class UIControllerBase<TContext, TForm> : IUIFormController
where TContext : UIContext
where TForm : UGuiForm
{
private TContext _context;
private TForm _form;
private int? _formSerialId;
protected TContext Context => _context;
protected TForm Form => _form;
protected abstract UIFormType UIFormType { get; }
protected abstract void RefreshUI(TForm form, TContext context);
protected virtual void SubscribeCustomEvents()
{
}
protected virtual void UnsubscribeCustomEvents()
{
}
protected virtual void CloseLoadedFormDirect(TForm form)
{
form.Close();
}
protected async UniTask<int?> OpenFormAsync(TContext context, float timeout = 30f)
{
if (context == null)
{
Log.Warning("{0}.OpenFormAsync() context is null.", GetType().Name);
return null;
}
if (_form != null)
{
_context = context;
RefreshUI(_form, _context);
return _formSerialId;
}
_context = context;
UIForm uiForm = await GameEntry.UI.OpenUIFormAsync(UIFormType, _context, timeout);
if (uiForm == null)
{
Log.Warning("{0}.OpenFormAsync() failed to open form '{1}'.", GetType().Name, UIFormType.ToString());
return null;
}
_formSerialId = uiForm.SerialId;
_form = uiForm.Logic as TForm;
if (_form == null)
{
Log.Warning("{0} open success but form logic is invalid.", GetType().Name);
_context = null;
_formSerialId = null;
return null;
}
SubscribeCustomEvents();
RefreshUI(_form, _context);
return _formSerialId;
}
protected virtual async UniTask CloseFormAsync(object userData = null, float timeout = 30f)
{
UnsubscribeCustomEvents();
int? serialId = _formSerialId;
TForm form = _form;
_context = null;
_form = null;
_formSerialId = null;
if (serialId.HasValue)
{
if (GameEntry.UI.HasUIForm(serialId.Value))
{
await GameEntry.UI.CloseUIFormAsync(serialId.Value, userData, timeout);
}
return;
}
if (form != null)
{
CloseLoadedFormDirect(form);
}
}
public abstract UniTask<int?> OpenUIAsync(object userData = null, float timeout = 30f);
public virtual UniTask CloseUIAsync(object userData = null, float timeout = 30f)
{
return CloseFormAsync(userData, timeout);
}
public abstract void BindUseCase(IUIUseCase useCase);
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7e46538e3d51b6b4ca463fa6080ad335
guid: d69abc928823685498bed2fd356128be
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,14 +1,8 @@
using GameFramework.DataTable;
using GameFramework.UI;
using System.Collections;
using SepCore.DataTable;
using SepCore.Definition;
using CustomUtility;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
namespace SepCore.UI
{
public static class UIExtension
{
@@ -39,122 +33,5 @@ namespace UI
slider.value = value;
}
public static bool HasUIForm(this UIComponent uiComponent, UIFormType uiFormType, string uiGroupName = null)
{
return uiComponent.HasUIForm((int)uiFormType, uiGroupName);
}
public static bool HasUIForm(this UIComponent uiComponent, int uiFormId, string uiGroupName = null)
{
IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();
DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);
if (drUIForm == null)
{
return false;
}
string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);
if (string.IsNullOrEmpty(uiGroupName))
{
return uiComponent.HasUIForm(assetName);
}
IUIGroup uiGroup = uiComponent.GetUIGroup(uiGroupName);
if (uiGroup == null)
{
return false;
}
return uiGroup.HasUIForm(assetName);
}
public static UGuiForm GetUIForm(this UIComponent uiComponent, UIFormType uiFormType, string uiGroupName = null)
{
return uiComponent.GetUIForm((int)uiFormType, uiGroupName);
}
public static UGuiForm GetUIForm(this UIComponent uiComponent, int uiFormId, string uiGroupName = null)
{
IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();
DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);
if (drUIForm == null)
{
return null;
}
string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);
UIForm uiForm = null;
if (string.IsNullOrEmpty(uiGroupName))
{
uiForm = uiComponent.GetUIForm(assetName);
if (uiForm == null)
{
return null;
}
return (UGuiForm)uiForm.Logic;
}
IUIGroup uiGroup = uiComponent.GetUIGroup(uiGroupName);
if (uiGroup == null)
{
return null;
}
uiForm = (UIForm)uiGroup.GetUIForm(assetName);
if (uiForm == null)
{
return null;
}
return (UGuiForm)uiForm.Logic;
}
public static void CloseUIForm(this UIComponent uiComponent, UGuiForm uiForm)
{
uiComponent.CloseUIForm(uiForm.UIForm);
}
public static int? OpenUIForm(this UIComponent uiComponent, UIFormType uiFormType, object userData = null)
{
return uiComponent.OpenUIForm((int)uiFormType, userData);
}
public static int? OpenUIForm(this UIComponent uiComponent, int uiFormId, object userData = null)
{
IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();
DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);
if (drUIForm == null)
{
Log.Warning("Can not load UI form '{0}' from data table.", uiFormId.ToString());
return null;
}
string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);
if (!drUIForm.AllowMultiInstance)
{
if (uiComponent.IsLoadingUIForm(assetName))
{
return null;
}
if (uiComponent.HasUIForm(assetName))
{
return null;
}
}
return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName, Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, userData);
}
private static void OpenNativeDialog(DialogFormRawData rawData)
{
// TODO:这里应该弹出原生对话框,先简化实现为直接按确认按钮
if (rawData != null && rawData.OnClickConfirm != null)
{
rawData.OnClickConfirm(rawData.UserData);
}
}
}
}
@@ -1,10 +0,0 @@
namespace UI
{
public abstract class UIFormControllerBase<TContext> : IUIFormController where TContext : UIContext
{
protected abstract int? OpenUIInternal(TContext context);
public abstract int? OpenUI(object userData = null);
public abstract void CloseUI();
public abstract void BindUseCase(IUIUseCase useCase);
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 692b282b1ecbf5a44839d5bf4a03a937
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,183 +0,0 @@
using SepCore.Definition;
using GameFramework.Event;
using UnityGameFramework.Runtime;
namespace UI
{
public abstract class UIFormControllerCommonBase<TContext, TForm> : UIFormControllerBase<TContext>
where TContext : UIContext
where TForm : UGuiForm
{
private TContext _context;
private TForm _form;
private int? _formSerialId;
private bool _pendingRefresh;
private bool _isBindEvent;
protected TContext Context => _context;
protected TForm Form => _form;
protected int? FormSerialId => _formSerialId;
protected abstract UIFormType UIFormTypeId { get; }
protected abstract void RefreshUI(TForm form, TContext context);
protected virtual void SubscribeCustomEvents()
{
}
protected virtual void UnsubscribeCustomEvents()
{
}
protected virtual void CloseLoadedFormDirect(TForm form)
{
form.Close();
}
protected void SetContext(TContext context)
{
_context = context;
}
protected void RefreshCurrentUI()
{
if (_context == null)
{
return;
}
if (_form == null)
{
_pendingRefresh = true;
return;
}
RefreshUI(_form, _context);
_pendingRefresh = false;
}
protected override int? OpenUIInternal(TContext context)
{
if (context == null)
{
Log.Warning("{0}.OpenUI() context is null.", GetType().Name);
return null;
}
_context = context;
if (_form != null && _formSerialId.HasValue && GameEntry.UI.HasUIForm(_formSerialId.Value))
{
RefreshUI(_form, _context);
return _formSerialId;
}
CloseUI();
_pendingRefresh = true;
SubscribeEvents();
_formSerialId = GameEntry.UI.OpenUIForm(UIFormTypeId, _context);
return _formSerialId;
}
public override void CloseUI()
{
_pendingRefresh = false;
UnsubscribeEvents();
if (_formSerialId.HasValue)
{
if (GameEntry.UI.HasUIForm(_formSerialId.Value))
{
GameEntry.UI.CloseUIForm(_formSerialId.Value);
}
_form = null;
_formSerialId = null;
return;
}
if (_form != null)
{
CloseLoadedFormDirect(_form);
_form = null;
}
}
private void SubscribeEvents()
{
if (_isBindEvent)
{
return;
}
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
SubscribeCustomEvents();
_isBindEvent = true;
}
private void UnsubscribeEvents()
{
if (!_isBindEvent)
{
return;
}
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, CloseUIFormComplete);
UnsubscribeCustomEvents();
_isBindEvent = false;
}
private void OpenUIFormSuccess(object sender, GameEventArgs e)
{
if (!(e is OpenUIFormSuccessEventArgs args))
{
return;
}
if (!_formSerialId.HasValue)
{
return;
}
if (args.UIForm == null || args.UIForm.SerialId != _formSerialId.Value || args.UserData != _context)
{
return;
}
_form = args.UIForm.Logic as TForm;
if (_form == null)
{
Log.Warning("{0} open success but form logic is invalid.", GetType().Name);
return;
}
if (_pendingRefresh)
{
RefreshCurrentUI();
}
}
private void CloseUIFormComplete(object sender, GameEventArgs e)
{
if (!(e is CloseUIFormCompleteEventArgs args))
{
return;
}
if (args.SerialId != _formSerialId)
{
return;
}
_form = null;
_formSerialId = null;
}
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 696c0314286f89c4082c2aa2eddaec2d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,44 +0,0 @@
using SepCore.Definition;
using UnityGameFramework.Runtime;
namespace UI
{
public class TUIFormController : UIFormControllerCommonBase<UIContext, TUIForm>
{
private IUIUseCase _useCase;
protected override UIFormType UIFormTypeId => UIFormType.TUIForm;
protected override void RefreshUI(TUIForm form, UIContext context)
{
form.RefreshUI(context);
}
public override int? OpenUI(object userData = null)
{
if (userData is UIContext context)
{
return OpenUIInternal(context);
}
if (userData != null)
{
Log.Warning("TUIFormController.OpenUI() userData type is invalid.");
return null;
}
return OpenUIInternal(Context);
}
public override void BindUseCase(IUIUseCase useCase)
{
if (!(useCase is IUIUseCase uiFormUseCase))
{
Log.Error("LevelUpForm.BindUseCase() useCase is invalid.");
return;
}
_useCase = uiFormUseCase;
}
}
}
@@ -1,27 +0,0 @@
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UI
{
public class TUIForm : UGuiForm
{
public void RefreshUI(UIContext context)
{
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (!(userData is UIContext context))
{
Log.Error("UIContext is invalid.");
return;
}
RefreshUI(context);
}
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e8bc5e59a2be3094798c8c46d1a4999f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: