diff --git a/Editor/Flow.meta b/Editor/Flow.meta
new file mode 100644
index 0000000..ac894ba
--- /dev/null
+++ b/Editor/Flow.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 1e14c6504b4b4601bb79db0271af5e61
+timeCreated: 1673299690
\ No newline at end of file
diff --git a/Editor/Flow/FlowNodeEditor.cs b/Editor/Flow/FlowNodeEditor.cs
new file mode 100644
index 0000000..56e5356
--- /dev/null
+++ b/Editor/Flow/FlowNodeEditor.cs
@@ -0,0 +1,15 @@
+
+using XNode.Flow;
+
+namespace XNodeEditor.Flow
+{
+ [CustomNodeEditor(typeof(FlowNode))]
+ public class FlowNodeEditor : NodeEditor
+ {
+ public override void OnBodyGUI()
+ {
+ NodeEditorGUILayout.PortPair(target.GetPort("previousNode"), target.GetPort("nextNode"));
+ base.OnBodyGUI();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/Flow/FlowNodeEditor.cs.meta b/Editor/Flow/FlowNodeEditor.cs.meta
new file mode 100644
index 0000000..91aa59e
--- /dev/null
+++ b/Editor/Flow/FlowNodeEditor.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: efc69c086ec342a8b6aef9ff7ad81f5b
+timeCreated: 1673299707
\ No newline at end of file
diff --git a/Editor/NodeEditorGUILayout.cs b/Editor/NodeEditorGUILayout.cs
index a0e3358..8592d4b 100644
--- a/Editor/NodeEditorGUILayout.cs
+++ b/Editor/NodeEditorGUILayout.cs
@@ -6,6 +6,7 @@ using System.Reflection;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
+using XNode.Flow;
namespace XNodeEditor {
/// xNode-specific version of
@@ -194,7 +195,8 @@ namespace XNodeEditor {
if (port == null) return;
if (options == null) options = new GUILayoutOption[] { GUILayout.MinWidth(30) };
Vector2 position = Vector3.zero;
- GUIContent content = label != null ? label : new GUIContent(ObjectNames.NicifyVariableName(port.fieldName));
+ GUIContent content = label ?? new GUIContent(ObjectNames.NicifyVariableName(port.fieldName));
+ if (label == null && port.ValueType.IsAssignableFrom(typeof(FlowNode))) content = EditorGUIUtility.TrIconContent("Animation.Play", content.text);
// If property is an input, display a regular property field and put a port handle on the left side
if (port.direction == XNode.NodePort.IO.Input) {
diff --git a/Runtime/Flow.meta b/Runtime/Flow.meta
new file mode 100644
index 0000000..926ea9d
--- /dev/null
+++ b/Runtime/Flow.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 835a6229a286e044b87361784c807aef
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Flow/FlowNode.cs b/Runtime/Flow/FlowNode.cs
new file mode 100644
index 0000000..d21b758
--- /dev/null
+++ b/Runtime/Flow/FlowNode.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace XNode.Flow
+{
+ public abstract class FlowNode : Node
+ {
+ public override object GetValue(NodePort port)
+ {
+ if (port.IsConnected && port.Connection.node is FlowNode flowNode) return flowNode;
+ return null;
+ }
+
+ public virtual IEnumerator Perform()
+ {
+ yield break;
+ }
+
+ public virtual IEnumerable PreviousNodes => Array.Empty();
+ public virtual IEnumerable NextNodes => Array.Empty();
+
+ public FlowNode GetFlowNode(string portName) => GetValue(GetPort(portName)) as FlowNode;
+ }
+
+ public abstract class InFlowNode : FlowNode
+ {
+ [Input(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.Inherited)]
+ [SerializeField, HideInInspector]
+ public FlowNode previousNode;
+
+ public override IEnumerable PreviousNodes
+ {
+ get { yield return GetFlowNode("previousNodes"); }
+ }
+ }
+
+ public abstract class OutFlowNode : FlowNode
+ {
+ [Output(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.Inherited)]
+ [SerializeField, HideInInspector]
+ public FlowNode nextNode;
+
+ public override IEnumerable NextNodes
+ {
+ get { yield return GetFlowNode("nextNode"); }
+ }
+ }
+
+ public abstract class InOutFlowNode : FlowNode
+ {
+ [Input(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.Inherited)]
+ [SerializeField, HideInInspector]
+ public FlowNode previousNode;
+
+ [Output(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.Inherited)]
+ [SerializeField, HideInInspector]
+ public FlowNode nextNode;
+
+ public override IEnumerable PreviousNodes
+ {
+ get { yield return GetFlowNode("previousNodes"); }
+ }
+
+ public override IEnumerable NextNodes
+ {
+ get { yield return GetFlowNode("nextNode"); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Flow/FlowNode.cs.meta b/Runtime/Flow/FlowNode.cs.meta
new file mode 100644
index 0000000..eb141c4
--- /dev/null
+++ b/Runtime/Flow/FlowNode.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 19577700addb44bfbe0004ed13078931
+timeCreated: 1673298639
\ No newline at end of file