5 层 UI 规范收敛 SelectRoleForm 的 RawData / Context

围绕规范 §3.2 / §3.4 / §8 整理 SelectRoleForm 的数据传输与展示模型,让两层各自只承担规范允许的职责,并把子组件归位到模块目录内。

RawData层:
- RolePropertyAreaRawData 移除展示串 InitialPropertyText,改为业务字段 StatModifier[] InitialProperties,并补回 RoleId,避免 RawData 携带已格式化的展示文本(违反 §3.2)。
- SelectRoleRawData 拆掉平铺的 RoleIds / RoleIconNames 平行数组与 SelectedRoleId / SelectedRoleName / SelectedRoleInitialProperties 哨兵字段,聚合为 RoleItemRawData[] RoleItems 与 RolePropertyAreaRawData SelectedRole(null 表示未选中),跟 Context 端的子结构形态对称。
- SelectRoleUseCase.BuildModel 同步改造为构造子 RawData,不再处理 -1 哨兵 ID。

Context 层:
- 删除 SelectRoleContext.RoleIds 冗余字段(信息已由 RoleItemContexts[i].RoleId 承载)。
- 新增 bool ShowRoleProperty,把"显示属性卡 vs 显示随机卡"从 RolePropertyAreaContext == null 的隐式哨兵改成显式信号;Form 端 UpdateShowRole 改为读 ShowRoleProperty 切换卡片,不再用 null 当三态信号。
- Controller.BuildContext 用 rawData.SelectedRole != null 取代 >= 0 判定,InitialPropertyText 仍由 Controller 通过 ItemDescUtility.CreatePropDescription 拼装后注入 Context。

