- `Texture` and `Color` can be picked as a variable kind, a struct field kind and a declared port kind; a new `Texture` node hands a picture id into the graph. Declared, a texture is its bare id – the `$texture` tag stays a list-only thing. - The `String` node is labelled "Text" like its kind; the type id stays. - Whole-number inputs (`Item at`, `Set item`, `Sub list`, `Fill`, `Repeat`, `Substring`, `To text`) show no decimals (`int()` in shared.ts). - All server projects are reseeded, so `legacyNodes.ts`, `migrateDeclaredLists` and the `ownerId` fallback go, with their tests. - Note `reseed-because-of-list` moved to done/; new note `refactor-types`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
95 lines
3.0 KiB
TypeScript
95 lines
3.0 KiB
TypeScript
import type { PropertyBag } from '../model/Properties';
|
|
|
|
/** `exec` carries control flow, the others values; `any` accepts every value type. */
|
|
export type PortType = 'exec' | 'number' | 'boolean' | 'string' | 'object' | 'list' | 'struct' | 'any';
|
|
|
|
export interface PortRef {
|
|
node: string;
|
|
port: string;
|
|
}
|
|
|
|
/**
|
|
* `type` names a NodeDef in the registry; `params` holds both the node's own settings and the
|
|
* inline values of unconnected data inputs, keyed by param or port key.
|
|
*/
|
|
export interface GraphNode {
|
|
id: string;
|
|
type: string;
|
|
x: number;
|
|
y: number;
|
|
params: PropertyBag;
|
|
/**
|
|
* Ports the node declares itself, on top of the fixed ones of its type; the types that have
|
|
* them say so with `NodeDef.declaresPorts`. A behavior's start/end node is what gives the
|
|
* behavior its signature; an Expand/Pack node is what gives a struct its fields.
|
|
*/
|
|
ports?: DeclaredPort[];
|
|
/** Drawn as its title bar alone, every link meeting at one point per side. Purely visual. */
|
|
collapsed?: boolean;
|
|
}
|
|
|
|
/** A port a start/end node declares. `kind` maps to the PortType of the same name (`text` → string). */
|
|
export interface DeclaredPort {
|
|
key: string;
|
|
kind: DeclaredPortKind;
|
|
/** On a node declaring `both` sides: the port is an input too, so the node writes it. */
|
|
write?: true;
|
|
}
|
|
|
|
/** A color travels as a number and a texture as text; the kind says which field edits the value. */
|
|
export const DECLARED_PORT_KINDS = [
|
|
'number',
|
|
'boolean',
|
|
'text',
|
|
'color',
|
|
'texture',
|
|
'object',
|
|
'list',
|
|
'struct',
|
|
] as const;
|
|
export type DeclaredPortKind = (typeof DECLARED_PORT_KINDS)[number];
|
|
|
|
export function declaredPortType(kind: DeclaredPortKind): PortType {
|
|
if (kind === 'text' || kind === 'texture') return 'string';
|
|
return kind === 'color' ? 'number' : kind;
|
|
}
|
|
|
|
export interface GraphEdge {
|
|
id: string;
|
|
from: PortRef;
|
|
to: PortRef;
|
|
/** Drawn as a stub at each end instead of a curve across the graph. Purely visual. */
|
|
folded?: boolean;
|
|
}
|
|
|
|
export interface Graph {
|
|
nodes: GraphNode[];
|
|
edges: GraphEdge[];
|
|
}
|
|
|
|
export function createEmptyGraph(): Graph {
|
|
return { nodes: [], edges: [] };
|
|
}
|
|
|
|
export function findNode(graph: Graph, nodeId: string): GraphNode | undefined {
|
|
return graph.nodes.find((n) => n.id === nodeId);
|
|
}
|
|
|
|
/** Edges arriving at one input port (data inputs allow at most one, exec inputs any number). */
|
|
export function edgesInto(graph: Graph, nodeId: string, port: string): GraphEdge[] {
|
|
return graph.edges.filter((e) => e.to.node === nodeId && e.to.port === port);
|
|
}
|
|
|
|
export function edgesOutOf(graph: Graph, nodeId: string, port: string): GraphEdge[] {
|
|
return graph.edges.filter((e) => e.from.node === nodeId && e.from.port === port);
|
|
}
|
|
|
|
export function edgesOfNode(graph: Graph, nodeId: string): GraphEdge[] {
|
|
return graph.edges.filter((e) => e.from.node === nodeId || e.to.node === nodeId);
|
|
}
|
|
|
|
export function portsCompatible(from: PortType, to: PortType): boolean {
|
|
if (from === 'exec' || to === 'exec') return from === to;
|
|
return from === to || from === 'any' || to === 'any';
|
|
}
|