State machines: asset, tab, State branch and Set state nodes (#51)
A state machine is an asset whose graph holds one `State` node per state (no ports, name as title), edited in a new "State machine" tab that reuses the graph canvas: right-click places "State n", snap toggle shared with the Behavior tab via SnapToggle. `statemachine` is a value kind like texture (port, literal node, variable, struct field, tagged list item). Behaviors use it through `State branch` (one exec output per state) and `Set state` (one exec input per state; the interpreter now hands `run` the entry port). States live per behavior instance in NodeContext.states, with no initial state. Ports derive from the inline picker or a wired `State machine` literal; BehaviorLookup became GraphLookup with behavior(id) and machine(id). The Graph tab is labelled "Behavior" (key unchanged). Unit tests (state-machine, kinds, catalog, ports), e2e step 26 and README added. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
ce42d16657
commit
e7d82bd1a9
60 files changed
+1269
-213
No files matched your search
@@ -9,6 +9,7 @@ import {
|
||||
isValidPortName,
|
||||
fixedPortKeys,
|
||||
nodeDef,
|
||||
STATE,
|
||||
} from '../graph';
|
||||
import type { Asset, TextureFrame } from '../model/Asset';
|
||||
import { isAssetType } from '../model/AssetTypes';
|
||||
@@ -89,6 +90,8 @@ export function deserializeProject(raw: unknown, fallbackId = ''): Project {
|
||||
variables: variables.get(id) ?? [],
|
||||
graph: normalizeGraph(a.graph),
|
||||
});
|
||||
} else if (type === 'statemachine') {
|
||||
assets.push({ id, type, name, props, graph: normalizeGraph(a.graph, STATE) });
|
||||
} else if (type === 'texture') {
|
||||
assets.push({ id, type, name, props, ...normalizeTexture(a, takenIds) });
|
||||
} else if (type === 'animation') {
|
||||
@@ -242,7 +245,8 @@ function normalizePorts(raw: unknown, fixed: readonly string[], writable: boolea
|
||||
return ports;
|
||||
}
|
||||
|
||||
function normalizeGraph(raw: unknown): Graph {
|
||||
/** `only` restricts the node types kept: a state machine's graph holds states and nothing else. */
|
||||
function normalizeGraph(raw: unknown, only?: string): Graph {
|
||||
const g = asRecord(raw);
|
||||
const graph = createEmptyGraph();
|
||||
const nodeIds = new Set<string>();
|
||||
@@ -251,7 +255,7 @@ function normalizeGraph(raw: unknown): Graph {
|
||||
const id = typeof n.id === 'string' ? n.id : '';
|
||||
const type = typeof n.type === 'string' ? n.type : '';
|
||||
const def = nodeDef(type);
|
||||
if (!id || nodeIds.has(id) || !def) continue;
|
||||
if (!id || nodeIds.has(id) || !def || (only !== undefined && type !== only)) continue;
|
||||
nodeIds.add(id);
|
||||
// Params carry both settings and inline input values, so there is no schema to coerce against.
|
||||
const params: PropertyBag = {};
|
||||
|
||||
Reference in new issue
Block a user