geometry-tower-defense/Assets/GameMain/Scripts/UI/Game/Controller/NodeMapFormController.cs

163 lines
5.3 KiB
C#

using GeometryTD.CustomEvent;
using GeometryTD.Definition;
using GeometryTD.Procedure;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.UI
{
public sealed class NodeMapFormController : UIFormControllerCommonBase<NodeMapFormContext, NodeMapForm>
{
private NodeMapFormUseCase _useCase;
protected override UIFormType UIFormTypeId => UIFormType.NodeMapForm;
protected override void RefreshUI(NodeMapForm form, NodeMapFormContext context)
{
form.RefreshUI(context);
}
protected override void SubscribeCustomEvents()
{
GameEntry.Event.Subscribe(NodeMapNodeClickEventArgs.EventId, OnNodeClicked);
}
protected override void UnsubscribeCustomEvents()
{
GameEntry.Event.Unsubscribe(NodeMapNodeClickEventArgs.EventId, OnNodeClicked);
}
public override int? OpenUI(object userData = null)
{
if (userData is NodeMapFormContext context)
{
return OpenUIInternal(context);
}
if (userData is NodeMapFormRawData rawDataFromUserData)
{
return OpenUI(rawDataFromUserData);
}
if (userData != null)
{
Log.Warning("NodeMapFormController.OpenUI() userData type is invalid.");
return null;
}
if (_useCase == null)
{
Log.Error("NodeMapFormController.OpenUI() useCase is null.");
return null;
}
return OpenUI(_useCase.CreateInitialModel());
}
public int? OpenUI(NodeMapFormRawData rawData)
{
return OpenUIInternal(BuildContext(rawData));
}
public override void BindUseCase(IUIUseCase useCase)
{
if (!(useCase is NodeMapFormUseCase nodeMapFormUseCase))
{
Log.Error("NodeMapFormController.BindUseCase() useCase is invalid.");
return;
}
_useCase = nodeMapFormUseCase;
}
private void OnNodeClicked(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is NodeMapNodeClickEventArgs args) || _useCase == null)
{
return;
}
if (!_useCase.TryRequestEnterNode(args.SequenceIndex, out NodeMapNodeRawData selectedNode, out NodeMapFormRawData latestRawData))
{
if (latestRawData != null)
{
SetContext(BuildContext(latestRawData));
RefreshCurrentUI();
}
return;
}
if (latestRawData != null)
{
SetContext(BuildContext(latestRawData));
RefreshCurrentUI();
}
if (Form != null && selectedNode != null)
{
GameEntry.Event.Fire(Form, NodeMapNodeEnterRequestedEventArgs.Create(
selectedNode.RunId,
selectedNode.NodeId,
selectedNode.NodeType,
selectedNode.SequenceIndex));
}
}
private bool IsEventFromCurrentForm(object sender)
{
if (Form == null)
{
return false;
}
if (ReferenceEquals(sender, Form))
{
return true;
}
if (sender is Component component)
{
NodeMapForm ownerForm = component.GetComponentInParent<NodeMapForm>();
return ownerForm == Form;
}
return false;
}
private static NodeMapFormContext BuildContext(NodeMapFormRawData rawData)
{
NodeItemContext[] nodeItemContexts = System.Array.Empty<NodeItemContext>();
if (rawData?.Nodes != null && rawData.Nodes.Count > 0)
{
nodeItemContexts = new NodeItemContext[rawData.Nodes.Count];
for (int i = 0; i < rawData.Nodes.Count; i++)
{
NodeMapNodeRawData node = rawData.Nodes[i];
nodeItemContexts[i] = new NodeItemContext
{
NodeId = node?.NodeId ?? 0,
SequenceIndex = node?.SequenceIndex ?? i,
NodeType = node?.NodeType ?? RunNodeType.None,
IsLocked = node != null && node.Status == RunNodeStatus.Locked,
IsCurrent = node != null && node.IsCurrentNode,
IsCompleted = node != null && node.Status == RunNodeStatus.Completed,
IsFailed = node != null && node.Status == RunNodeStatus.Failed,
CanClick = node != null && node.CanEnter
};
}
}
return new NodeMapFormContext
{
Title = rawData?.Title ?? "节点地图",
ProgressText = rawData?.ProgressText ?? "0 / 0",
CurrentNodeText = rawData?.CurrentNodeText ?? "当前节点: 无",
IsRunCompleted = rawData != null && rawData.IsRunCompleted,
NodeItems = nodeItemContexts
};
}
}
}