From 398cbafc95853b48a97922d509bce59a5484cd72 Mon Sep 17 00:00:00 2001 From: Lex Date: Mon, 1 Jun 2026 23:42:16 -0300 Subject: [PATCH 1/3] Added configurable port names --- Forge/Statescript/Node.cs | 4 +++- Forge/Statescript/Nodes/ActionNode.cs | 4 ++-- Forge/Statescript/Nodes/ConditionNode.cs | 6 +++--- Forge/Statescript/Nodes/EntryNode.cs | 2 +- Forge/Statescript/Nodes/ExitNode.cs | 2 +- Forge/Statescript/Nodes/State/EffectNode.cs | 2 +- Forge/Statescript/Nodes/State/TimerNode.cs | 2 +- Forge/Statescript/Nodes/StateNode.cs | 12 ++++++------ Forge/Statescript/Port.cs | 5 +++++ 9 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Forge/Statescript/Node.cs b/Forge/Statescript/Node.cs index cc686fd..c66ad13 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, }; } diff --git a/Forge/Statescript/Nodes/ActionNode.cs b/Forge/Statescript/Nodes/ActionNode.cs index fd44ee4..fa7f6e6 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, "Execute")); + outputPorts.Add(CreatePort(OutputPort, "Done")); } /// diff --git a/Forge/Statescript/Nodes/ConditionNode.cs b/Forge/Statescript/Nodes/ConditionNode.cs index 7f0544e..cc1b85c 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, "Condition")); + 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..26449c4 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, "Start")); } /// diff --git a/Forge/Statescript/Nodes/ExitNode.cs b/Forge/Statescript/Nodes/ExitNode.cs index 72cbce0..e674e62 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, "Stop")); } /// 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..b137238 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, "Begin")); + 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; } From b7f55ccd117a8a5c8fad42134e9cab9cde75dbe1 Mon Sep 17 00:00:00 2001 From: Lex Date: Tue, 2 Jun 2026 00:04:36 -0300 Subject: [PATCH 2/3] Update docs --- docs/statescript/nodes/README.md | 6 ++++++ docs/statescript/nodes/state/README.md | 12 ++++++++++++ docs/statescript/subgraphs.md | 2 ++ docs/statescript/templates/action-node-template.md | 2 ++ .../statescript/templates/condition-node-template.md | 2 ++ docs/statescript/templates/state-node-template.md | 1 + 6 files changed, 25 insertions(+) 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 From 66f17f50dac182fdc69d366e38357f3764e8e7d3 Mon Sep 17 00:00:00 2001 From: Lex Date: Tue, 2 Jun 2026 22:46:20 -0300 Subject: [PATCH 3/3] PR comments --- Forge/Statescript/Node.cs | 2 +- Forge/Statescript/Nodes/ActionNode.cs | 4 ++-- Forge/Statescript/Nodes/ConditionNode.cs | 2 +- Forge/Statescript/Nodes/EntryNode.cs | 2 +- Forge/Statescript/Nodes/ExitNode.cs | 2 +- Forge/Statescript/Nodes/StateNode.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Forge/Statescript/Node.cs b/Forge/Statescript/Node.cs index c66ad13..a28e119 100644 --- a/Forge/Statescript/Node.cs +++ b/Forge/Statescript/Node.cs @@ -234,7 +234,7 @@ protected static T CreatePort(byte index, string label = "") return new T { Index = index, - Label = label, + Label = label ?? string.Empty, }; } diff --git a/Forge/Statescript/Nodes/ActionNode.cs b/Forge/Statescript/Nodes/ActionNode.cs index fa7f6e6..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, "Execute")); - outputPorts.Add(CreatePort(OutputPort, "Done")); + 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 cc1b85c..ea4f5fc 100644 --- a/Forge/Statescript/Nodes/ConditionNode.cs +++ b/Forge/Statescript/Nodes/ConditionNode.cs @@ -47,7 +47,7 @@ internal override IEnumerable GetReachableOutputPorts(byte inputPortIndex) /// protected override void DefinePorts(List inputPorts, List outputPorts) { - inputPorts.Add(CreatePort(InputPort, "Condition")); + 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 26449c4..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, "Start")); + outputPorts.Add(CreatePort(OutputPort, "Output")); } /// diff --git a/Forge/Statescript/Nodes/ExitNode.cs b/Forge/Statescript/Nodes/ExitNode.cs index e674e62..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, "Stop")); + inputPorts.Add(CreatePort(InputPort, "Input")); } /// diff --git a/Forge/Statescript/Nodes/StateNode.cs b/Forge/Statescript/Nodes/StateNode.cs index b137238..89edc3b 100644 --- a/Forge/Statescript/Nodes/StateNode.cs +++ b/Forge/Statescript/Nodes/StateNode.cs @@ -134,7 +134,7 @@ protected virtual void OnUpdate(double deltaTime, GraphContext graphContext) /// protected override void DefinePorts(List inputPorts, List outputPorts) { - inputPorts.Add(CreatePort(InputPort, "Begin")); + inputPorts.Add(CreatePort(InputPort, "Input")); inputPorts.Add(CreatePort(AbortPort, "Abort")); outputPorts.Add(CreatePort(OnActivatePort, "OnActivate")); outputPorts.Add(CreatePort(OnDeactivatePort, "OnDeactivate"));