目录归属
事件命名
This commit is contained in:
SepComet
2026-06-16 17:09:20 +08:00
committed by basil
parent d2ce741a37
commit aca311dd60
21 changed files with 49 additions and 69 deletions
@@ -0,0 +1,41 @@
using Cysharp.Threading.Tasks;
using SepCore.Event;
using UnityEngine;
using UnityEngine.UI;
namespace SepCore.UI
{
public class RoleItem : MonoBehaviour
{
[SerializeField] private Image _roleImage = null;
private RoleItemContext _context = null;
public async UniTaskVoid OnInit(RoleItemContext context)
{
_context = context;
if (_context == null || string.IsNullOrEmpty(_context.IconName))
{
return;
}
_roleImage.sprite = await GameEntry.SpriteCache.GetSprite(_context.IconName);
}
public void OnReset()
{
_context = null;
}
public void UpdateShowRole()
{
int roleId = _context?.RoleId ?? -1;
GameEntry.Event.Fire(this, SelectRoleHoverEventArgs.Create(roleId));
}
public 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 int RoleId;
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,37 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace SepCore.UI
{
public class RolePropertyArea : MonoBehaviour
{
[SerializeField] private TMP_Text _roleNameText;
[SerializeField] private RawImage _roleAvatar;
[SerializeField] private TMP_Text _roleInitialPropertyText;
[SerializeField] private Transform _roleInitialItemParent;
private RolePropertyAreaContext _context;
public void OnInit(RolePropertyAreaContext context)
{
_context = context;
if (_context == null)
{
OnReset();
return;
}
_roleNameText.text = _context.RoleName;
_roleInitialPropertyText.text = _context.InitialPropertyText;
}
public void OnReset(object userData = null)
{
_context = null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e82dc413a4cd277429ec1e3f2de69434
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
namespace SepCore.UI
{
public class RolePropertyAreaContext : UIContext
{
public string RoleName;
public string InitialPropertyText;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f37335b27f20c647a0a6175226c0b45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -4,6 +4,6 @@ namespace SepCore.UI
{
public RoleItemContext[] RoleItemContexts;
public RolePropertyAreaContext RolePropertyAreaContext;
public int[] RoleIds;
public bool ShowRoleProperty;
}
}
@@ -21,14 +21,14 @@ namespace SepCore.UI
protected override void SubscribeCustomEvents()
{
GameEntry.Event.Subscribe(MenuSelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Subscribe(SelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Subscribe(SelectRoleHoverEventArgs.EventId, OnSelectRoleHover);
GameEntry.Event.Subscribe(SelectRoleConfirmEventArgs.EventId, OnMenuSelectRoleConfirm);
}
protected override void UnsubscribeCustomEvents()
{
GameEntry.Event.Unsubscribe(MenuSelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Unsubscribe(SelectRoleReturnEventArgs.EventId, OnSelectRoleReturn);
GameEntry.Event.Unsubscribe(SelectRoleHoverEventArgs.EventId, OnSelectRoleHover);
GameEntry.Event.Unsubscribe(SelectRoleConfirmEventArgs.EventId, OnMenuSelectRoleConfirm);
}
@@ -37,32 +37,29 @@ namespace SepCore.UI
{
if (rawData == null)
{
Log.Error("SelectRoleFormController.BuildContext() rawData is null.");
Log.Error("SelectRoleController.BuildContext() rawData is null.");
return null;
}
int count = rawData.RoleIds?.Length ?? 0;
int count = rawData.RoleItems?.Length ?? 0;
RoleItemContext[] roleItems = new RoleItemContext[count];
for (int i = 0; i < count; i++)
{
string iconName = rawData.RoleIconNames != null && i < rawData.RoleIconNames.Length
? rawData.RoleIconNames[i]
: null;
RoleItemRawData itemRawData = rawData.RoleItems[i];
roleItems[i] = new RoleItemContext
{
RoleId = rawData.RoleIds[i],
IconName = iconName
RoleId = itemRawData.RoleId,
IconName = itemRawData.IconName
};
}
RolePropertyAreaContext propertyContext = null;
if (rawData.SelectedRoleId >= 0)
if (rawData.SelectedRole != null)
{
propertyContext = new RolePropertyAreaContext
{
RoleName = rawData.SelectedRoleName,
InitialPropertyText = ItemDescUtility.CreatePropDescription(rawData.SelectedRoleInitialProperties)
RoleName = rawData.SelectedRole.RoleName,
InitialPropertyText = ItemDescUtility.CreatePropDescription(rawData.SelectedRole.InitialProperties)
?? string.Empty
};
}
@@ -71,7 +68,7 @@ namespace SepCore.UI
{
RoleItemContexts = roleItems,
RolePropertyAreaContext = propertyContext,
RoleIds = rawData.RoleIds
ShowRoleProperty = propertyContext != null
};
}
@@ -120,13 +117,14 @@ namespace SepCore.UI
{
if (Context == null)
{
Log.Error("SelectRoleFormController.UpdateShowRole() Context is null.");
Log.Error("SelectRoleController.UpdateShowRole() Context is null.");
return;
}
Context.RolePropertyAreaContext = rolePropertyAreaContext;
Context.ShowRoleProperty = rolePropertyAreaContext != null;
Form?.UpdateShowRole(rolePropertyAreaContext);
Form?.UpdateShowRole(Context.ShowRoleProperty, rolePropertyAreaContext);
}
private bool IsCurrentFormEventSender(object sender)
@@ -151,7 +149,7 @@ namespace SepCore.UI
return;
}
if (e is not MenuSelectRoleReturnEventArgs)
if (e is not SelectRoleReturnEventArgs)
{
return;
}
@@ -178,7 +176,7 @@ namespace SepCore.UI
{
if (_useCase == null)
{
Log.Error("SelectRoleFormController.OnMenuSelectRoleSelected() useCase is null.");
Log.Error("SelectRoleController.OnMenuSelectRoleSelected() useCase is null.");
return;
}
@@ -200,7 +198,7 @@ namespace SepCore.UI
if (_useCase == null)
{
Log.Error("SelectRoleFormController.OnMenuSelectRoleConfirm() useCase is null.");
Log.Error("SelectRoleController.OnMenuSelectRoleConfirm() useCase is null.");
return;
}
@@ -39,7 +39,7 @@ namespace SepCore.UI
roleIndex++;
}
UpdateShowRole(_context.RolePropertyAreaContext);
UpdateShowRole(_context.ShowRoleProperty, _context.RolePropertyAreaContext);
}
#region FSM
@@ -76,9 +76,9 @@ namespace SepCore.UI
#endregion
public void UpdateShowRole(RolePropertyAreaContext propertyAreaContext)
public void UpdateShowRole(bool showRoleProperty, RolePropertyAreaContext propertyAreaContext)
{
if (propertyAreaContext == null)
if (!showRoleProperty)
{
_randomRoleCard.SetActive(true);
_roleCard.SetActive(false);
@@ -94,7 +94,7 @@ namespace SepCore.UI
public void OnReturnButtonClick()
{
GameEntry.Event.Fire(this, MenuSelectRoleReturnEventArgs.Create());
GameEntry.Event.Fire(this, SelectRoleReturnEventArgs.Create());
}
}
}