diff --git a/Forge/Statescript/Node.cs b/Forge/Statescript/Node.cs
index cc686fd..a28e119 100644
--- a/Forge/Statescript/Node.cs
+++ b/Forge/Statescript/Node.cs
@@ -226,13 +226,15 @@ internal virtual void Update(double deltaTime, GraphContext graphContext)
///
/// The type of port to create.
/// The index of the port.
+ /// The editor-facing label for the port.
/// The created port.
- protected static T CreatePort(byte index)
+ protected static T CreatePort(byte index, string label = "")
where T : Port, new()
{
return new T
{
Index = index,
+ Label = label ?? string.Empty,
};
}
diff --git a/Forge/Statescript/Nodes/ActionNode.cs b/Forge/Statescript/Nodes/ActionNode.cs
index fd44ee4..956118d 100644
--- a/Forge/Statescript/Nodes/ActionNode.cs
+++ b/Forge/Statescript/Nodes/ActionNode.cs
@@ -40,8 +40,8 @@ internal override IEnumerable GetReachableOutputPorts(byte inputPortIndex)
///
protected override void DefinePorts(List inputPorts, List outputPorts)
{
- inputPorts.Add(CreatePort(InputPort));
- outputPorts.Add(CreatePort(OutputPort));
+ inputPorts.Add(CreatePort(InputPort, "Input"));
+ outputPorts.Add(CreatePort(OutputPort, "Output"));
}
///
diff --git a/Forge/Statescript/Nodes/ConditionNode.cs b/Forge/Statescript/Nodes/ConditionNode.cs
index 7f0544e..ea4f5fc 100644
--- a/Forge/Statescript/Nodes/ConditionNode.cs
+++ b/Forge/Statescript/Nodes/ConditionNode.cs
@@ -47,9 +47,9 @@ internal override IEnumerable GetReachableOutputPorts(byte inputPortIndex)
///
protected override void DefinePorts(List inputPorts, List outputPorts)
{
- inputPorts.Add(CreatePort(InputPort));
- outputPorts.Add(CreatePort(TruePort));
- outputPorts.Add(CreatePort(FalsePort));
+ inputPorts.Add(CreatePort(InputPort, "Input"));
+ outputPorts.Add(CreatePort(TruePort, "True"));
+ outputPorts.Add(CreatePort(FalsePort, "False"));
}
///
diff --git a/Forge/Statescript/Nodes/EntryNode.cs b/Forge/Statescript/Nodes/EntryNode.cs
index c8cf871..2fb82c6 100644
--- a/Forge/Statescript/Nodes/EntryNode.cs
+++ b/Forge/Statescript/Nodes/EntryNode.cs
@@ -45,7 +45,7 @@ internal override IEnumerable GetReachableOutputPorts(byte inputPortIndex)
///
protected override void DefinePorts(List inputPorts, List outputPorts)
{
- outputPorts.Add(CreatePort(OutputPort));
+ outputPorts.Add(CreatePort(OutputPort, "Output"));
}
///
diff --git a/Forge/Statescript/Nodes/ExitNode.cs b/Forge/Statescript/Nodes/ExitNode.cs
index 72cbce0..e86c3c5 100644
--- a/Forge/Statescript/Nodes/ExitNode.cs
+++ b/Forge/Statescript/Nodes/ExitNode.cs
@@ -31,7 +31,7 @@ internal override IEnumerable GetReachableOutputPorts(byte inputPortIndex)
///
protected override void DefinePorts(List inputPorts, List outputPorts)
{
- inputPorts.Add(CreatePort(InputPort));
+ inputPorts.Add(CreatePort(InputPort, "Input"));
}
///
diff --git a/Forge/Statescript/Nodes/State/EffectNode.cs b/Forge/Statescript/Nodes/State/EffectNode.cs
index 8e0238d..7a81d9d 100644
--- a/Forge/Statescript/Nodes/State/EffectNode.cs
+++ b/Forge/Statescript/Nodes/State/EffectNode.cs
@@ -52,7 +52,7 @@ public class EffectNode : StateNode
protected override void DefinePorts(List inputPorts, List outputPorts)
{
base.DefinePorts(inputPorts, outputPorts);
- outputPorts.Add(CreatePort(OnEffectEndPort));
+ outputPorts.Add(CreatePort(OnEffectEndPort, "OnEffectEnd"));
}
///
diff --git a/Forge/Statescript/Nodes/State/TimerNode.cs b/Forge/Statescript/Nodes/State/TimerNode.cs
index 2b9cd97..c4d64d1 100644
--- a/Forge/Statescript/Nodes/State/TimerNode.cs
+++ b/Forge/Statescript/Nodes/State/TimerNode.cs
@@ -35,7 +35,7 @@ public class TimerNode : StateNode
protected override void DefinePorts(List inputPorts, List outputPorts)
{
base.DefinePorts(inputPorts, outputPorts);
- outputPorts.Add(CreatePort(OnTimerEndPort));
+ outputPorts.Add(CreatePort(OnTimerEndPort, "OnTimerEnd"));
}
///
diff --git a/Forge/Statescript/Nodes/StateNode.cs b/Forge/Statescript/Nodes/StateNode.cs
index d5b4efe..89edc3b 100644
--- a/Forge/Statescript/Nodes/StateNode.cs
+++ b/Forge/Statescript/Nodes/StateNode.cs
@@ -134,12 +134,12 @@ protected virtual void OnUpdate(double deltaTime, GraphContext graphContext)
///
protected override void DefinePorts(List inputPorts, List outputPorts)
{
- inputPorts.Add(CreatePort(InputPort));
- inputPorts.Add(CreatePort(AbortPort));
- outputPorts.Add(CreatePort(OnActivatePort));
- outputPorts.Add(CreatePort(OnDeactivatePort));
- outputPorts.Add(CreatePort(OnAbortPort));
- outputPorts.Add(CreatePort(SubgraphPort));
+ inputPorts.Add(CreatePort(InputPort, "Input"));
+ inputPorts.Add(CreatePort(AbortPort, "Abort"));
+ outputPorts.Add(CreatePort(OnActivatePort, "OnActivate"));
+ outputPorts.Add(CreatePort(OnDeactivatePort, "OnDeactivate"));
+ outputPorts.Add(CreatePort(OnAbortPort, "OnAbort"));
+ outputPorts.Add(CreatePort(SubgraphPort, "Subgraph"));
}
///
diff --git a/Forge/Statescript/Port.cs b/Forge/Statescript/Port.cs
index cb91300..8911ec7 100644
--- a/Forge/Statescript/Port.cs
+++ b/Forge/Statescript/Port.cs
@@ -16,4 +16,9 @@ public abstract class Port
/// Gets or sets the index of this port.
///
public byte Index { get; set; }
+
+ ///
+ /// Gets or sets the editor-facing label for this port.
+ ///
+ public string Label { get; set; } = string.Empty;
}
diff --git a/docs/statescript/nodes/README.md b/docs/statescript/nodes/README.md
index ca439c9..067a967 100644
--- a/docs/statescript/nodes/README.md
+++ b/docs/statescript/nodes/README.md
@@ -75,6 +75,12 @@ Carries **both** regular messages and disable-subgraph signals. Used by the Entr
Receives messages from connected output ports and notifies the owning node.
+## Port Labels
+
+Port labels are defined by the runtime node, not by editor-specific discovery code. Built-in nodes already provide labels for their standard ports automatically.
+
+If a custom node adds extra flow ports, create them with `CreatePort(index, "Label")` so editor integrations can surface the intended port name consistently without plugin-specific hard-coding.
+
## Graph Construction
Nodes are added to a graph with `AddNode()` and wired together with `AddConnection()`:
diff --git a/docs/statescript/nodes/state/README.md b/docs/statescript/nodes/state/README.md
index 5b99832..465319f 100644
--- a/docs/statescript/nodes/state/README.md
+++ b/docs/statescript/nodes/state/README.md
@@ -78,6 +78,18 @@ public class WaitForTagNode : StateNode
Use `DeactivateNode(graphContext)` for simple deactivation, or `DeactivateNodeAndEmitMessage(graphContext, portIds)` to emit custom event port messages before deactivation.
+If your state node defines additional event or subgraph ports, override `DefinePorts`, call `base.DefinePorts(...)`, and create each custom port with an explicit label:
+
+```csharp
+protected override void DefinePorts(List inputPorts, List outputPorts)
+{
+ base.DefinePorts(inputPorts, outputPorts);
+ outputPorts.Add(CreatePort(OnFinishedPort, "OnFinished"));
+}
+```
+
+That label becomes the canonical port name surfaced by editor integrations such as Forge for Godot.
+
## Built-in State Nodes
| Node | Description |
diff --git a/docs/statescript/subgraphs.md b/docs/statescript/subgraphs.md
index 4306328..bdff07d 100644
--- a/docs/statescript/subgraphs.md
+++ b/docs/statescript/subgraphs.md
@@ -150,6 +150,8 @@ Entry → TimerA(10s)
Custom state nodes can define additional Subgraph ports and control them independently while the node remains active. This is one of the most powerful patterns in Statescript.
+When defining extra Event or Subgraph ports for these nodes, assign explicit labels with `CreatePort(index, "Label")`. Editor integrations use those runtime labels when rendering custom ports.
+
For example, a combat stance node could have two Subgraph ports, one for each stance. While active, the node switches between stances by disabling one subgraph and activating the other:
```
diff --git a/docs/statescript/templates/action-node-template.md b/docs/statescript/templates/action-node-template.md
index 0a68547..6df9c72 100644
--- a/docs/statescript/templates/action-node-template.md
+++ b/docs/statescript/templates/action-node-template.md
@@ -19,6 +19,8 @@
|-------|------|------|-------------|
| 0 | Output | Event | Emits after execution. |
+> Port names should match the labels defined in code via `CreatePort(index, "Label")`.
+
## Parameters
**Input Properties:**
diff --git a/docs/statescript/templates/condition-node-template.md b/docs/statescript/templates/condition-node-template.md
index 5a8c242..16de355 100644
--- a/docs/statescript/templates/condition-node-template.md
+++ b/docs/statescript/templates/condition-node-template.md
@@ -20,6 +20,8 @@
| 0 | True | Event | Emits if the test returns `true`. |
| 1 | False | Event | Emits if the test returns `false`. |
+> Port names should match the labels defined in code via `CreatePort(index, "Label")`.
+
## Parameters
**Input Properties:**
diff --git a/docs/statescript/templates/state-node-template.md b/docs/statescript/templates/state-node-template.md
index 4d6a749..c8cdbd7 100644
--- a/docs/statescript/templates/state-node-template.md
+++ b/docs/statescript/templates/state-node-template.md
@@ -26,6 +26,7 @@
| {4+} | {Custom} | {Event or Subgraph} | {Description of additional ports.} |
> Remove the custom port rows if the node defines no additional ports beyond the standard four.
+> Port names should match the labels defined in code via `CreatePort(index, "Label")`.
## Parameters