Aus #51: Die Kanten einer State machine sind gerade Linien von Node zu Node, ohne Ports (keine Bezier-Kurven wie im Behavior-Graph).
Was heute ist: Das Asset trägt bereits einen Graph mit edges, im State-machine-Tab sind aber nur State-Nodes ohne Ports – es gibt keinen Weg, eine Kante zu ziehen, und normalizeGraph(raw, STATE) behält beim Laden nur State-Nodes.
Zu klären / zu bauen:
Zeichnen: Ziehen von Node-Rand zu Node-Rand (Rechtsklick-Menü „Übergang nach …“ als Alternative), gerade Linie, Pfeilspitze am Ziel, Auswahl/Löschen/Undo über die vorhandenen Graph-Commands.
Speicherformat: edges mit from.node/to.node und leerem Port-Key, oder ein eigenes Feld transitions – das entscheidet, ob die Kanten-Commands des Graph-Editors wiederverwendet werden können.
Semantik im Behavior: Erlaubte Übergänge – soll Set state einen Wechsel ohne Kante verweigern (oder nur warnen)? Ein Node Transition / Next state (Exec rein, folgt der einzigen ausgehenden Kante) wäre der Nutzen der Kanten zur Laufzeit.
Optional an der Kante: Bedingung oder Timer („nach 2 s nach X“) – eher ein eigener Schritt.
Folge-Issue zu #51 (State machine, Commit e7d82bd, 2026-09-12).
Aus #51: Die Kanten einer State machine sind **gerade Linien von Node zu Node, ohne Ports** (keine Bezier-Kurven wie im Behavior-Graph).
**Was heute ist:** Das Asset trägt bereits einen `Graph` mit `edges`, im State-machine-Tab sind aber nur `State`-Nodes ohne Ports – es gibt keinen Weg, eine Kante zu ziehen, und `normalizeGraph(raw, STATE)` behält beim Laden nur State-Nodes.
**Zu klären / zu bauen:**
- Zeichnen: Ziehen von Node-Rand zu Node-Rand (Rechtsklick-Menü „Übergang nach …“ als Alternative), gerade Linie, Pfeilspitze am Ziel, Auswahl/Löschen/Undo über die vorhandenen Graph-Commands.
- Speicherformat: `edges` mit `from.node`/`to.node` und leerem Port-Key, oder ein eigenes Feld `transitions` – das entscheidet, ob die Kanten-Commands des Graph-Editors wiederverwendet werden können.
- Semantik im Behavior: Erlaubte Übergänge – soll `Set state` einen Wechsel ohne Kante **verweigern** (oder nur warnen)? Ein Node `Transition` / `Next state` (Exec rein, folgt der einzigen ausgehenden Kante) wäre der Nutzen der Kanten zur Laufzeit.
- Optional an der Kante: Bedingung oder Timer („nach 2 s nach X“) – eher ein eigener Schritt.
---
Folge-Issue zu #51 (State machine, Commit `e7d82bd`, 2026-09-12).
in/out port gefällt mir nicht (von der darstellung her) => lieber rechtsklick => make transition => klick auf anderen state
eine transition sollte man auch benennen können - der name muss nicht eindeutig sein innerhalb eines state machine
node "State transition" => dort wählt man per input port wieder eine state machine, und man wählt einen namen welche transition man machen möchte (transition namen sollten dann natürlich distincted sein, sprich keine duplikate)
die darstellung der pfeile ist schon gut, aber:
4.1. ein bisschen ein abstand zum node border wäre noch schön
4.2. wenn es in beide richtungen eine transition gibt, dann sind die beiden transition genau übereinander. schöner wäre es wenn die beiden nebeneinander liegen
was die benennung der transition betrifft, könnte man alle transition von einem node (in / out, 2 gruppen/section) im inspector anzeigen vom ausgewählten node und dort könnte man die transitions benennen.
wie ich es mir dachte:
1. in/out port gefällt mir nicht (von der darstellung her) => lieber rechtsklick => make transition => klick auf anderen state
2. eine transition sollte man auch benennen können - der name muss nicht eindeutig sein innerhalb eines state machine
3. node "State transition" => dort wählt man per input port wieder eine state machine, und man wählt einen namen welche transition man machen möchte (transition namen sollten dann natürlich distincted sein, sprich keine duplikate)
4. die darstellung der pfeile ist schon gut, aber:
4.1. ein bisschen ein abstand zum node border wäre noch schön
4.2. wenn es in beide richtungen eine transition gibt, dann sind die beiden transition genau übereinander. schöner wäre es wenn die beiden nebeneinander liegen
was die benennung der transition betrifft, könnte man alle transition von einem node (in / out, 2 gruppen/section) im inspector anzeigen vom ausgewählten node und dort könnte man die transitions benennen.
Umgesetzt in 68c92da, Wiki 7b5974b (State machines neu geschrieben, dazu Concepts, Home, Development).
1. Keine Pins. Verbunden wird per Rechtsklick auf einen Zustand -> Make transition -> Klick auf den Zielzustand; Escape, ein Klick ins Leere oder ein Asset-Wechsel bricht ab, und die Statuszeile sagt, worauf der Editor wartet. Ein Statetraegt die exec-Ports in/out weiterhin im Modell -- ein Port ist der einzige Anker, den eine Kante in diesem Editor hat -- der Editor zeichnet sie nur nie und gibt sie auch nicht mehr zum Anfassen heraus. Genau deshalb kamen Verbinden, Undo, das Aufraeumen beim Loeschen und das Speichern ohne eine Zeile Neubau.
2. Namen + Inspector.GraphEdge traegt jetzt ein optionales label. Am ausgewaehlten Zustand listet der Inspector TRANSITIONS OUT und TRANSITIONS IN getrennt -- je Zeile der Zustand am anderen Ende, ein Namensfeld und ein Entfernen-Knopf. Der Name wird auf den Pfeil gezeichnet. Diese Liste ist dabei nicht nur Komfort: Kanten haben nirgends einen Hit-Test, der Pin-Rechtsklick war bisher der einzige Weg zum Loeschen -- ohne die Liste waere eine Transition nach Punkt 1 unloeschbar geworden.
3. State transition ersetzt Next state (das gibt es nicht mehr). Maschine ueber den Input-Port wie bei Set state, Name ueber einen Picker, der die Transitionsnamen genau dieser Maschine anbietet. Aufgeloest wird gegen den aktuellen Zustand.
Zu dem Punkt, der sich zwischen 2. und 3. widersprochen hat, und den du dann so entschieden hast: Namen sind nicht maschinenweit eindeutig -- zwei Zustaende duerfen beide ein alarm haben, und genau das macht einen Node fuer mehrere Zustaende brauchbar. Eindeutig muessen sie nur je Ausgangszustand sein; der Inspector warnt bei einem Duplikat, und zur Laufzeit wird dann nicht gewechselt, weil eine Wahl zwischen zwei Pfeilen geraten waere. Ein leerer Name folgt der einen unbenannten Kante.
4.1 / 4.2 liegen als reine Mathematik in src/editor/graph/transitions.ts: ein Abstand zum Node-Rand, und ein Faecher, der Hin- und Rueckkante nebeneinanderlegt statt uebereinander.
Was der Screenshot gefunden hat, kein Check
Nach dem Entfernen der Pins zaehlte deren Zeile weiter fuer die Node-Hoehe -- die Zustaende hatten unten einen leeren Streifen. Jetzt sind die Kaesten kompakt. Davor hatte ein Screenshot schon einen zweiten Fehler gezeigt: eine gerade Kante von Pin zu Pin laeuft diagonal unter den Ziel-Node und nimmt ihre Pfeilspitze mit, weil nodeLayer ueber edgeLayer liegt. Deshalb laeuft sie jetzt Rand zu Rand -- was ohnehin naeher an 4.1 ist.
ConnectCommand lehnt eine zweite Kante zwischen demselben Paar mit Already connected ab, weil alle Uebergaenge auf denselben zwei Ports haengen. Mit Namen waere A --alarm--> B neben A --gesehen--> B ein sinnvolles Paar -- heute nicht moeglich. Ebenso bleibt die Self-Transition gesperrt (fromNode === toNode). Beides gehoert in je ein eigenes Issue, wenn du es willst.
Umgesetzt in 68c92da, Wiki 7b5974b (*State machines* neu geschrieben, dazu *Concepts*, *Home*, *Development*).
**1. Keine Pins.** Verbunden wird per Rechtsklick auf einen Zustand -> *Make transition* -> Klick auf den Zielzustand; `Escape`, ein Klick ins Leere oder ein Asset-Wechsel bricht ab, und die Statuszeile sagt, worauf der Editor wartet. Ein `State` *traegt* die exec-Ports `in`/`out` weiterhin im Modell -- ein Port ist der einzige Anker, den eine Kante in diesem Editor hat -- der Editor zeichnet sie nur nie und gibt sie auch nicht mehr zum Anfassen heraus. Genau deshalb kamen Verbinden, Undo, das Aufraeumen beim Loeschen und das Speichern ohne eine Zeile Neubau.
**2. Namen + Inspector.** `GraphEdge` traegt jetzt ein optionales `label`. Am ausgewaehlten Zustand listet der Inspector **TRANSITIONS OUT** und **TRANSITIONS IN** getrennt -- je Zeile der Zustand am anderen Ende, ein Namensfeld und ein Entfernen-Knopf. Der Name wird auf den Pfeil gezeichnet. Diese Liste ist dabei nicht nur Komfort: Kanten haben nirgends einen Hit-Test, der Pin-Rechtsklick war bisher der einzige Weg zum Loeschen -- ohne die Liste waere eine Transition nach Punkt 1 unloeschbar geworden.
**3. `State transition`** ersetzt `Next state` (das gibt es nicht mehr). Maschine ueber den Input-Port wie bei `Set state`, Name ueber einen Picker, der die Transitionsnamen genau dieser Maschine anbietet. Aufgeloest wird gegen den **aktuellen** Zustand.
Zu dem Punkt, der sich zwischen 2. und 3. widersprochen hat, und den du dann so entschieden hast: Namen sind **nicht** maschinenweit eindeutig -- zwei Zustaende duerfen beide ein `alarm` haben, und genau das macht *einen* Node fuer mehrere Zustaende brauchbar. Eindeutig muessen sie nur **je Ausgangszustand** sein; der Inspector warnt bei einem Duplikat, und zur Laufzeit wird dann nicht gewechselt, weil eine Wahl zwischen zwei Pfeilen geraten waere. Ein leerer Name folgt der einen unbenannten Kante.
**4.1 / 4.2** liegen als reine Mathematik in `src/editor/graph/transitions.ts`: ein Abstand zum Node-Rand, und ein Faecher, der Hin- und Rueckkante nebeneinanderlegt statt uebereinander.
## Was der Screenshot gefunden hat, kein Check
Nach dem Entfernen der Pins zaehlte deren **Zeile** weiter fuer die Node-Hoehe -- die Zustaende hatten unten einen leeren Streifen. Jetzt sind die Kaesten kompakt. Davor hatte ein Screenshot schon einen zweiten Fehler gezeigt: eine gerade Kante von Pin zu Pin laeuft diagonal unter den Ziel-Node und nimmt ihre Pfeilspitze mit, weil `nodeLayer` ueber `edgeLayer` liegt. Deshalb laeuft sie jetzt Rand zu Rand -- was ohnehin naeher an 4.1 ist.
## Belege
| | |
|---|---|
| `./check.sh` | `CHECK EXIT 0`, 971 Tests in 74 Dateien |
| e2e Modul 26 | `ALL PASSED -- 51 Checks`, `E2E EXIT 0` |
| Gegenproben | 5 Verbiegungen, jede beisst isoliert (Name ignoriert -> 2 FAILED; `label` beim Laden verworfen -> 1; Randabstand 0 -> 1; Versatz 0 -> 2; Pin-Guard entfernt -> 1 im Browser, die 48 uebrigen gruen) |
## Zwei Grenzen bleiben bewusst offen
`ConnectCommand` lehnt eine **zweite Kante zwischen demselben Paar** mit *Already connected* ab, weil alle Uebergaenge auf denselben zwei Ports haengen. Mit Namen waere `A --alarm--> B` neben `A --gesehen--> B` ein sinnvolles Paar -- heute nicht moeglich. Ebenso bleibt die **Self-Transition** gesperrt (`fromNode === toNode`). Beides gehoert in je ein eigenes Issue, wenn du es willst.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Aus #51: Die Kanten einer State machine sind gerade Linien von Node zu Node, ohne Ports (keine Bezier-Kurven wie im Behavior-Graph).
Was heute ist: Das Asset trägt bereits einen
Graphmitedges, im State-machine-Tab sind aber nurState-Nodes ohne Ports – es gibt keinen Weg, eine Kante zu ziehen, undnormalizeGraph(raw, STATE)behält beim Laden nur State-Nodes.Zu klären / zu bauen:
edgesmitfrom.node/to.nodeund leerem Port-Key, oder ein eigenes Feldtransitions– das entscheidet, ob die Kanten-Commands des Graph-Editors wiederverwendet werden können.Set stateeinen Wechsel ohne Kante verweigern (oder nur warnen)? Ein NodeTransition/Next state(Exec rein, folgt der einzigen ausgehenden Kante) wäre der Nutzen der Kanten zur Laufzeit.Folge-Issue zu #51 (State machine, Commit
e7d82bd, 2026-09-12).wie ich es mir dachte:
4.1. ein bisschen ein abstand zum node border wäre noch schön
4.2. wenn es in beide richtungen eine transition gibt, dann sind die beiden transition genau übereinander. schöner wäre es wenn die beiden nebeneinander liegen
was die benennung der transition betrifft, könnte man alle transition von einem node (in / out, 2 gruppen/section) im inspector anzeigen vom ausgewählten node und dort könnte man die transitions benennen.
Umgesetzt in
68c92da, Wiki 7b5974b (State machines neu geschrieben, dazu Concepts, Home, Development).1. Keine Pins. Verbunden wird per Rechtsklick auf einen Zustand -> Make transition -> Klick auf den Zielzustand;
Escape, ein Klick ins Leere oder ein Asset-Wechsel bricht ab, und die Statuszeile sagt, worauf der Editor wartet. EinStatetraegt die exec-Portsin/outweiterhin im Modell -- ein Port ist der einzige Anker, den eine Kante in diesem Editor hat -- der Editor zeichnet sie nur nie und gibt sie auch nicht mehr zum Anfassen heraus. Genau deshalb kamen Verbinden, Undo, das Aufraeumen beim Loeschen und das Speichern ohne eine Zeile Neubau.2. Namen + Inspector.
GraphEdgetraegt jetzt ein optionaleslabel. Am ausgewaehlten Zustand listet der Inspector TRANSITIONS OUT und TRANSITIONS IN getrennt -- je Zeile der Zustand am anderen Ende, ein Namensfeld und ein Entfernen-Knopf. Der Name wird auf den Pfeil gezeichnet. Diese Liste ist dabei nicht nur Komfort: Kanten haben nirgends einen Hit-Test, der Pin-Rechtsklick war bisher der einzige Weg zum Loeschen -- ohne die Liste waere eine Transition nach Punkt 1 unloeschbar geworden.3.
State transitionersetztNext state(das gibt es nicht mehr). Maschine ueber den Input-Port wie beiSet state, Name ueber einen Picker, der die Transitionsnamen genau dieser Maschine anbietet. Aufgeloest wird gegen den aktuellen Zustand.Zu dem Punkt, der sich zwischen 2. und 3. widersprochen hat, und den du dann so entschieden hast: Namen sind nicht maschinenweit eindeutig -- zwei Zustaende duerfen beide ein
alarmhaben, und genau das macht einen Node fuer mehrere Zustaende brauchbar. Eindeutig muessen sie nur je Ausgangszustand sein; der Inspector warnt bei einem Duplikat, und zur Laufzeit wird dann nicht gewechselt, weil eine Wahl zwischen zwei Pfeilen geraten waere. Ein leerer Name folgt der einen unbenannten Kante.4.1 / 4.2 liegen als reine Mathematik in
src/editor/graph/transitions.ts: ein Abstand zum Node-Rand, und ein Faecher, der Hin- und Rueckkante nebeneinanderlegt statt uebereinander.Was der Screenshot gefunden hat, kein Check
Nach dem Entfernen der Pins zaehlte deren Zeile weiter fuer die Node-Hoehe -- die Zustaende hatten unten einen leeren Streifen. Jetzt sind die Kaesten kompakt. Davor hatte ein Screenshot schon einen zweiten Fehler gezeigt: eine gerade Kante von Pin zu Pin laeuft diagonal unter den Ziel-Node und nimmt ihre Pfeilspitze mit, weil
nodeLayerueberedgeLayerliegt. Deshalb laeuft sie jetzt Rand zu Rand -- was ohnehin naeher an 4.1 ist.Belege
./check.shCHECK EXIT 0, 971 Tests in 74 DateienALL PASSED -- 51 Checks,E2E EXIT 0labelbeim Laden verworfen -> 1; Randabstand 0 -> 1; Versatz 0 -> 2; Pin-Guard entfernt -> 1 im Browser, die 48 uebrigen gruen)Zwei Grenzen bleiben bewusst offen
ConnectCommandlehnt eine zweite Kante zwischen demselben Paar mit Already connected ab, weil alle Uebergaenge auf denselben zwei Ports haengen. Mit Namen waereA --alarm--> BnebenA --gesehen--> Bein sinnvolles Paar -- heute nicht moeglich. Ebenso bleibt die Self-Transition gesperrt (fromNode === toNode). Beides gehoert in je ein eigenes Issue, wenn du es willst.