Files
plugin-library/Assets/10.StoryEditor/RunTime/VisualEditor/Node/FlowNode.cs

128 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Sirenix.OdinInspector;
using UnityEngine;
using XNode;
namespace Stary.Evo.StoryEditor
{
[Serializable,CreateNodeMenu("")]
public class FlowNode : NodeBase
{
[HorizontalGroup("Port", order:0)]
[Input]
public Enter enter;
[HorizontalGroup("Port")]
[Output]
public Exit exit;
/// <summary>
/// Exit端口连接的节点的执行类型
/// </summary>
[BoxGroup("Config", order:5, showLabel:false)]
[LabelText("后续执行")]
public NodeExecuteType exitNodeExecuteType = NodeExecuteType.Async;
/// <summary>
/// 创建新的流程节点
/// </summary>
/// <param name="graph">所在的块</param>
/// <param name="name">节点名称</param>
/// <param name="position">节点位置</param>
/// <param name="prePorts">节点前部连接</param>
/// <param name="nextPorts">节点后部连接</param>
public static T Create<T>(NodeGraph graph, string name = null, Vector2 position = default,
List<NodePort> prePorts = null, List<NodePort> nextPorts = null) where T:FlowNode
{
// 创建节点
var node = NodeBase.Create<T>(graph, name, position);
if (node == null)
return null;
// 将剧本与前部节点和后部节点相连
var enterPort = node.GetInputPort("enter");
if (enterPort != null && prePorts != null)
prePorts.ForEach(port => port.Connect(enterPort));
var exitPort = node.GetInputPort("exit");
if (exitPort != null && nextPorts != null)
nextPorts.ForEach(port => port.Connect(exitPort));
return node;
}
#region
/// <summary>
/// 将自身的入口连接传递给指定端口
/// </summary>
/// <param name="otherPort">指定端口</param>
/// <param name="deleteSelf">传递后删除自身连接</param>
public void GiveEnterPortToOtherPort(NodePort otherPort, bool deleteSelf)
=> GiveConnectionToOtherPort(GetInputPort("enter"), otherPort, deleteSelf);
/// <summary>
/// 将自身的出口连接传递给指定端口
/// </summary>
/// <param name="otherPort">指定端口</param>
/// <param name="deleteSelf">传递后删除自身连接</param>
public void GiveExitPortToOtherPort(NodePort otherPort, bool deleteSelf = false)
=> GiveConnectionToOtherPort(GetOutputPort("exit"), otherPort, deleteSelf);
#endregion
#region
/// <summary>
/// 向前插入节点
/// </summary>
[HorizontalGroup("Insert", order:1)]
[Button("(←)插入节点")]
public void InsertForward()
{
// 生成新的空节点
var newNode = SelectionNode.Create(graph);
// 将本节点的Enter连接给到新的节点的Enter
GiveEnterPortToOtherPort(newNode.GetInputPort("enter"), true);
// 将新的节点的Exit连接到本节点的Enter
GetInputPort("enter").Connect(newNode.GetOutputPort("exit"));
// 将新节点设定为本节点位置
newNode.position = position;
// 将包括自身在内的所有后续节点向后移动一个默认间隔
newNode.DoActionToAllNodesAfter((thisNode, otherNode) => otherNode.position = thisNode.position + new Vector2(DefaultNodeXInterval, DefaultNodeYInterval));
}
/// <summary>
/// 向后插入节点
/// </summary>
[HorizontalGroup("Insert")]
[Button("插入节点(→)")]
public void InsertBackward()
{
// 生成新的空节点
var newNode = SelectionNode.Create(graph);
// 将本节点的Exit连接给到新的节点的Exit
GiveExitPortToOtherPort(newNode.GetOutputPort("exit"), true);
// 将新的节点的Enter连接到本节点的Exit
GetOutputPort("exit").Connect(newNode.GetInputPort("enter"));
// 将新节点设置为本节点位置后移一格
newNode.position = position + new Vector2(DefaultNodeXInterval, DefaultNodeYInterval);
// 将所有后续节点向后移动一个默认间隔
newNode.DoActionToAllNodesAfter((thisNode, otherNode) => otherNode.position = thisNode.position + new Vector2(DefaultNodeXInterval, DefaultNodeYInterval));
}
#endregion
/// <summary>
/// 导出
/// </summary>
public new async UniTask<FlowNodeData> Export()
{
FlowNodeData node = new(await base.Export());
node.executeType = exitNodeExecuteType;
return node;
}
}
}