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
@@ -72,13 +72,15 @@ describe('node registry', () => {
|
||||
const keys = [...def.inputs, ...def.outputs].map((p) => p.key);
|
||||
expect(new Set(def.inputs.map((p) => p.key)).size).toBe(def.inputs.length);
|
||||
expect(new Set(def.outputs.map((p) => p.key)).size).toBe(def.outputs.length);
|
||||
// An event is seeded by the runtime, so nothing flows into it.
|
||||
if (def.category === 'event') expect(def.inputs).toHaveLength(0);
|
||||
// An event is seeded by the runtime, so no flow arrives at one. What it may take is a data
|
||||
// input that says which event it means – the machine `On state entered` watches.
|
||||
if (def.category === 'event') expect(def.inputs.filter((p) => p.type === 'exec')).toHaveLength(0);
|
||||
// A state is a name in a machine; its ports only anchor transitions, so it never runs.
|
||||
else if (def.category === 'state') expect(def.run).toBeUndefined();
|
||||
// A shader node is compiled to GLSL and a particle node to a function: neither is ever run.
|
||||
else if (def.category === 'shader' || def.category === 'particles') expect('emit' in def).toBe(true);
|
||||
else expect(def.run).toBeTypeOf('function');
|
||||
// Everything else does one of the two: a step (`run`), or an answer whenever asked (`read`).
|
||||
else expect(typeof (def.run ?? def.read)).toBe('function');
|
||||
expect(keys.every((k) => k.length > 0)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user