引入 UISerializationRoot 和 Item

- 完成 MenuForm 和 SelectRoleForm 的迁移
This commit is contained in:
2026-09-13 22:18:29 +08:00
parent e2fdb660ab
commit 091a29db63
101 changed files with 5281 additions and 5753 deletions
@@ -0,0 +1,59 @@
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using SepCore.Event;
using UnityEngine;
using UnityEngine.UI;
namespace SepCore.UI
{
public class RoleItem : MonoBehaviour
{
[SerializeField] private Image _roleImage = null;
private RoleItemContext _context = null;
private bool _listenersBound;
public async UniTaskVoid OnInit(RoleItemContext context)
{
EnsureListeners();
_context = context;
if (string.IsNullOrEmpty(_context.IconName))
{
return;
}
_roleImage.sprite = await SpriteLoader.LoadSpriteByKeyAsync(_context.IconName);
}
public void OnReset()
{
_context = null;
}
private void EnsureListeners()
{
if (_listenersBound)
{
return;
}
_listenersBound = true;
CommonButton button = GetComponent<CommonButton>();
button.onClick.AddListener(OnConfirmRoleClick);
button.RegisterPointerEnterAction(OnHoverEnter);
}
private void OnHoverEnter()
{
GameEntry.Event.Fire(this, SelectRoleHoverEventArgs.Create(_context.RoleName));
}
private void OnConfirmRoleClick()
{
GameEntry.Event.Fire(this, SelectRoleConfirmEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35de2974f065de547952f8d5cbb9f6fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
namespace SepCore.UI
{
public class RoleItemContext : UIContext
{
public string RoleName;
public string IconName;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0337fd9faf4a5b44eb95858bff44c015
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
namespace SepCore.UI
{
public class SelectRoleContext : UIContext
{
public RoleItemContext[] RoleItemContexts;
public ShowAreaContext ShowAreaContext;
public bool ShowRoleProperty;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c34d5aa87925ee41b70887958e7611c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,222 @@
using Cysharp.Threading.Tasks;
using SepCore.Event;
using SepCore.Definition;
using SepCore.CustomUtility;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace SepCore.UI
{
public class SelectRoleController : UIControllerBase<SelectRoleContext, SelectRoleForm>
{
private SelectRoleUseCase _useCase;
protected override UIFormType UIFormType => UIFormType.SelectRoleForm;
protected override void RefreshUI(SelectRoleForm form, SelectRoleContext context)
{
form.RefreshUI(context);
}
protected override void SubscribeCustomEvents()
{
GameEntry.Event.Subscribe(SelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Subscribe(SelectRoleHoverEventArgs.EventId, OnSelectRoleHover);
GameEntry.Event.Subscribe(SelectRoleClearEventArgs.EventId, OnSelectRoleClear);
GameEntry.Event.Subscribe(SelectRoleConfirmEventArgs.EventId, OnSelectRoleConfirm);
}
protected override void UnsubscribeCustomEvents()
{
GameEntry.Event.Unsubscribe(SelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Unsubscribe(SelectRoleHoverEventArgs.EventId, OnSelectRoleHover);
GameEntry.Event.Unsubscribe(SelectRoleClearEventArgs.EventId, OnSelectRoleClear);
GameEntry.Event.Unsubscribe(SelectRoleConfirmEventArgs.EventId, OnSelectRoleConfirm);
}
private static SelectRoleContext BuildContext(SelectRoleRawData rawData)
{
if (rawData == null)
{
Log.Error("SelectRoleController.BuildContext() rawData is null.");
return null;
}
int count = rawData.RoleItems.Length;
RoleItemContext[] roleItems = new RoleItemContext[count];
for (int i = 0; i < count; i++)
{
RoleItemRawData itemRawData = rawData.RoleItems[i];
roleItems[i] = new RoleItemContext
{
RoleName = itemRawData.RoleName,
IconName = itemRawData.IconName
};
}
ShowAreaContext showAreaContext = null;
if (rawData.SelectedRole != null)
{
showAreaContext = new ShowAreaContext
{
RoleName = rawData.SelectedRole.Name,
InitialPropertyText = ItemDescUtility.CreatePropDescription(rawData.SelectedRole.InitialProperties)
};
}
return new SelectRoleContext
{
RoleItemContexts = roleItems,
ShowAreaContext = showAreaContext,
ShowRoleProperty = showAreaContext != null
};
}
public override async UniTask OpenUIAsync(object userData = null, float timeout = 30f)
{
if (userData is SelectRoleRawData rawData)
{
await OpenUIAsync(rawData, timeout);
return;
}
if (userData != null)
{
Log.Error("SelectRoleController.OpenUIAsync() userData type is invalid.");
return;
}
if (_useCase == null)
{
Log.Error("SelectRoleController.OpenUIAsync() useCase is null.");
return;
}
SelectRoleRawData initialRawData = _useCase.CreateModel();
await OpenUIAsync(initialRawData, timeout);
}
public async UniTask OpenUIAsync(SelectRoleRawData rawData, float timeout = 30f)
{
SelectRoleContext context = BuildContext(rawData);
await OpenFormAsync(context, timeout);
}
public override void BindUseCase(IUIUseCase useCase)
{
if (useCase is not SelectRoleUseCase selectRoleUseCase)
{
Log.Error("SelectRoleController.BindUseCase() useCase is invalid.");
return;
}
_useCase = selectRoleUseCase;
}
private bool IsCurrentFormEventSender(object sender)
{
if (sender is SelectRoleForm selectRoleForm)
{
return selectRoleForm == Form;
}
if (sender is Component component && Form != null)
{
return component.transform.IsChildOf(Form.transform);
}
return false;
}
private void OnSelectRoleReturn(object sender, GameEventArgs e)
{
if (e is not SelectRoleReturnEventArgs)
{
return;
}
if (!IsCurrentFormEventSender(sender))
{
return;
}
CloseUIAsync().Forget();
}
private void OnSelectRoleHover(object sender, GameEventArgs e)
{
if (e is not SelectRoleHoverEventArgs args)
{
return;
}
if (!IsCurrentFormEventSender(sender))
{
return;
}
OnSelectRoleHoverAsync(args).Forget();
}
private async UniTaskVoid OnSelectRoleHoverAsync(SelectRoleHoverEventArgs args)
{
if (_useCase == null)
{
Log.Error("SelectRoleController.OnSelectRoleHoverAsync() useCase is null.");
return;
}
SelectRoleRawData rawData = _useCase.SelectRole(args.RoleName);
await OpenUIAsync(rawData);
}
private void OnSelectRoleClear(object sender, GameEventArgs e)
{
if (e is not SelectRoleClearEventArgs)
{
return;
}
if (!IsCurrentFormEventSender(sender))
{
return;
}
OnSelectRoleClearAsync().Forget();
}
private async UniTaskVoid OnSelectRoleClearAsync()
{
if (_useCase == null)
{
Log.Error("SelectRoleController.OnSelectRoleClearAsync() useCase is null.");
return;
}
SelectRoleRawData rawData = _useCase.ClearSelection();
await OpenUIAsync(rawData);
}
private void OnSelectRoleConfirm(object sender, GameEventArgs e)
{
if (e is not SelectRoleConfirmEventArgs)
{
return;
}
if (!IsCurrentFormEventSender(sender))
{
return;
}
if (_useCase == null)
{
Log.Error("SelectRoleController.OnSelectRoleConfirm() useCase is null.");
return;
}
_useCase.ConfirmSelectedRole();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff46cd6b508b0304a801223cbae79419
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,115 @@
using System.Collections.Generic;
using SepCore.Event;
using UnityGameFramework.Runtime;
namespace SepCore.UI
{
public partial class SelectRoleForm
{
private readonly List<RoleItem> _roleItems = new List<RoleItem>();
private SelectRoleContext _context = null;
private bool _listenersBound;
public void RefreshUI(SelectRoleContext context)
{
EnsureButtonListeners();
_context = context;
EnsureRoleItemCount(context.RoleItemContexts.Length);
RoleItemContext[] roleContexts = _context.RoleItemContexts;
for (int i = 0; i < _roleItems.Count; i++)
{
RoleItem item = _roleItems[i];
if (i < roleContexts.Length)
{
item.OnInit(roleContexts[i]).Forget();
item.gameObject.SetActive(true);
}
else
{
item.OnReset();
item.gameObject.SetActive(false);
}
}
if (_context.ShowRoleProperty)
{
View.showAreaForm.ShowRoleProperty(_context.ShowAreaContext);
}
else
{
View.showAreaForm.ShowRandomRole();
}
}
#region Lifecycle
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (userData is SelectRoleContext context)
{
RefreshUI(context);
return;
}
Log.Error("SelectRoleForm requires SelectRoleContext as userData.");
}
protected override void OnClose(bool isShutdown, object userData)
{
base.OnClose(isShutdown, userData);
_context = null;
for (int i = 0; i < _roleItems.Count; i++)
{
_roleItems[i].OnReset();
}
}
#endregion
private void EnsureButtonListeners()
{
if (_listenersBound)
{
return;
}
_listenersBound = true;
View.returnButton.onClick.AddListener(OnReturnButtonClick);
View.randomRoleItem.onClick.AddListener(OnRandomConfirmClick);
View.randomRoleItem.RegisterPointerEnterAction(OnRandomHoverEnter);
}
private void EnsureRoleItemCount(int count)
{
while (_roleItems.Count < count)
{
RoleItem item = Instantiate(View.roleItemTemplate, View.roleListRoot);
_roleItems.Add(item);
}
}
private void OnReturnButtonClick()
{
GameEntry.Event.Fire(this, SelectRoleReturnEventArgs.Create());
}
private void OnRandomConfirmClick()
{
GameEntry.Event.Fire(this, SelectRoleConfirmEventArgs.Create());
}
private void OnRandomHoverEnter()
{
GameEntry.Event.Fire(this, SelectRoleClearEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad9c806bb95be684cb75ae84394f8cd0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
// <auto-generated />
using UnityEngine;
namespace SepCore.UI
{
[DisallowMultipleComponent]
public partial class SelectRoleForm : UGuiForm
{
[SerializeField] private SelectRoleView _view = null;
public SelectRoleView View => _view;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 665710bc9ed5c5547a40f0cc2d92ba2e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,15 @@
// <auto-generated />
using UnityEngine;
namespace SepCore.UI
{
[DisallowMultipleComponent]
public partial class SelectRoleView : MonoBehaviour
{
[SerializeField] public global::SepCore.UI.CommonButton returnButton;
[SerializeField] public global::UnityEngine.RectTransform roleListRoot;
[SerializeField] public global::SepCore.UI.CommonButton randomRoleItem;
[SerializeField] public global::SepCore.UI.RoleItem roleItemTemplate;
[SerializeField] public global::SepCore.UI.ShowAreaForm showAreaForm;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69fadbcf4f76eb4499b21ac72f667fc0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: