A state change is something the graph can react to, so the machine announces it (#53, #54, #55, #57)
game-maker / suite (push) Successful in 10m58s
game-maker / suite (push) Successful in 10m58s
Four issues that all reach for the same line: how the current state is read and written. Splitting them into four commits would mean four states of the tree that do not compile, so they arrive together. #55 start state — the machine asset carries an optional `start` holding a State node's id. Right-click a state to set or remove it, a ring in the node's title says which one it is. A dead id (the state was deleted) reads as "no start", so nothing has to clean up after a deletion. #53 entered/exited — `On state entered` and `On state exited`, one exec output per state. Every change now goes through a single `setState` that reports it; BehaviorSystem delivers it after the exec flow that caused it, `exited` of the old before `entered` of the new, round after round until the queue is empty, with a cap that stops a ping-pong graph with an endless-loop error. A local machine tells the instance that switched, a global one tells every instance holding a matching event node. The start state fires `entered` too: per instance for a local machine, once per run for a global one. #57 reading — `Current state` with `name` for showing and `id` for comparing, `Is in state` with one boolean per state. Neither has a `run`, so `read` learned `def` and `lookup`, and the catalog test knows this third kind of node. #54 seeing it — during a run the state machine tab marks every state some instance is holding faintly, and the one held by the selected scene object's instance strongly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bc57f61c91
commit
7babf88636
30 files changed
+906
-44
No files matched your search
@@ -0,0 +1,26 @@
|
||||
import type { NodeDef } from '../../NodeRegistry';
|
||||
import { currentState } from '../../sharedState';
|
||||
import { machinePort } from '../../stateMachine';
|
||||
import { asString } from '../../values';
|
||||
import { str } from '../shared';
|
||||
|
||||
/**
|
||||
* The data side of `State branch`: two outputs, because the two uses pull apart. `name` is what
|
||||
* `Join` and a `Text` want to show, `id` is what a comparison should hold – a rename moves the
|
||||
* name, never the id. Both are empty while the machine is in no state.
|
||||
*/
|
||||
export const CurrentState: NodeDef = {
|
||||
type: 'CurrentState',
|
||||
label: 'Current state',
|
||||
category: 'data',
|
||||
description: 'The state the machine is in: its name to show, its id to compare. Empty for no state.',
|
||||
inputs: [machinePort()],
|
||||
outputs: [str('name'), str('id')],
|
||||
params: [],
|
||||
read: (ctx, _params, input, _def, lookup) => {
|
||||
const machine = asString(input('machine'));
|
||||
const id = currentState(ctx, machine);
|
||||
const name = (id && lookup.machine(machine)?.states.find((s) => s.id === id)?.name) || '';
|
||||
return { name, id };
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { NodeDef } from '../../NodeRegistry';
|
||||
import { currentState } from '../../sharedState';
|
||||
import { machineOf, machinePort, statePorts } from '../../stateMachine';
|
||||
import { asString, type Value } from '../../values';
|
||||
|
||||
/**
|
||||
* One boolean per state, all false while the machine is in none – the data twin of `State branch`,
|
||||
* for the places a flow cannot go: `Branch`, `And`, a property. Every output is answered, so a
|
||||
* state nobody is in reads `false` rather than nothing at all.
|
||||
*/
|
||||
export const IsInState: NodeDef = {
|
||||
type: 'IsInState',
|
||||
label: 'Is in state',
|
||||
category: 'data',
|
||||
description: 'True on the output of the state the machine is in, false on every other.',
|
||||
inputs: [machinePort()],
|
||||
outputs: [],
|
||||
params: [],
|
||||
derivePorts: (source) => ({ outputs: statePorts(machineOf(source), 'boolean') }),
|
||||
read: (ctx, _params, input, def) => {
|
||||
const current = currentState(ctx, asString(input('machine')));
|
||||
const values: Record<string, Value> = {};
|
||||
for (const port of def.outputs) values[port.key] = port.key === current;
|
||||
return values;
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user