补全部分 EventComponent 设计
This commit is contained in:
@@ -4,5 +4,7 @@ namespace GeometryTD.UI
|
||||
{
|
||||
public int OptionIndex;
|
||||
public string OptionText;
|
||||
public bool IsSelectable;
|
||||
public string BlockedReason;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace GeometryTD.UI
|
||||
{
|
||||
public class RepoFormContext : UIContext
|
||||
{
|
||||
public string GoldText;
|
||||
public CombineAreaContext CombineAreaContext;
|
||||
public CompAreaContext CompAreaContext;
|
||||
public ParticipantAreaContext ParticipantAreaContext;
|
||||
|
||||
@@ -140,6 +140,7 @@ namespace GeometryTD.UI
|
||||
|
||||
return new RepoFormContext
|
||||
{
|
||||
GoldText = $"金币: {rawData.Inventory.Gold}",
|
||||
CombineAreaContext = new CombineAreaContext(),
|
||||
CompAreaContext = new CompAreaContext
|
||||
{
|
||||
@@ -322,6 +323,7 @@ namespace GeometryTD.UI
|
||||
return;
|
||||
}
|
||||
|
||||
Form.RefreshGoldText(latestContext.GoldText);
|
||||
Form.RefreshParticipantArea(latestContext.ParticipantAreaContext);
|
||||
ApplyParticipantSelection();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace GeometryTD.UI
|
||||
|
||||
private static EventFormContext BuildContext(EventFormRawData rawData)
|
||||
{
|
||||
if (rawData?.EventItem == null)
|
||||
if (rawData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -82,24 +82,30 @@ namespace GeometryTD.UI
|
||||
for (int i = 0; i < options.Length; i++)
|
||||
{
|
||||
string optionText = string.Empty;
|
||||
if (rawData.EventItem.Options != null && i < rawData.EventItem.Options.Length &&
|
||||
rawData.EventItem.Options[i] != null)
|
||||
bool isSelectable = false;
|
||||
string blockedReason = string.Empty;
|
||||
if (rawData.OptionItems != null && i < rawData.OptionItems.Length &&
|
||||
rawData.OptionItems[i] != null)
|
||||
{
|
||||
optionText = rawData.EventItem.Options[i].OptionText;
|
||||
optionText = rawData.OptionItems[i].OptionText;
|
||||
isSelectable = rawData.OptionItems[i].IsSelectable;
|
||||
blockedReason = rawData.OptionItems[i].BlockedReason;
|
||||
}
|
||||
|
||||
options[i] = new EventOptionItemContext
|
||||
{
|
||||
OptionIndex = i,
|
||||
OptionText = optionText
|
||||
OptionText = optionText,
|
||||
IsSelectable = isSelectable,
|
||||
BlockedReason = blockedReason
|
||||
};
|
||||
}
|
||||
|
||||
return new EventFormContext
|
||||
{
|
||||
EventId = rawData.EventItem.Id,
|
||||
Title = rawData.EventItem.Title,
|
||||
Description = rawData.EventItem.Description,
|
||||
EventId = rawData.EventId,
|
||||
Title = rawData.Title,
|
||||
Description = rawData.Description,
|
||||
OptionItems = options
|
||||
};
|
||||
}
|
||||
@@ -117,7 +123,7 @@ namespace GeometryTD.UI
|
||||
return;
|
||||
}
|
||||
|
||||
m_UseCase.SelectOption(args.SelectedItemId);
|
||||
m_UseCase.TrySelectOption(args.SelectedItemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,8 +245,8 @@ namespace GeometryTD.UI
|
||||
RepoFormContext latestContext = BuildContext(latestRawData);
|
||||
if (latestContext != null)
|
||||
{
|
||||
Form.RefreshUI(latestContext);
|
||||
ApplyParticipantSelection();
|
||||
SetContext(latestContext);
|
||||
RefreshCurrentUI();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
using GeometryTD.Definition;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class EventFormRawData
|
||||
{
|
||||
public EventItem EventItem;
|
||||
public int EventId;
|
||||
public string Title;
|
||||
public string Description;
|
||||
public EventOptionRawData[] OptionItems;
|
||||
}
|
||||
|
||||
public sealed class EventOptionRawData
|
||||
{
|
||||
public int OptionIndex;
|
||||
public string OptionText;
|
||||
public bool IsSelectable;
|
||||
public string BlockedReason;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using GeometryTD.CustomComponent;
|
||||
using GeometryTD.CustomEvent;
|
||||
using GeometryTD.Definition;
|
||||
using GeometryTD.Procedure;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
@@ -8,10 +7,21 @@ namespace GeometryTD.UI
|
||||
public class EventFormUseCase : IUIUseCase
|
||||
{
|
||||
private EventItem _currentEvent;
|
||||
private RunNodeExecutionContext _currentContext;
|
||||
private readonly EventOptionExecutor _executor = new EventOptionExecutor();
|
||||
|
||||
public void SetCurrentEvent(EventItem eventItem)
|
||||
public void BindEvent(
|
||||
EventItem eventItem,
|
||||
RunNodeExecutionContext context)
|
||||
{
|
||||
_currentEvent = eventItem;
|
||||
_currentContext = context != null ? context.Clone() : null;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_currentEvent = null;
|
||||
_currentContext = null;
|
||||
}
|
||||
|
||||
public EventFormRawData CreateInitialModel()
|
||||
@@ -23,26 +33,74 @@ namespace GeometryTD.UI
|
||||
|
||||
return new EventFormRawData
|
||||
{
|
||||
EventItem = _currentEvent
|
||||
EventId = _currentEvent.Id,
|
||||
Title = _currentEvent.Title,
|
||||
Description = _currentEvent.Description,
|
||||
OptionItems = BuildOptionItems()
|
||||
};
|
||||
}
|
||||
|
||||
public EventOption SelectOption(int optionIndex)
|
||||
public bool TrySelectOption(int optionIndex)
|
||||
{
|
||||
if (_currentEvent == null || _currentEvent.Options == null)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (optionIndex < 0 || optionIndex >= _currentEvent.Options.Length)
|
||||
{
|
||||
Log.Warning("EventFormUseCase.SelectOption() option index is invalid: {0}", optionIndex);
|
||||
return null;
|
||||
Log.Warning("EventFormUseCase.TrySelectOption() option index is invalid: {0}", optionIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
BackpackInventoryData workingInventory = GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: new BackpackInventoryData();
|
||||
EventOptionExecutionResult executionResult = _executor.Execute(
|
||||
_currentEvent,
|
||||
optionIndex,
|
||||
_currentContext,
|
||||
workingInventory);
|
||||
if (!executionResult.IsAccepted)
|
||||
{
|
||||
Log.Warning(
|
||||
"EventFormUseCase.TrySelectOption() rejected. EventId={0}, OptionIndex={1}, Reason={2}",
|
||||
_currentEvent.Id,
|
||||
optionIndex,
|
||||
executionResult.FailureReason);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GameEntry.PlayerInventory != null)
|
||||
{
|
||||
GameEntry.PlayerInventory.ReplaceInventorySnapshot(workingInventory);
|
||||
}
|
||||
|
||||
// TODO: 执行 Requirements 校验、CostEffects/RewardEffects 结算与后续节点推进。
|
||||
GameEntry.EventNode.EndEvent();
|
||||
return _currentEvent.Options[optionIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
private EventOptionRawData[] BuildOptionItems()
|
||||
{
|
||||
EventOption[] options = _currentEvent.Options ?? System.Array.Empty<EventOption>();
|
||||
EventOptionRawData[] result = new EventOptionRawData[options.Length];
|
||||
BackpackInventoryData inventory = GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: new BackpackInventoryData();
|
||||
for (int i = 0; i < options.Length; i++)
|
||||
{
|
||||
EventOption option = options[i];
|
||||
EventOptionAvailability availability = _executor.EvaluateOption(option, inventory);
|
||||
result[i] = new EventOptionRawData
|
||||
{
|
||||
OptionIndex = i,
|
||||
OptionText = option?.OptionText ?? string.Empty,
|
||||
IsSelectable = availability.IsSelectable,
|
||||
BlockedReason = availability.BlockedReason
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,18 @@ namespace GeometryTD.UI
|
||||
public class EventOptionItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_Text _optionText;
|
||||
|
||||
|
||||
private static readonly Color SelectableTextColor = Color.white;
|
||||
private static readonly Color BlockedTextColor = new Color(0.75f, 0.75f, 0.75f, 1f);
|
||||
|
||||
private int _optionIndex;
|
||||
private bool _isSelectable;
|
||||
private CommonButton _commonButton;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_commonButton = GetComponent<CommonButton>();
|
||||
}
|
||||
|
||||
public void OnInit(EventOptionItemContext context)
|
||||
{
|
||||
@@ -20,9 +30,16 @@ namespace GeometryTD.UI
|
||||
}
|
||||
|
||||
_optionIndex = context.OptionIndex;
|
||||
_isSelectable = context.IsSelectable;
|
||||
if (_optionText != null)
|
||||
{
|
||||
_optionText.text = context.OptionText ?? string.Empty;
|
||||
_optionText.text = BuildDisplayText(context);
|
||||
_optionText.color = _isSelectable ? SelectableTextColor : BlockedTextColor;
|
||||
}
|
||||
|
||||
if (_commonButton != null)
|
||||
{
|
||||
_commonButton.Interactive = _isSelectable;
|
||||
}
|
||||
|
||||
gameObject.SetActive(!string.IsNullOrEmpty(context.OptionText));
|
||||
@@ -31,20 +48,38 @@ namespace GeometryTD.UI
|
||||
public void OnReset()
|
||||
{
|
||||
_optionIndex = -1;
|
||||
_isSelectable = false;
|
||||
if (_optionText != null)
|
||||
{
|
||||
_optionText.text = string.Empty;
|
||||
_optionText.color = SelectableTextColor;
|
||||
}
|
||||
|
||||
if (_commonButton != null)
|
||||
{
|
||||
_commonButton.Interactive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
if (_optionIndex < 0)
|
||||
if (_optionIndex < 0 || !_isSelectable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, EventOptionItemSelectedEventArgs.Create(_optionIndex));
|
||||
}
|
||||
|
||||
private static string BuildDisplayText(EventOptionItemContext context)
|
||||
{
|
||||
string optionText = context.OptionText ?? string.Empty;
|
||||
if (context.IsSelectable || string.IsNullOrEmpty(context.BlockedReason))
|
||||
{
|
||||
return optionText;
|
||||
}
|
||||
|
||||
return $"{optionText}\n<size=75%>{context.BlockedReason}</size>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using GeometryTD.CustomEvent;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace GeometryTD.UI
|
||||
|
||||
[SerializeField] private ParticipantArea _participantArea;
|
||||
|
||||
[SerializeField] private TMP_Text _goldText;
|
||||
|
||||
public void RefreshUI(RepoFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
@@ -19,11 +22,21 @@ namespace GeometryTD.UI
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshGoldText(context.GoldText);
|
||||
|
||||
_combineArea?.OnInit(context.CombineAreaContext);
|
||||
_compArea?.OnInit(context.CompAreaContext);
|
||||
_participantArea?.OnInit(context.ParticipantAreaContext);
|
||||
}
|
||||
|
||||
public void RefreshGoldText(string goldText)
|
||||
{
|
||||
if (_goldText != null)
|
||||
{
|
||||
_goldText.text = goldText ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryAssignItemToCombineArea(RepoItemContext itemContext)
|
||||
{
|
||||
if (_combineArea == null)
|
||||
@@ -69,6 +82,11 @@ namespace GeometryTD.UI
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
if (_goldText != null)
|
||||
{
|
||||
_goldText.text = string.Empty;
|
||||
}
|
||||
|
||||
_combineArea?.OnReset();
|
||||
_compArea?.OnReset();
|
||||
_participantArea?.OnReset();
|
||||
|
||||
Reference in New Issue
Block a user