Make a call node say why it does nothing, and easier to place
A behavior node that cannot run looked exactly like a healthy one: no start node, no behavior picked, a deleted behavior or a self-call were all silently skipped. The call still had to be forgiving at runtime -- a dangling reference must not abort a game -- so the fix is diagnosis, not an exception: describeProblem() names the one reason, the node draws it in red under its title, and the inspector repeats it where you pick the behavior. A missing end node is deliberately not a problem: a call is always synchronous, and the end node only decides which values come back. Two ways in: a behavior dragged from the asset panel lands in the graph under the pointer, and double-clicking a call node opens the graph it runs. Both reuse machinery that already existed -- the asset panel already starts the drag, and list views already report double clicks. The e2e module needed its assets at the head of the asset list: after 18 modules the list is long enough that a newly appended row scrolls out of view, and the press then lands on the panel behind it, starting no drag at all. That looked exactly like a rejected drop and cost two full runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1d8e6ebea0
commit
c6f907b4e0
12 files changed
+427
-24
No files matched your search
@@ -0,0 +1,109 @@
|
||||
Ein paar Fragen zu behavior als node in einem graph:
|
||||
|
||||
- wenn es keinen Start oder End node gibt, kann man trotztdem das behaviour in einem graph hinzufügen, aber wie läuft dann der flow? (vorallem wenn es keinen start node gibt)
|
||||
- ohne end node: woher weiß der parent graph (behavior) dass das child (sub behavior) "fertig" ist?
|
||||
- drag and drop vom asset inspector wäre auch gut als spwan im graph, ist das möglich?
|
||||
- doppelklick auf node (type behavior) um von dem asset behavior den graph zu öffnen wäre noch gut
|
||||
|
||||
---
|
||||
|
||||
## Beantwortet und umgesetzt
|
||||
|
||||
Deine ersten zwei Punkte waren Fragen, die letzten zwei Wuensche. Die Antworten standen schon
|
||||
im Code — der Mangel war, dass **du sie nicht sehen konntest**. Genau das ist jetzt behoben.
|
||||
|
||||
### 1. Ohne Start-Node: wie laeuft der Flow?
|
||||
|
||||
**Gar nicht — der Aufruf wird uebersprungen, und der Fluss laeuft am `exec`-Ausgang weiter.**
|
||||
Ohne Start-Node gibt es keinen Eingang in den Sub-Graphen; der Interpreter bricht den Aufruf ab
|
||||
(`if (!start) return {}`) und macht beim Aufrufer weiter. Dasselbe gilt, wenn gar kein Behavior
|
||||
gewaehlt ist oder das gewaehlte geloescht wurde. Das ist Absicht: ein toter Verweis soll kein
|
||||
Spiel abbrechen.
|
||||
|
||||
**Das war aber still, und still ist hier falsch.** Es ist derselbe Fehlgriff wie damals beim
|
||||
`Run in editor`-Schalter: der Node sah gesund aus und tat nichts. Ein Aufruf, der nichts tun
|
||||
*kann*, sagt es jetzt selbst — rote Zeile auf dem Node, roter Rand, dieselbe Zeile im Inspector:
|
||||
|
||||
| Lage | was der Node sagt |
|
||||
|---|---|
|
||||
| kein Behavior gewaehlt | `No behavior picked` |
|
||||
| Behavior geloescht | `That behavior is gone` |
|
||||
| Behavior ohne Start-Node | `No start node – does nothing` |
|
||||
| Behavior zeigt auf sich selbst | `A behavior cannot run itself` |
|
||||
|
||||
Einfuegen kann man ein Behavior ohne Start-Node weiterhin — das ist der normale Weg beim Bauen
|
||||
(erst den Aufruf setzen, dann den Sub-Graphen fuellen). Es sieht nur nicht mehr fertig aus.
|
||||
|
||||
### 2. Ohne End-Node: woher weiss der Parent, dass das Child fertig ist?
|
||||
|
||||
**Die Frage stellt sich nicht: ein Aufruf ist immer synchron.** Der aufrufende Node kehrt erst
|
||||
zurueck, wenn der Fluss im Sub-Graphen ausgelaufen ist — "fertig" ist kein Signal, sondern das
|
||||
Ende der Ausfuehrung. Der End-Node hat damit nichts zu tun; er entscheidet nur, **welche Werte**
|
||||
zurueckkommen. Ohne ihn kommt schlicht nichts zurueck, alles andere ist unveraendert.
|
||||
|
||||
Deshalb wird ein fehlender End-Node auch **nicht** als Mangel angezeigt — das waere eine
|
||||
Warnung vor etwas Erlaubtem. Ein eigener Test haelt das fest: der Sub-Graph loggt `sub`, der
|
||||
Aufrufer danach `after`, und das Ergebnis ist `['sub', 'after']` — nicht umgekehrt und nicht
|
||||
verschraenkt.
|
||||
|
||||
### 3. Drag & Drop aus dem Asset-Panel in den Graphen
|
||||
|
||||
**Gebaut.** Ein Behavior aus der Asset-Liste in den Graphen gezogen wird zu einem Aufruf-Node,
|
||||
und zwar **dort, wo du losgelassen hast** (unter dem Zeiger zentriert, nicht rechts-unter ihm).
|
||||
Waehrend des Ziehens zeigt ein Umriss die Landestelle. Ins **eigene** Behavior gezogen wird
|
||||
abgelehnt — mit Meldung, statt einen Node zu erzeugen, der beim Laufen einen Fehler wirft.
|
||||
|
||||
Das war billig, weil der Mechanismus schon existierte: `startDrag` feuert im Asset-Panel
|
||||
laengst fuer jedes platzierbare Asset, und die Szenen-Ansicht ist bereits ein Drop-Ziel. Neu
|
||||
ist nur, dass der Graph-Canvas jetzt auch eines ist.
|
||||
|
||||
### 4. Doppelklick auf einen Behavior-Node oeffnet dessen Graph
|
||||
|
||||
**Gebaut.** Doppelklick auf einen Aufruf-Node zeigt den Graphen des Behaviors, das er ausfuehrt.
|
||||
Auch das nutzt vorhandene Mechanik (`pressCount`, dieselbe Erkennung wie in den Listen); der
|
||||
Node waehlt einfach das Asset aus, und der Graph-Tab folgt der Selektion.
|
||||
|
||||
Zusammen mit Punkt 1 schliesst sich damit ein Kreis: der Node sagt *"No start node"*, ein
|
||||
Doppelklick bringt dich in den Graphen, und dort legst du den Start-Node an.
|
||||
|
||||
## Belegt
|
||||
|
||||
```
|
||||
PASS a behavior dragged from the asset panel becomes a call node
|
||||
PASS and it lands under the pointer, not at some default spot
|
||||
PASS a behavior without a start node can be added just the same
|
||||
PASS and the node says why it does nothing, instead of failing silently – "No start node – does nothing"
|
||||
PASS a healthy call carries no such warning
|
||||
PASS dropping a behavior into its own graph is refused, out loud
|
||||
PASS double-clicking a call node opens the behavior it runs
|
||||
```
|
||||
|
||||
Gegenprobe gefahren: ohne die Diagnose fallen beide neuen Unit-Tests. Der zweite war beim
|
||||
ersten Versuch wertlos — er wollte zeigen, dass der Node **neu gezeichnet** wird, wenn der
|
||||
Mangel entsteht, prueft das aber an einem Behavior mit Ports, wo sich die Signatur ohnehin
|
||||
aendert. Jetzt haengt er an einem Behavior ganz ohne Ports, wo sich wirklich nur der Mangel
|
||||
aendert.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| volle Suite, remote | **ALL PASSED – 387 Checks** (379 + 8 neue), 0 FAIL |
|
||||
| `npm run check` lokal | gruen, **527 Tests** (+3) |
|
||||
|
||||
## Ein Fehlschlag, der zweimal dasselbe war
|
||||
|
||||
Der erste Drag klappte, die beiden folgenden nicht — und zwar **nur im vollen Lauf**, allein
|
||||
war das Modul gruen. Ich habe zuerst die Drop-Punkte verdaechtigt (falsch: sie lagen in der
|
||||
Flaeche) und dann die Reihenfolge der Module (falsch: die letzten drei reichten nicht zum
|
||||
Reproduzieren). Erst eine Messung in der Check-Nachricht hat es gezeigt: die Asset-Zeile lag
|
||||
bei **y = 449** statt 293 — nach 18 Modulen ist die Liste so lang, dass die zuletzt
|
||||
angehaengten Behaviors **aus dem sichtbaren Bereich gescrollt** waren. Der Druck landete auf
|
||||
dem Panel dahinter, es startete gar kein Drag, und das sah exakt aus wie eine Ablehnung.
|
||||
|
||||
Die Testdaten liegen jetzt am **Anfang** der Liste. `__gm.dragPayload()` als neuer Hook
|
||||
unterscheidet die beiden Faelle kuenftig direkt: *abgelehnt* hat einen Drag, *nie angekommen*
|
||||
keinen.
|
||||
|
||||
Ein Reparaturversuch am Test-Hook selbst (`rowGlobal` sollte `null` liefern, wenn der
|
||||
Scroll-Container die Zeile abschneidet) habe ich **wieder zurueckgenommen** — meine Pruefung
|
||||
ueber die Masken-Bounds lieferte `null` auch fuer klar sichtbare Zeilen und hat den Lauf
|
||||
sofort im ersten Modul zerlegt. Lieber ein Hook, der schweigt, als einer, der falsch redet.
|
||||
@@ -1,6 +0,0 @@
|
||||
Ein paar Fragen zu behavior als node in einem graph:
|
||||
|
||||
- wenn es keinen Start oder End node gibt, kann man trotztdem das behaviour in einem graph hinzufügen, aber wie läuft dann der flow? (vorallem wenn es keinen start node gibt)
|
||||
- ohne end node: woher weiß der parent graph (behavior) dass das child (sub behavior) "fertig" ist?
|
||||
- drag and drop vom asset inspector wäre auch gut als spwan im graph, ist das möglich?
|
||||
- doppelklick auf node (type behavior) um von dem asset behavior den graph zu öffnen wäre noch gut
|
||||
Reference in new issue
Block a user