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
@@ -102,6 +102,13 @@ export class NodeView extends Widget {
|
||||
private problem: string | null = null;
|
||||
selected = false;
|
||||
hot = false;
|
||||
/** The state a machine begins in wears a ring, so the entry point is visible at a glance. */
|
||||
isStart = false;
|
||||
/**
|
||||
* While something is running: `held` for a state some instance of the machine is in, `current`
|
||||
* for the one the selected object's instance holds. Nothing outside a run.
|
||||
*/
|
||||
stateMark: 'none' | 'held' | 'current' = 'none';
|
||||
/** Port a running edge drag would connect to, drawn with a ring so the drop is predictable. */
|
||||
targetPort: { port: string; isOutput: boolean } | null = null;
|
||||
/** Data inputs that currently have a connection (their inline value is hidden). */
|
||||
@@ -390,10 +397,20 @@ export class NodeView extends Widget {
|
||||
.rect(0, TITLE_HEIGHT - Theme.radius, this.w, Theme.radius)
|
||||
.fill(categoryColor(this.def.category));
|
||||
this.drawChevron(PAD + 4, TITLE_HEIGHT / 2);
|
||||
// The ring sits where a state's ports never are: a state draws none (see `portCentres`).
|
||||
if (this.isStart)
|
||||
this.box
|
||||
.circle(this.w - PAD - PORT_RADIUS, TITLE_HEIGHT / 2, PORT_RADIUS)
|
||||
.stroke({ width: 2, color: c.text });
|
||||
const border = this.hot ? c.hot : this.selected ? c.nodeSelected : this.problem ? c.danger : c.nodeBorder;
|
||||
this.box
|
||||
.roundRect(0.5, 0.5, this.w - 1, this.h - 1, Theme.radius)
|
||||
.stroke({ width: this.selected || this.hot || this.problem ? 2 : 1, color: border });
|
||||
// Inside the border, so a selected state still shows both: what is picked, and what is live.
|
||||
if (this.stateMark !== 'none')
|
||||
this.box
|
||||
.roundRect(2.5, 2.5, this.w - 5, this.h - 5, Theme.radius)
|
||||
.stroke({ width: 2, color: c.hot, alpha: this.stateMark === 'current' ? 1 : 0.35 });
|
||||
|
||||
this.ports.clear();
|
||||
const r = PORT_RADIUS;
|
||||
|
||||
Reference in new issue
Block a user