Let a Start input or a variable name the state machine it carries
A sub-behavior that gets its machine through a Start input had no state ports on Is in state, Set state and the other state nodes. Their ports came only from an inline pick or a State machine literal, so a machine handed in from outside left them empty. - A statemachine port of a Start node can now name a machine (DeclaredPort.machine). The inspector shows the pick next to the port name. SetPortMachineCommand sets it with undo. - machineIdOf follows an edge from such a port to that machine, so the state nodes it feeds offer its states. - A Run behavior node has the machine picked in advance on that input. - A different pick there is allowed, but the node warns, because the called graph asks for the states of its own machine. - A statemachine variable of a Variables node can name a machine the same way, picked next to the variable's row. - The inspector signature of a node now includes the picked machine. Before, the pick changed the ports but the dropdown kept its text until the node was selected again. - A local machine handed in still starts in no state every call. That rule from #229 is unchanged. Tests: - tests/core/start-machine.test.ts (7): ports with and without a machine and undo, save and load, the preset value moving a shared machine through the call, the warning, a port of another kind, the inspector signature, a Variables node. - Counter checks: without the new branch in machineIdOf 2 tests fail, without the machine in the signature 1 test fails. - Gate on melektaus-atx: 239 files, 3599 tests, CHECK EXIT 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3f12a77aea
commit
d80d5cce26
8 files changed
+284
-10
No files matched your search
@@ -279,6 +279,48 @@ export class SetPortWriteCommand implements Command {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Says which machine a `statemachine` port carries – an input of a start node, or a variable a
|
||||
* Variables node reads; empty says none. Edges on the states of the one before stay where they are
|
||||
* and hang there, as when a machine loses a state.
|
||||
*/
|
||||
export class SetPortMachineCommand implements Command {
|
||||
readonly label: string;
|
||||
private was: string | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly assetId: string,
|
||||
private readonly nodeId: string,
|
||||
private readonly key: string,
|
||||
private readonly machine: string,
|
||||
) {
|
||||
this.label = `Set machine of ${key}`;
|
||||
}
|
||||
|
||||
execute(project: Project): void {
|
||||
const node = requireNode(project, this.assetId, this.nodeId);
|
||||
if (!isEntryTerminal(node.type) && !declaresVariablePorts(node.type))
|
||||
throw new CommandError('Only a start node or a Variables node carries a machine');
|
||||
const port = (node.ports ?? []).find((p) => p.key === this.key);
|
||||
if (!port) throw new CommandError(`Port "${this.key}" not found`);
|
||||
if (port.kind !== 'statemachine') throw new CommandError(`"${this.key}" is not a state machine`);
|
||||
this.was = port.machine;
|
||||
this.mark(node, this.machine);
|
||||
}
|
||||
|
||||
undo(project: Project): void {
|
||||
this.mark(requireNode(project, this.assetId, this.nodeId), this.was ?? '');
|
||||
}
|
||||
|
||||
private mark(node: GraphNode, machine: string): void {
|
||||
node.ports = (node.ports ?? []).map((port) => {
|
||||
if (port.key !== this.key) return port;
|
||||
const { machine: _, ...plain } = port;
|
||||
return machine ? { ...plain, machine } : plain;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Rewrites the edges and inline values pointing at the port too, in every graph that has any. */
|
||||
export class RenamePortCommand extends RenameCommand {
|
||||
constructor(
|
||||
|
||||
Reference in new issue
Block a user