Behavior: mehrere Flow-Ports an Start und End, und der Event-Node On behavior #294

Closed
opened 2026-10-02 18:24:20 +02:00 by meleki · 1 comment
Owner

Aus der Zwischenfrage vom 2026-10-02 (bei #216): Der User will Behaviors als eigene Verzweigungs-Nodes bauen, etwa für Eingaben. Dafür reicht der eine Flow-Port an Start und End nicht. Die sechs offenen Punkte sind vor dem Anlegen per Rückfrage geklärt, siehe Entschieden.

Nachtrag vom selben Tag: Der Node On behavior gehört jetzt mit in dieses Issue (Wunsch des Users: „gleich mit rein, alles in einem Wisch“). Seine fünf Punkte sind ebenfalls per Rückfrage geklärt, siehe On behavior.

Stand heute

  • Start und End haben je genau einen festen Flow-Port (exec). Deklarieren lassen sich nur Wert-Ports, der Name exec ist dafür gesperrt (isValidPortName in src/core/graph/nested.ts).
  • Run behavior hat einen Flow-Eingang und einen Flow-Ausgang. Seine Wert-Ports leitet es aus den deklarierten Ports von Start und End des gewählten Behaviors ab (derivePorts in src/core/graph/nodes/flow/RunBehavior.ts).
  • Der Aufruf beginnt immer am exec des Start (oder an jedem On start, wenn es kein Start gibt, #230) und geht am Aufrufer immer am exec weiter, auch wenn das End nie erreicht wurde (call in src/core/graph/GraphInterpreter.ts).
  • End beendet den inneren Lauf nicht. Es legt nur seine Eingangswerte ab, andere Zweige laufen weiter. Wird es mehrmals erreicht, gelten die Werte des letzten Durchgangs.
  • Es zählt ein Start und ein End je Graph, ein zweites wird ignoriert.

Entschieden (Antworten des Users)

  1. Der feste exec bleibt immer da und verhält sich wie heute. Run behavior geht am exec immer weiter. Die zusätzlichen Ausgänge feuern zusätzlich, wenn ihr Eingang am End erreicht wurde. Bestehende Graphen ändern sich nicht.
  2. Wird das End in einem Aufruf über mehrere Flow-Eingänge erreicht, feuert nur der zuletzt erreichte. Ein Aufruf geht also höchstens an einem Zusatz-Ausgang weiter. Das passt zu den Werten, bei denen auch der letzte Durchgang gilt.
  3. Zusatz-Ports am Start: Run behavior bekommt je Port einen eigenen Flow-Eingang. Kommt der Puls am Eingang open an, beginnt der innere Lauf nur am gleichnamigen Ausgang open des Start. Der feste exec des Start feuert nur, wenn der Aufruf über exec hereinkam.
  4. Anlegen im Inspector als weitere Art flow in der bestehenden Port-Liste von Start und End: ein Knopf, eine Liste, Umbenennen, Löschen und Sortieren wie bei Wert-Ports. Am Node stehen Flow-Ports trotzdem immer oben, vor den Werten.
  5. Reihenfolge am Aufrufer: zuerst der Zusatz-Ausgang, dann exec. exec liest sich damit als „danach weiter“, wie completed an einer Schleife.
  6. Umfang: die Flow-Ports und, seit dem Nachtrag, On behavior. Ein Input-Action-Asset ist nicht Teil dieses Issues, siehe Nicht dabei.

Zu bauen

  • Port-Art flow für deklarierte Ports an Start (Ausgänge) und End (Eingänge). portDefOf liefert dafür einen Port vom Typ exec, ohne Feld zum Eintippen.
  • Run behavior zeigt die Flow-Ports des Start als Flow-Eingänge und die des End als Flow-Ausgänge, unter dem festen exec und über den Werten (execFirst sortiert das schon so).
  • Interpreter, Eingang: run bekommt den betretenen Port schon heute mit (entry). Run behavior gibt ihn im call weiter, und call folgt am Start diesem Port statt fest exec.
  • Interpreter, Ausgang: End merkt sich, über welchen Flow-Eingang es zuletzt betreten wurde. call gibt das neben den Werten zurück, und der Aufrufer folgt erst diesem Ausgang, dann exec.
  • Aufrufstellen nachziehen: Umbenennen und Löschen eines deklarierten Ports ziehen die Kanten an den Run behavior-Nodes schon heute nach (src/core/commands/portCommands.ts). Das muss für Flow-Ports mitlaufen.
  • Palette und Beschreibung von Start, End und Run behavior nennen die Flow-Ports. benchmark/engine-prompt.md und das Wiki (Behaviors) ebenso.

Vorschläge für die Kleinigkeiten (nicht einzeln gefragt)

  • Namen: Ein Flow-Port teilt sich den Namensraum mit den Wert-Ports desselben Nodes. exec bleibt gesperrt.
  • Werte gelten für alle Flow-Ports gemeinsam. Jeder Flow-Eingang von Run behavior übergibt dieselben Wert-Eingänge, und am End gibt es eine Wertliste, nicht eine je Flow-Eingang.
  • Erreicht der Lauf nur den festen exec des End oder gar kein End, feuert kein Zusatz-Ausgang, nur exec.
  • Behavior ohne Start (Einstieg über On start, #230): Es gibt keine Zusatz-Eingänge, weil sie am Start deklariert werden. Zusatz-Ausgänge am End gehen trotzdem.
  • Ein Behavior, das selbst an einem Objekt läuft und nicht aufgerufen wird: Die Zusatz-Ausgänge des Start verhalten sich wie sein exec heute. Beim Bau nachlesen, was das genau ist, und im Wiki festhalten.
  • Art eines Ports nachträglich ändern (Wert zu flow oder zurück): Die Kanten an diesem Port bleiben liegen und werden rot, wie bei jeder anderen Typänderung. Gelöschte Ports hinterlassen Geister-Kanten wie heute.
  • Trace im laufenden Graph: Der gefolgte Zusatz-Ausgang leuchtet wie jede andere Flow-Kante.

Tests (Vorschlag)

  • Unit, Ports: flow deklarieren, umbenennen, löschen und sortieren an Start und End, und Run behavior zeigt dieselben Ports in derselben Reihenfolge. Namensregeln.
  • Unit, Interpreter:
    • Aufruf über exec verhält sich wie heute (Bestand).
    • Aufruf über einen Zusatz-Eingang beginnt nur am gleichnamigen Ausgang.
    • Ein erreichter Zusatz-Eingang am End feuert erst seinen Ausgang, dann exec.
    • Zwei erreichte Eingänge: nur der letzte feuert.
    • Kein End erreicht: nur exec.
    • Verschachtelter Aufruf: Der gemerkte Eingang des inneren End sickert nicht in den äußeren Aufruf durch.
    • In einer Schleife: Jede Runde entscheidet neu.
  • Unit, Commands: Umbenennen und Löschen eines Flow-Ports ziehen die Kanten an den Aufrufstellen nach, ein Undo-Schritt.
  • e2e mit echter Maus im Graph-Modul: Flow-Port im Inspector anlegen, am Run behavior verbinden, im Play prüfen, welcher Zweig gelaufen ist. Dazu ein Screenshot des Nodes mit mehreren Flow-Pins, angesehen.
  • Gegenprobe je Regel.

On behavior

Anlass: Ein Behavior soll sich wie ein Event verwenden lassen. Beispiel „Confirm“: Innen hängen On key down (Space) und On key down (Enter) am End, außen steht überall nur On Confirm und dahinter die Logik. Mit Run behavior geht das nicht, weil ein Aufruf einen Puls am Flow-Eingang braucht und die Events des aufgerufenen Graphs nie feuern.

On behavior ist ein Event-Node ohne Flow-Eingang mit der Einstellung Behavior. Das gewählte Behavior lebt an der Einsatzstelle, solange das äußere Behavior läuft.

Entschieden (Antworten des Users)

  1. Außen feuert nur etwas, wenn ein innerer Puls das End erreicht. Es feuert der Ausgang, der dem zuletzt erreichten Flow-Eingang des End entspricht. Das gilt auch für den festen exec: Er feuert nur, wenn End.exec der zuletzt erreichte war. Ein innerer Puls, der das End nicht erreicht, ist außen unsichtbar. (Anders als bei Run behavior, dessen exec immer feuert.)
  2. Alle inneren Events feuern, wie bei einem Behavior, das direkt am Objekt hängt: Tasten, Maus, On update, On timer, Kollisionen, Animation, State-Events und auch On start, On enable, On disable und On destroy im Takt des äußeren Behaviors.
  3. Alle Variablen des inneren Behaviors leben, solange das äußere läuft, je Einsatzstelle ein eigener Satz. Keep spielt hier keine Rolle. Zwei On behavior-Nodes mit demselben Behavior teilen nichts.
  4. Start feuert nie. Seine Wert-Ports werden zu Dateneingängen von On behavior (getippt oder verbunden), innen am Start lesbar und bei jedem inneren Puls frisch gelesen. Die Wert-Ports des End werden Ausgänge mit den Werten des Pulses, der das End erreicht hat.
  5. Verschachtelung beliebig tief: Ein On behavior darf in einem Behavior stehen, das selbst über On behavior eingesetzt ist. In einem per Run behavior aufgerufenen Behavior bleibt es stumm, wie heute alle Events dort. Ein Kreis (A hört auf B, B auf A) wird als Fehler am Node gemeldet.

Vorschläge für die Kleinigkeiten (nicht einzeln gefragt)

  • Der Node heißt wie sein Behavior: On Confirm, ohne Wahl On behavior. Er liegt in der Palette bei den Events.
  • Der äußere Ausgang feuert nach dem inneren Puls, nicht mittendrin. Erreicht ein innerer Puls das End mehrmals, feuert außen einmal der letzte.
  • Flow-Ports des Start erscheinen an On behavior nicht, weil der Node keine Flow-Eingänge hat.
  • Timer, lokale State Machines und sonstiger Node-Zustand des inneren Behaviors leben wie die Variablen je Einsatzstelle.
  • Kein Feld Order am Node. Die inneren Events tragen ihr eigenes Order und laufen in ihrer Event-Art mit allen anderen mit.
  • Run behavior im inneren Behavior geht wie überall.
  • Gewähltes Behavior ohne End: Der Node warnt, weil er nie feuern kann.
  • Run in editor: Das innere Behavior läuft dort, wo das äußere läuft.
  • Trace: Ist das innere Behavior im Graph-Tab offen, leuchtet es wie ein aufgerufenes.

Zu bauen

  • Node OnBehavior (Event) mit derivePorts: Wert-Ports des Start als Eingänge, exec plus Flow- und Wert-Ports des End als Ausgänge.
  • Laufzeit: Je On behavior-Node einer Instanz ein eigener Interpreter samt Variablen und States für das innere Behavior, rekursiv für dessen eigene On behavior-Nodes. Die Event-Sammlung des BehaviorSystem läuft über alle diese Interpreter.
  • Nach jedem inneren Puls: Wurde das End erreicht, startet am äußeren Node ein Puls am passenden Ausgang mit den Werten des End.
  • Umbenennen und Löschen deklarierter Ports ziehen auch die Kanten an On behavior-Nodes nach.
  • Problem-Meldungen am Node: kein Behavior gewählt, Behavior weg, hört auf sich selbst (auch über Umwege), kein End.

Tests (Vorschlag)

  • Unit: inneres On key down feuert außen; Puls ohne End feuert nicht; letzter End-Eingang gewinnt, exec nur bei End.exec; Werte hinein (frisch je Puls) und heraus; Variablen leben je Einsatzstelle und werden nicht geteilt; On start und On destroy innen im Takt des äußeren; zwei Stufen tief; stumm unter Run behavior; Kreis wird gemeldet und läuft nicht.
  • e2e: „Confirm“ mit zwei Tasten bauen, außen On Confirm, im Play mit echter Tastatur drücken. Screenshot des Nodes, angesehen.
  • Gegenprobe je Regel.

Nicht dabei

  • Input-Action-Asset (Tasten an einer Stelle definieren, Umbelegen, Gamepad). Mit On behavior und den Flow-Ports lässt sich eine Eingabe als Behavior bauen, das sich wie ein Event verwenden lässt. Ob das reicht, zeigt sich am echten Graph. Wenn nicht, ist das Asset ein eigenes Issue.
  • Die Taste als Wert (ein Ausgang key an den Tasten-Events, „Any key“).
  • Mehrere Start- oder End-Nodes je Graph.
  • Ein End, das den inneren Lauf abbricht (echtes Return).
Aus der Zwischenfrage vom 2026-10-02 (bei #216): Der User will Behaviors als eigene Verzweigungs-Nodes bauen, etwa für Eingaben. Dafür reicht der eine Flow-Port an `Start` und `End` nicht. Die sechs offenen Punkte sind vor dem Anlegen per Rückfrage geklärt, siehe *Entschieden*. **Nachtrag vom selben Tag:** Der Node `On behavior` gehört jetzt mit in dieses Issue (Wunsch des Users: „gleich mit rein, alles in einem Wisch“). Seine fünf Punkte sind ebenfalls per Rückfrage geklärt, siehe *`On behavior`*. ## Stand heute - **`Start` und `End` haben je genau einen festen Flow-Port** (`exec`). Deklarieren lassen sich nur Wert-Ports, der Name `exec` ist dafür gesperrt (`isValidPortName` in `src/core/graph/nested.ts`). - **`Run behavior` hat einen Flow-Eingang und einen Flow-Ausgang.** Seine Wert-Ports leitet es aus den deklarierten Ports von `Start` und `End` des gewählten Behaviors ab (`derivePorts` in `src/core/graph/nodes/flow/RunBehavior.ts`). - **Der Aufruf beginnt immer am `exec` des `Start`** (oder an jedem `On start`, wenn es kein `Start` gibt, #230) und geht am Aufrufer immer am `exec` weiter, auch wenn das `End` nie erreicht wurde (`call` in `src/core/graph/GraphInterpreter.ts`). - **`End` beendet den inneren Lauf nicht.** Es legt nur seine Eingangswerte ab, andere Zweige laufen weiter. Wird es mehrmals erreicht, gelten die Werte des letzten Durchgangs. - Es zählt ein `Start` und ein `End` je Graph, ein zweites wird ignoriert. ## Entschieden (Antworten des Users) 1. **Der feste `exec` bleibt immer da und verhält sich wie heute.** `Run behavior` geht am `exec` immer weiter. Die zusätzlichen Ausgänge feuern zusätzlich, wenn ihr Eingang am `End` erreicht wurde. Bestehende Graphen ändern sich nicht. 2. **Wird das `End` in einem Aufruf über mehrere Flow-Eingänge erreicht, feuert nur der zuletzt erreichte.** Ein Aufruf geht also höchstens an einem Zusatz-Ausgang weiter. Das passt zu den Werten, bei denen auch der letzte Durchgang gilt. 3. **Zusatz-Ports am `Start`:** `Run behavior` bekommt je Port einen eigenen Flow-Eingang. Kommt der Puls am Eingang `open` an, beginnt der innere Lauf nur am gleichnamigen Ausgang `open` des `Start`. Der feste `exec` des `Start` feuert nur, wenn der Aufruf über `exec` hereinkam. 4. **Anlegen im Inspector als weitere Art `flow`** in der bestehenden Port-Liste von `Start` und `End`: ein Knopf, eine Liste, Umbenennen, Löschen und Sortieren wie bei Wert-Ports. Am Node stehen Flow-Ports trotzdem immer oben, vor den Werten. 5. **Reihenfolge am Aufrufer:** zuerst der Zusatz-Ausgang, dann `exec`. `exec` liest sich damit als „danach weiter“, wie `completed` an einer Schleife. 6. **Umfang:** die Flow-Ports und, seit dem Nachtrag, `On behavior`. Ein Input-Action-Asset ist nicht Teil dieses Issues, siehe *Nicht dabei*. ## Zu bauen - **Port-Art `flow`** für deklarierte Ports an `Start` (Ausgänge) und `End` (Eingänge). `portDefOf` liefert dafür einen Port vom Typ `exec`, ohne Feld zum Eintippen. - **`Run behavior`** zeigt die Flow-Ports des `Start` als Flow-Eingänge und die des `End` als Flow-Ausgänge, unter dem festen `exec` und über den Werten (`execFirst` sortiert das schon so). - **Interpreter, Eingang:** `run` bekommt den betretenen Port schon heute mit (`entry`). `Run behavior` gibt ihn im `call` weiter, und `call` folgt am `Start` diesem Port statt fest `exec`. - **Interpreter, Ausgang:** `End` merkt sich, über welchen Flow-Eingang es zuletzt betreten wurde. `call` gibt das neben den Werten zurück, und der Aufrufer folgt erst diesem Ausgang, dann `exec`. - **Aufrufstellen nachziehen:** Umbenennen und Löschen eines deklarierten Ports ziehen die Kanten an den `Run behavior`-Nodes schon heute nach (`src/core/commands/portCommands.ts`). Das muss für Flow-Ports mitlaufen. - **Palette und Beschreibung** von `Start`, `End` und `Run behavior` nennen die Flow-Ports. `benchmark/engine-prompt.md` und das Wiki (*Behaviors*) ebenso. ## Vorschläge für die Kleinigkeiten (nicht einzeln gefragt) - **Namen:** Ein Flow-Port teilt sich den Namensraum mit den Wert-Ports desselben Nodes. `exec` bleibt gesperrt. - **Werte gelten für alle Flow-Ports gemeinsam.** Jeder Flow-Eingang von `Run behavior` übergibt dieselben Wert-Eingänge, und am `End` gibt es eine Wertliste, nicht eine je Flow-Eingang. - **Erreicht der Lauf nur den festen `exec` des `End` oder gar kein `End`,** feuert kein Zusatz-Ausgang, nur `exec`. - **Behavior ohne `Start`** (Einstieg über `On start`, #230): Es gibt keine Zusatz-Eingänge, weil sie am `Start` deklariert werden. Zusatz-Ausgänge am `End` gehen trotzdem. - **Ein Behavior, das selbst an einem Objekt läuft** und nicht aufgerufen wird: Die Zusatz-Ausgänge des `Start` verhalten sich wie sein `exec` heute. Beim Bau nachlesen, was das genau ist, und im Wiki festhalten. - **Art eines Ports nachträglich ändern** (Wert zu `flow` oder zurück): Die Kanten an diesem Port bleiben liegen und werden rot, wie bei jeder anderen Typänderung. Gelöschte Ports hinterlassen Geister-Kanten wie heute. - **Trace im laufenden Graph:** Der gefolgte Zusatz-Ausgang leuchtet wie jede andere Flow-Kante. ## Tests (Vorschlag) - **Unit, Ports:** `flow` deklarieren, umbenennen, löschen und sortieren an `Start` und `End`, und `Run behavior` zeigt dieselben Ports in derselben Reihenfolge. Namensregeln. - **Unit, Interpreter:** - Aufruf über `exec` verhält sich wie heute (Bestand). - Aufruf über einen Zusatz-Eingang beginnt nur am gleichnamigen Ausgang. - Ein erreichter Zusatz-Eingang am `End` feuert erst seinen Ausgang, dann `exec`. - Zwei erreichte Eingänge: nur der letzte feuert. - Kein `End` erreicht: nur `exec`. - Verschachtelter Aufruf: Der gemerkte Eingang des inneren `End` sickert nicht in den äußeren Aufruf durch. - In einer Schleife: Jede Runde entscheidet neu. - **Unit, Commands:** Umbenennen und Löschen eines Flow-Ports ziehen die Kanten an den Aufrufstellen nach, ein Undo-Schritt. - **e2e mit echter Maus** im Graph-Modul: Flow-Port im Inspector anlegen, am `Run behavior` verbinden, im Play prüfen, welcher Zweig gelaufen ist. Dazu ein Screenshot des Nodes mit mehreren Flow-Pins, angesehen. - Gegenprobe je Regel. ## `On behavior` Anlass: Ein Behavior soll sich wie ein Event verwenden lassen. Beispiel „Confirm“: Innen hängen `On key down (Space)` und `On key down (Enter)` am `End`, außen steht überall nur `On Confirm` und dahinter die Logik. Mit `Run behavior` geht das nicht, weil ein Aufruf einen Puls am Flow-Eingang braucht und die Events des aufgerufenen Graphs nie feuern. `On behavior` ist ein Event-Node ohne Flow-Eingang mit der Einstellung *Behavior*. Das gewählte Behavior lebt an der Einsatzstelle, solange das äußere Behavior läuft. ### Entschieden (Antworten des Users) 1. **Außen feuert nur etwas, wenn ein innerer Puls das `End` erreicht.** Es feuert der Ausgang, der dem zuletzt erreichten Flow-Eingang des `End` entspricht. Das gilt auch für den festen `exec`: Er feuert nur, wenn `End.exec` der zuletzt erreichte war. Ein innerer Puls, der das `End` nicht erreicht, ist außen unsichtbar. (Anders als bei `Run behavior`, dessen `exec` immer feuert.) 2. **Alle inneren Events feuern**, wie bei einem Behavior, das direkt am Objekt hängt: Tasten, Maus, `On update`, `On timer`, Kollisionen, Animation, State-Events und auch `On start`, `On enable`, `On disable` und `On destroy` im Takt des äußeren Behaviors. 3. **Alle Variablen des inneren Behaviors leben, solange das äußere läuft, je Einsatzstelle ein eigener Satz.** `Keep` spielt hier keine Rolle. Zwei `On behavior`-Nodes mit demselben Behavior teilen nichts. 4. **`Start` feuert nie.** Seine Wert-Ports werden zu Dateneingängen von `On behavior` (getippt oder verbunden), innen am `Start` lesbar und bei jedem inneren Puls frisch gelesen. Die Wert-Ports des `End` werden Ausgänge mit den Werten des Pulses, der das `End` erreicht hat. 5. **Verschachtelung beliebig tief:** Ein `On behavior` darf in einem Behavior stehen, das selbst über `On behavior` eingesetzt ist. In einem per `Run behavior` aufgerufenen Behavior bleibt es stumm, wie heute alle Events dort. Ein Kreis (A hört auf B, B auf A) wird als Fehler am Node gemeldet. ### Vorschläge für die Kleinigkeiten (nicht einzeln gefragt) - **Der Node heißt wie sein Behavior:** `On Confirm`, ohne Wahl `On behavior`. Er liegt in der Palette bei den Events. - **Der äußere Ausgang feuert nach dem inneren Puls,** nicht mittendrin. Erreicht ein innerer Puls das `End` mehrmals, feuert außen einmal der letzte. - **Flow-Ports des `Start`** erscheinen an `On behavior` nicht, weil der Node keine Flow-Eingänge hat. - **Timer, lokale State Machines und sonstiger Node-Zustand** des inneren Behaviors leben wie die Variablen je Einsatzstelle. - **Kein Feld `Order` am Node.** Die inneren Events tragen ihr eigenes `Order` und laufen in ihrer Event-Art mit allen anderen mit. - **`Run behavior` im inneren Behavior** geht wie überall. - **Gewähltes Behavior ohne `End`:** Der Node warnt, weil er nie feuern kann. - **Run in editor:** Das innere Behavior läuft dort, wo das äußere läuft. - **Trace:** Ist das innere Behavior im Graph-Tab offen, leuchtet es wie ein aufgerufenes. ### Zu bauen - Node `OnBehavior` (Event) mit `derivePorts`: Wert-Ports des `Start` als Eingänge, `exec` plus Flow- und Wert-Ports des `End` als Ausgänge. - Laufzeit: Je `On behavior`-Node einer Instanz ein eigener Interpreter samt Variablen und States für das innere Behavior, rekursiv für dessen eigene `On behavior`-Nodes. Die Event-Sammlung des `BehaviorSystem` läuft über alle diese Interpreter. - Nach jedem inneren Puls: Wurde das `End` erreicht, startet am äußeren Node ein Puls am passenden Ausgang mit den Werten des `End`. - Umbenennen und Löschen deklarierter Ports ziehen auch die Kanten an `On behavior`-Nodes nach. - Problem-Meldungen am Node: kein Behavior gewählt, Behavior weg, hört auf sich selbst (auch über Umwege), kein `End`. ### Tests (Vorschlag) - **Unit:** inneres `On key down` feuert außen; Puls ohne `End` feuert nicht; letzter End-Eingang gewinnt, `exec` nur bei `End.exec`; Werte hinein (frisch je Puls) und heraus; Variablen leben je Einsatzstelle und werden nicht geteilt; `On start` und `On destroy` innen im Takt des äußeren; zwei Stufen tief; stumm unter `Run behavior`; Kreis wird gemeldet und läuft nicht. - **e2e:** „Confirm“ mit zwei Tasten bauen, außen `On Confirm`, im Play mit echter Tastatur drücken. Screenshot des Nodes, angesehen. - Gegenprobe je Regel. ## Nicht dabei - **Input-Action-Asset** (Tasten an einer Stelle definieren, Umbelegen, Gamepad). Mit `On behavior` und den Flow-Ports lässt sich eine Eingabe als Behavior bauen, das sich wie ein Event verwenden lässt. Ob das reicht, zeigt sich am echten Graph. Wenn nicht, ist das Asset ein eigenes Issue. - **Die Taste als Wert** (ein Ausgang `key` an den Tasten-Events, „Any key“). - **Mehrere `Start`- oder `End`-Nodes je Graph.** - **Ein `End`, das den inneren Lauf abbricht** (echtes Return).
meleki changed title from Behavior: mehrere Flow-Ports an Start und End to Behavior: mehrere Flow-Ports an Start und End, und der Event-Node `On behavior` 2026-10-02 18:58:27 +02:00
admin added this to the Development project 2026-10-02 18:59:22 +02:00
admin moved this to Next in Development on 2026-10-02 18:59:25 +02:00
Author
Owner

Gebaut wie im Issue festgelegt, beide Teile in einem Commit.

Was sich ändert

  • Port-Art Flow: + Input am Start und + Output am End bieten jetzt auch Flow an (Antwort 4). Am Node stehen Flow-Ports über den Werten.
  • Run behavior:
    • Ein Flow-Port des Start wird ein weiterer Flow-Eingang. Ein Aufruf über open beginnt innen nur am Ausgang open (Antwort 3).
    • Ein Flow-Port des End wird ein weiterer Flow-Ausgang. Zuerst feuert der zuletzt erreichte, danach exec (Antworten 2 und 5). exec feuert weiterhin immer (Antwort 1).
  • On <Name>: Jedes andere Behavior mit End-Node steht in der Palette zusätzlich als Event.
    • Das gehörte Behavior läuft am Node mit allen eigenen Events (Antwort 2) und einem eigenen Satz Variablen je Node (Antwort 3).
    • Außen feuert der Ausgang, über den das End zuletzt erreicht wurde, exec nur bei End.exec (Antwort 1).
    • Die Wert-Ports des Start sind Eingänge des Nodes, die des End Ausgänge. Das Start selbst feuert dort nie (Antwort 4).
    • Verschachtelung geht beliebig tief. Unter Run behavior bleibt ein On behavior stumm. Ein Kreis meldet am Node „A behavior cannot listen to itself“ und wird nicht gestartet (Antwort 5).
  • Der Anlass „Confirm“: Innen hängen zwei On key down (Space, Enter) am Flow-Port pressed des End. Außen steht nur On Confirm mit dem Ausgang pressed.

Was ich selbst festgelegt habe

  • On behavior hat kein Feld Order. Die inneren Events tragen ihr eigenes.
  • Der äußere Ausgang feuert erst, wenn der innere Ablauf durch ist. Erreicht er das End zweimal, feuert außen einmal der letzte.
  • Ohne End-Node steht ein Behavior nicht als On … in der Palette. Ein schon gesetzter Node meldet dann „No End node – never fires“.
  • Ein im laufenden Spiel gelöschter On-Node beendet sein Behavior mit On disable und On destroy.
  • Die Sounds der Entity stoppt nur das Behavior, das am Objekt hängt, nicht ein gehörtes.
  • Flow-Ports gibt es nur an Start und End, nicht an Pack oder Expand.
  • Ein Behavior, das direkt am Objekt läuft: Die Zusatz-Ausgänge seines Start feuern nie, so wie sein exec. Das war oben als „beim Bau nachlesen“ markiert.

Under the hood

  • kinds.ts kennt die Art flow (reist als exec). AddPortsCommand lässt sie nur an Start und End zu.
  • CallResult trägt entry, den betretenen Flow-Eingang. call im GraphInterpreter folgt am Start diesem Port und gibt ein Ending zurück (Port und Werte). Das End merkt sich den Port im Frame des aufgerufenen Graphs, er sickert also nicht nach außen durch.
  • BehaviorSystem.syncHeard hält je On behavior-Node eine weitere Instance mit eigenem Interpreter und eigenen Variablen (host, variables), rekursiv. Nach jedem Puls reicht surface ein erreichtes End an den hörenden Node weiter, und von dort weiter nach oben.
  • namesBehavior fasst Run behavior und On behavior zusammen: Port-Commands, Clipboard, Doppelklick auf den Node.

Tests (auf melektaus-atx)

Gate                     → 215 Files, 3319 Tests, CHECK EXIT 0   (3278 + 41)
e2e 19                   → ALL PASSED – 39 checks   (+4 für Block 19e-ii)
e2e 1-6,17-24,26,36,51   → ALL PASSED – 628 checks
  • Neue Unit-Tests: 19 in tests/core/flow-ports.test.ts, 19 in tests/core/on-behavior.test.ts mit echter Welt, der Rest im Katalog.
  • Vier neue e2e-Checks in Modul 19: Flow-Port per Maus am End anlegen, On Confirm im Graph, der Aufruf über den Zusatz-Ausgang im Play, Enter und Space mit echter Tastatur.
  • 19 Unit-Gegenproben greifen. Eine griff zuerst nicht (gelöschter Node behält seine Instanz), dafür gibt es jetzt einen Test.
  • Beide Browser-Gegenproben greifen.
  • Ein Screenshot angesehen: On Confirm als Event-Node mit exec und pressed, am Aufruf der zweite Flow-Pin über dem ersten.
  • Die e2e-Summe 1680 ist gerechnet (1676 + 4). Volle Suite und Smokes liefen nicht, das macht der CI-Lauf.
  • Nicht im Browser geprüft:
    • Flow-Eingänge am Start, die Verschachtelung, der Kreis und Werte durch On behavior (nur Unit-Tests)
    • der Palette-Eintrag On … und der Doppelklick auf den Node
    • alles nach dem Build
  • Ohne Test: dass die Sounds der Entity weiterlaufen, wenn ein gehörtes Behavior endet.

Nicht dabei

Wie oben: das Input-Action-Asset, die Taste als Wert, mehrere Start- oder End-Nodes und ein End, das den inneren Lauf abbricht.

Commit: 46c620a. Wiki: Behaviors (zwei neue Absätze), Architecture und Development (Summe).

Gebaut wie im Issue festgelegt, beide Teile in einem Commit. ## Was sich ändert - **Port-Art *Flow*:** `+ Input` am `Start` und `+ Output` am `End` bieten jetzt auch *Flow* an (Antwort 4). Am Node stehen Flow-Ports über den Werten. - **`Run behavior`:** - Ein Flow-Port des `Start` wird ein weiterer Flow-Eingang. Ein Aufruf über `open` beginnt innen nur am Ausgang `open` (Antwort 3). - Ein Flow-Port des `End` wird ein weiterer Flow-Ausgang. Zuerst feuert der zuletzt erreichte, danach `exec` (Antworten 2 und 5). `exec` feuert weiterhin immer (Antwort 1). - **`On <Name>`:** Jedes andere Behavior mit `End`-Node steht in der Palette zusätzlich als Event. - Das gehörte Behavior läuft am Node mit allen eigenen Events (Antwort 2) und einem eigenen Satz Variablen je Node (Antwort 3). - Außen feuert der Ausgang, über den das `End` zuletzt erreicht wurde, `exec` nur bei `End.exec` (Antwort 1). - Die Wert-Ports des `Start` sind Eingänge des Nodes, die des `End` Ausgänge. Das `Start` selbst feuert dort nie (Antwort 4). - Verschachtelung geht beliebig tief. Unter `Run behavior` bleibt ein `On behavior` stumm. Ein Kreis meldet am Node „A behavior cannot listen to itself“ und wird nicht gestartet (Antwort 5). - **Der Anlass „Confirm“:** Innen hängen zwei `On key down` (Space, Enter) am Flow-Port `pressed` des `End`. Außen steht nur `On Confirm` mit dem Ausgang `pressed`. ## Was ich selbst festgelegt habe - **`On behavior` hat kein Feld *Order*.** Die inneren Events tragen ihr eigenes. - **Der äußere Ausgang feuert erst, wenn der innere Ablauf durch ist.** Erreicht er das `End` zweimal, feuert außen einmal der letzte. - **Ohne `End`-Node** steht ein Behavior nicht als `On …` in der Palette. Ein schon gesetzter Node meldet dann „No End node – never fires“. - **Ein im laufenden Spiel gelöschter `On`-Node** beendet sein Behavior mit `On disable` und `On destroy`. - **Die Sounds der Entity** stoppt nur das Behavior, das am Objekt hängt, nicht ein gehörtes. - **Flow-Ports gibt es nur an `Start` und `End`**, nicht an `Pack` oder `Expand`. - **Ein Behavior, das direkt am Objekt läuft:** Die Zusatz-Ausgänge seines `Start` feuern nie, so wie sein `exec`. Das war oben als „beim Bau nachlesen“ markiert. ## Under the hood - `kinds.ts` kennt die Art `flow` (reist als `exec`). `AddPortsCommand` lässt sie nur an `Start` und `End` zu. - `CallResult` trägt `entry`, den betretenen Flow-Eingang. `call` im `GraphInterpreter` folgt am `Start` diesem Port und gibt ein `Ending` zurück (Port und Werte). Das `End` merkt sich den Port im Frame des aufgerufenen Graphs, er sickert also nicht nach außen durch. - `BehaviorSystem.syncHeard` hält je `On behavior`-Node eine weitere `Instance` mit eigenem Interpreter und eigenen Variablen (`host`, `variables`), rekursiv. Nach jedem Puls reicht `surface` ein erreichtes `End` an den hörenden Node weiter, und von dort weiter nach oben. - `namesBehavior` fasst `Run behavior` und `On behavior` zusammen: Port-Commands, Clipboard, Doppelklick auf den Node. ## Tests (auf `melektaus-atx`) ``` Gate → 215 Files, 3319 Tests, CHECK EXIT 0 (3278 + 41) e2e 19 → ALL PASSED – 39 checks (+4 für Block 19e-ii) e2e 1-6,17-24,26,36,51 → ALL PASSED – 628 checks ``` - **Neue Unit-Tests:** 19 in `tests/core/flow-ports.test.ts`, 19 in `tests/core/on-behavior.test.ts` mit echter Welt, der Rest im Katalog. - **Vier neue e2e-Checks** in Modul 19: Flow-Port per Maus am `End` anlegen, `On Confirm` im Graph, der Aufruf über den Zusatz-Ausgang im Play, Enter und Space mit echter Tastatur. - **19 Unit-Gegenproben greifen.** Eine griff zuerst nicht (gelöschter Node behält seine Instanz), dafür gibt es jetzt einen Test. - **Beide Browser-Gegenproben greifen.** - **Ein Screenshot angesehen:** `On Confirm` als Event-Node mit `exec` und `pressed`, am Aufruf der zweite Flow-Pin über dem ersten. - Die e2e-Summe **1680** ist gerechnet (1676 + 4). Volle Suite und Smokes liefen nicht, das macht der CI-Lauf. - **Nicht im Browser geprüft:** - Flow-Eingänge am `Start`, die Verschachtelung, der Kreis und Werte durch `On behavior` (nur Unit-Tests) - der Palette-Eintrag `On …` und der Doppelklick auf den Node - alles nach dem Build - **Ohne Test:** dass die Sounds der Entity weiterlaufen, wenn ein gehörtes Behavior endet. ## Nicht dabei Wie oben: das Input-Action-Asset, die Taste als Wert, mehrere `Start`- oder `End`-Nodes und ein `End`, das den inneren Lauf abbricht. Commit: `46c620a`. Wiki: *Behaviors* (zwei neue Absätze), *Architecture* und *Development* (Summe).
admin moved this to Done in Development on 2026-10-02 19:36:43 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#294