Let a node work out its own ports
Ports that vary per node already existed, but only for the three nested-behavior
types, and the rule for them sat as a switch on type names in nested.ts – the
one place in the project that knew node types by name. It dissolves into two
optional contracts on NodeDef, so a type carries its own rule:
declaresPorts the node holds an editable list, shown as a section in the
inspector – behavior start/end, and now Pack/Expand
derivePorts the node computes them from its settings – Sequence from a
count, Run behavior from the behavior it names
Sequence gains an Outputs setting (2 to 26). Its keys stay a, b, c and count on
with d, e, so the edges of the sequences already out there survive.
A param can now take a port away, and the edge on it would stay: it draws as
nothing yet survives every save, and comes back to life if the port returns.
SetNodeParamCommand takes those edges with it, which also closes the same leak
that switching a Run behavior node's target has always had.
The port editor addresses its node by id rather than by type, so two Pack nodes
can live in one graph, and it calls the rows Fields when they are not a
behavior's signature.
This commit is contained in:
1 parent
2cf788eedd
commit
b6a609ae24
23 files changed
+438
-98
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import type { PropertyBag, PropertyValue } from '../model/Properties';
|
||||
import type { PropertyDef } from '../properties/PropertySchema';
|
||||
import type { PortType } from './Graph';
|
||||
import type { BehaviorLookup } from './lookup';
|
||||
import type { NodeContext } from './NodeContext';
|
||||
import { asBoolean, asNumber, asString, type Value } from './values';
|
||||
|
||||
@@ -41,6 +42,19 @@ export interface RunResult {
|
||||
call?: CallResult;
|
||||
}
|
||||
|
||||
/** What a node may compute its ports from: its own settings, and the behaviors around it. */
|
||||
export interface PortSource {
|
||||
params: PropertyBag;
|
||||
behaviors: BehaviorLookup;
|
||||
}
|
||||
|
||||
/** Ports a single node has on top of the fixed ones of its type, and a label naming what it does. */
|
||||
export interface DerivedShape {
|
||||
label?: string;
|
||||
inputs?: PortDef[];
|
||||
outputs?: PortDef[];
|
||||
}
|
||||
|
||||
/** Palette, port rendering, connection validation and inspector fields are all derived from this. */
|
||||
export interface NodeDef {
|
||||
type: string;
|
||||
@@ -56,6 +70,16 @@ export interface NodeDef {
|
||||
* still offers them. Without it a switched-off repeat is two rows of "0" on every key node.
|
||||
*/
|
||||
hiddenParams?(params: PropertyBag): string[];
|
||||
/**
|
||||
* Which side the ports this node declares for itself (`GraphNode.ports`) appear on. Setting it
|
||||
* is what gives a node the port editor in the inspector.
|
||||
*/
|
||||
declaresPorts?: 'inputs' | 'outputs';
|
||||
/**
|
||||
* Ports this node computes beyond the fixed and the declared ones – how many outputs a Sequence
|
||||
* offers, which values the behavior a call node names takes. `resolveDef` applies it.
|
||||
*/
|
||||
derivePorts?(source: PortSource): DerivedShape;
|
||||
/**
|
||||
* Pure data nodes are evaluated on demand when a downstream input needs their value; exec nodes
|
||||
* run when the flow reaches them. Event nodes have no `run` – the interpreter seeds their outputs.
|
||||
|
||||
Reference in new issue
Block a user