继续重构调整(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
@@ -0,0 +1,45 @@
using SepCore.UI;
namespace SepCore.UI
{
/// <summary>
/// 对话框显示数据。
/// </summary>
public class DialogContext : UIContext
{
/// <summary>
/// 模式,即按钮数量。取值 1、2、3。
/// </summary>
public int Mode { get; set; }
/// <summary>
/// 标题。
/// </summary>
public string Title { get; set; }
/// <summary>
/// 消息内容。
/// </summary>
public string Message { get; set; }
/// <summary>
/// 弹出窗口时是否暂停游戏。
/// </summary>
public bool PauseGame { get; set; }
/// <summary>
/// 确认按钮文本。
/// </summary>
public string ConfirmText { get; set; }
/// <summary>
/// 取消按钮文本。
/// </summary>
public string CancelText { get; set; }
/// <summary>
/// 中立按钮文本。
/// </summary>
public string OtherText { get; set; }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8fb06a34d7fb37146a4b9e2f8138a724
timeCreated: 1528026160
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,137 @@
using System;
using Cysharp.Threading.Tasks;
using GameFramework;
using GameFramework.Event;
using SepCore.Definition;
using SepCore.Event;
using UnityGameFramework.Runtime;
namespace SepCore.UI
{
public class DialogController : UIControllerBase<DialogContext, DialogForm>
{
private GameFrameworkAction<object> _onClickConfirmGFAction;
private GameFrameworkAction<object> _onClickCancelGFAction;
private GameFrameworkAction<object> _onClickOtherGFAction;
private object _currentUserData;
protected override UIFormType UIFormType => UIFormType.DialogForm;
protected override void RefreshUI(DialogForm form, DialogContext context)
{
form.RefreshUI(context);
}
protected virtual DialogContext BuildContext(DialogRawData rawData)
{
if (rawData == null)
{
return null;
}
return new DialogContext
{
Mode = rawData.Mode,
Title = rawData.Title,
Message = rawData.Message,
PauseGame = rawData.PauseGame,
ConfirmText = rawData.ConfirmText,
CancelText = rawData.CancelText,
OtherText = rawData.OtherText,
};
}
public override async UniTask<int?> OpenUIAsync(object userData = null, float timeout = 30f)
{
if (userData is not DialogRawData rawData)
{
if (userData != null)
{
Log.Warning("DialogController.OpenUIAsync() userData type is invalid.");
}
else
{
Log.Warning("DialogController.OpenUIAsync() rawData is required.");
}
return null;
}
DialogContext context = BuildContext(rawData);
if (context == null)
{
Log.Warning("DialogController.OpenUIAsync() rawData is invalid.");
return null;
}
_onClickConfirmGFAction = rawData.OnClickConfirm;
_onClickCancelGFAction = rawData.OnClickCancel;
_onClickOtherGFAction = rawData.OnClickOther;
_currentUserData = rawData.UserData;
return await OpenFormAsync(context, timeout);
}
public override async UniTask CloseUIAsync(object userData = null, float timeout = 30f)
{
ClearCallbacks();
await CloseFormAsync(userData, timeout);
}
public override void BindUseCase(IUIUseCase useCase)
{
if (useCase != null)
{
Log.Warning("DialogController does not use a use case.");
}
}
protected override void SubscribeCustomEvents()
{
GameEntry.Event.Subscribe(DialogEventArgs.EventId, HandleDialogEventArgs);
}
protected override void UnsubscribeCustomEvents()
{
GameEntry.Event.Unsubscribe(DialogEventArgs.EventId, HandleDialogEventArgs);
}
private void HandleDialogEventArgs(object sender, GameEventArgs e)
{
if (e is not DialogEventArgs args) return;
var callback = args.ButtonId switch
{
1 => _onClickConfirmGFAction,
2 => _onClickCancelGFAction,
3 => _onClickOtherGFAction,
_ => null
};
object userData = _currentUserData;
CloseAndInvokeAsync(callback, userData).Forget();
}
private void ClearCallbacks()
{
_onClickConfirmGFAction = null;
_onClickCancelGFAction = null;
_onClickOtherGFAction = null;
_currentUserData = null;
}
private async UniTaskVoid CloseAndInvokeAsync(GameFrameworkAction<object> callback, object userData)
{
try
{
await CloseUIAsync();
}
catch (Exception exception)
{
Log.Warning("DialogController.CloseUIAsync() failed: {0}", exception.Message);
}
finally
{
callback?.Invoke(userData);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9a41ea68676c324091e71f3531a9da2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,129 @@
using TMPro;
using UnityEngine;
using UnityGameFramework.Runtime;
using SepCore.Event;
namespace SepCore.UI
{
public class DialogForm : UGuiForm
{
[SerializeField] private TMP_Text _titleText = null;
[SerializeField] private TMP_Text _messageText = null;
[SerializeField] private GameObject[] _modeObjects = null;
[SerializeField] private TMP_Text[] _confirmTexts = null;
[SerializeField] private TMP_Text[] _cancelTexts = null;
[SerializeField] private TMP_Text[] _otherTexts = null;
private int _dialogMode = 1;
private bool _pauseGame = false;
public void OnConfirmButtonClick()
{
GameEntry.Event.FireNow(this, DialogEventArgs.Create(1, null));
}
public void OnCancelButtonClick()
{
GameEntry.Event.FireNow(this, DialogEventArgs.Create(2, null));
}
public void OnOtherButtonClick()
{
GameEntry.Event.FireNow(this, DialogEventArgs.Create(3, null));
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (userData is not DialogContext context)
{
Log.Warning("DialogContext is invalid.");
return;
}
RefreshUI(context);
}
public void RefreshUI(DialogContext context)
{
if (context == null)
{
Log.Warning("DialogContext is invalid.");
return;
}
_dialogMode = context.Mode;
RefreshDialogMode();
_titleText.text = context.Title;
_messageText.text = context.Message;
_pauseGame = context.PauseGame;
RefreshPauseGame();
RefreshConfirmText(context.ConfirmText);
RefreshCancelText(context.CancelText);
RefreshOtherText(context.OtherText);
}
protected override void OnClose(bool isShutdown, object userData)
{
if (_pauseGame)
{
GameEntry.Base.ResumeGame();
}
_dialogMode = 1;
_titleText.text = string.Empty;
_messageText.text = string.Empty;
_pauseGame = false;
RefreshConfirmText(string.Empty);
RefreshCancelText(string.Empty);
RefreshOtherText(string.Empty);
base.OnClose(isShutdown, userData);
}
private void RefreshDialogMode()
{
for (int i = 1; i <= _modeObjects.Length; i++)
{
_modeObjects[i - 1].SetActive(i == _dialogMode);
}
}
private void RefreshPauseGame()
{
if (_pauseGame)
{
GameEntry.Base.PauseGame();
}
}
private void RefreshConfirmText(string confirmText)
{
foreach (var text in _confirmTexts)
{
text.text = confirmText;
}
}
private void RefreshCancelText(string cancelText)
{
foreach (var text in _cancelTexts)
{
text.text = cancelText;
}
}
private void RefreshOtherText(string otherText)
{
foreach (var text in _otherTexts)
{
text.text = otherText;
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e75b6daf7a6651845bdbc6cf9dcaa400
timeCreated: 1528026160
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: