From 6471c446dfde0fcbbc10613305153725f776602a Mon Sep 17 00:00:00 2001 From: th Date: Mon, 20 Apr 2026 21:52:12 +0200 Subject: [PATCH] docs: testing walkthrough for the macro-clips feature set Covers the end-to-end flows per slice: markers (m shortcut + scrub- ruler interactions), script tracks/frames (open dialog, action types, forward-only firing rules), button clip creation and drag-to-track, ButtonInstance dialog (label, onClick, disabled, transitions), canvas runtime (pointer state machine, drag-out cancel behavior, scripted state flips), transitions (matched layer blend vs crossfade, easing), the DSL language reference with examples, a quick sanity pass for the HTML export runtime, and which in-app test suites to look for. Also documents the two known limitations (no in-app button state authoring, scripts not baked into the server PNG/MP4 render) and a small devtools cheat sheet for poking the pinia store directly. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/macro-clips-testing.md | 244 ++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 docs/macro-clips-testing.md diff --git a/docs/macro-clips-testing.md b/docs/macro-clips-testing.md new file mode 100644 index 0000000..4ad9274 --- /dev/null +++ b/docs/macro-clips-testing.md @@ -0,0 +1,244 @@ +# Macro Clips & Scripts — Testing Guide + +Eine Walkthrough für die Features aus `docs/macro-clips-and-scripts.md`. +Start: App mit `npm run dev`, leeres Projekt öffnen („New Project" im +Welcome-Dialog). + +--- + +## 1. Marker + +**Ziel:** Sprungziele auf der Haupt-Timeline setzen und benennen. + +1. Playhead an eine beliebige Stelle ziehen (z. B. t = 2 s). +2. `m` drücken → ein Marker wird an der Playhead-Position angelegt und ein + Rename-Prompt öffnet sich. Namen eingeben (z. B. `intro`), `Enter`. +3. Marker erscheint als kleine Fahne oben auf der Scrub-Ruler. +4. **Interaktionen am Marker:** + - Einfacher Klick → Playhead springt dort hin. + - Drag → Marker zeitlich verschieben. + - Doppelklick → Rename. + - Marker anwählen, `Backspace`/`Delete` → löscht ihn. `Esc` → entauswählt. + +**Erwartung:** +- Mehrere Marker bleiben zeitlich sortiert. +- Zweiter Marker mit gleichem Namen bekommt automatisch Suffix (`intro 2`). +- Namen müssen Scene-weit unique sein (Rename zeigt Fehler-Dialog bei + Kollision und öffnet den Prompt erneut). + +--- + +## 2. Script-Tracks & Action-Frames + +**Ziel:** Zeit-gebundene Aktionen definieren, die bei Playback feuern. + +1. Im Timeline-Header die **Code-Taste** (``-Icon) klicken → ein neuer + Script-Track wird angelegt (kleinere Zeile als Clip-Tracks). +2. Auf der leeren Script-Lane an beliebiger Zeitposition klicken → ein + neuer Action-Frame wird erstellt und der **ScriptFrameDialog** öffnet + sich. +3. Im Dialog **Add action** drücken → ein Dropdown zeigt alle Action-Typen. + - Beispiel: `Pause` auswählen → nur Typ, keine Params nötig. + - Weitere Action hinzufügen: `Jump to marker` → Marker-Name aus dem + Dropdown wählen (dafür muss aus Schritt 1 ein Marker existieren). +4. Dialog schließen mit **Done**. +5. Mehrere Actions pro Frame sind erlaubt — die Zahl rechts neben dem + Frame-Dot zeigt deren Anzahl. + +**Testen:** +- Playhead VOR den Action-Frame ziehen, dann `Space` (Play). +- Playback läuft, und **genau wenn der Playhead über den Frame hinausgeht**, + feuern die Actions in Listen-Reihenfolge. +- Beispiel `pause + jumpToMarker intro` → Playback pausiert und + Playhead springt zum `intro`-Marker. + +**Erwartung:** +- Beim Scrubben (Ziehen des Playheads oder Marker-Klick) feuern + **keine** Actions. +- Beim Loop-Wrap (von `playbackOut` zurück nach `playbackIn`) feuern + ebenfalls keine Actions. +- Rückwärtsbewegen der Zeit feuert nichts. + +--- + +## 3. Button-Clips erzeugen und platzieren + +**Ziel:** Einen klickbaren Button definieren, auf die Stage bringen und +onClick-Actions hinterlegen. + +1. In der Asset-Sidebar den Abschnitt **Buttons** → `+` klicken. Namen + eingeben (z. B. `PlayButton`), `Enter`. +2. Der Button erscheint in der Liste mit einem Cursor-Icon. Die 4 States + sind automatisch als bunte Rects vorausgefüllt + (blau / hellblau / dunkelblau / grau). +3. Button-Clip aus der Sidebar auf eine Clip-Track ziehen (Drag-and-Drop). + - Wenn keine Clip-Track existiert, in den Timeline-Bereich unter den + Tracks droppen → neue Clip-Track entsteht automatisch. +4. Auf der Clip-Track erscheint ein 4-Zellen-Block (`N H P D`) an der + Drop-Position. +5. Auf dem Canvas erscheint der Button (standardmäßig in der Stage-Mitte) + — wenn der Playhead ≥ Instanz-Startzeit. + +**Button editieren:** +1. Auf den 4-Zellen-Block klicken → **ButtonInstanceDialog** öffnet sich. +2. **Label** vergeben (z. B. `play`) — wichtig, weil: + - Im DSL über `btn:play` referenzierbar. + - Im Dropdown von `Set button state`-Actions sichtbar. +3. **On click** → Actions definieren (z. B. `Play` und `Jump to marker intro`). +4. **Start disabled** aktivieren → Button startet grau/schraffiert, + reagiert nicht auf Klicks. +5. **Done**. + +--- + +## 4. Button-Runtime auf der Stage testen + +**Voraussetzung:** Ein Button ist platziert und der Playhead ist auf +oder nach dessen Startzeit. + +1. Maus über den Button bewegen → Farbe wechselt zu *hellblau* (`hover`). +2. Maus-Down → Farbe wird *dunkelblau* (`pressed`). +3. Maus-Up (immer noch im Button) → `onClick`-Actions feuern; State geht + zurück zu `hover`. +4. Maus-Down und **rausziehen** vor dem Maus-Up → kein `onClick`, + State kehrt zu `normal` zurück (Standard-Browser-Button-Verhalten). +5. Disabled-Button hat keine Hover-/Press-Reaktion, ignoriert Klicks. + +**Skript-getriggert:** +- In einem ScriptFrame eine `Set button state`-Action mit Target = Button-Label + und state = `pressed` anlegen. +- Beim Playback überqueren → der Button schaltet visuell in `pressed`, + ohne dass der User hovert. +- `Set button disabled` / `Enable` toggelt den Disabled-Flag zur Laufzeit. + +--- + +## 5. Transitions zwischen States + +**Ziel:** Glatter visueller Übergang zwischen States statt hartem Wechsel. + +1. ButtonInstance-Dialog öffnen (4-Zellen-Block klicken). +2. Unter **Transitions** → `+ Add transition`. +3. Zeile: `normal → hover`, Duration `0.15`, Easing `easeOut`. +4. Weitere Zeile: `hover → normal`, Duration `0.2`, Easing `easeOut`. +5. Done. +6. Auf dem Canvas Maus über den Button → die Farbe **fade**t zwischen + Blau und Hellblau über 150 ms, statt instant zu wechseln. + +**Hinweise:** +- Transitions sind Clip-scoped, d. h. sie gelten für **alle** Instanzen + des Buttons. +- Layer werden zwischen den beiden States per `name` gematcht (beim + Default-Seed heißen alle Face-Layer schlicht `Face` → werden immer + interpoliert). Unmatched Layer faden nur rein/raus (Crossfade). +- Ohne Transition: State-Wechsel ist sofort (Verhalten wie vor Slice 7). + +--- + +## 6. Script-DSL testen + +**Ziel:** Komplexere Logik in einer kompakten Textform statt manuellem +Zusammenklicken mehrerer Actions. + +1. ScriptFrameDialog öffnen (oder ButtonInstanceDialog). +2. **Add action** → Typ `Run script` wählen. +3. Im Textarea: + ``` + // setzt Pause und springt an den intro-Marker + pause + jump @intro + state btn:play pressed + disable btn:play + ``` +4. Done. + +**Testen:** +- Frame überqueren → alle parsed Aktionen feuern in Reihenfolge. +- Falsche Syntax → Warnung erscheint in der Devtools-Konsole + (`[animatr] Script line N: ...`). Die fehlerhafte Zeile wird + übersprungen; valide Zeilen feuern trotzdem. + +**DSL-Referenz (aktueller Sprachumfang):** +``` +// Kommentar (bis Zeilenende) + +play // Playback starten +pause // Playback pausieren +rewind // Playhead → playbackIn (in-point) + +jump 2.5 // Zeit in Sekunden +jump #135 // Frame-Nummer (durch fps geteilt) +jump @markerName // benannter Marker + +state btn:label // ∈ normal|hover|pressed|disabled +enable btn:label +disable btn:label +``` + +--- + +## 7. Export-Runtime prüfen + +**Ziel:** Sicherstellen dass Buttons, Scripts, Marker im exportierten +Projekt genauso funktionieren wie im Editor. + +1. Menü → Export (oder beliebiger Export-Trigger je nach UI). +2. `AnimatrPlayer`-HTML-Export wählen → Datei öffnen im Browser. +3. **Erwartet:** + - Buttons rendern an ihren Positionen, mit Pointer-Reaktion. + - onClick feuert die hinterlegten Aktionen (z. B. `jump @intro` springt + im exportierten Player-Playhead zum Marker). + - Transitions animieren sauber. + - Script-Frames feuern bei natürlichem Playback. +4. Devtools-Konsole im Export-Tab → `window.AnimatrPlayer.__v` sollte + `'6'` ergeben. Cache-Probleme? Hard-Reload mit Shift+Cmd+R / Ctrl+F5. + +--- + +## 8. Runtime-Tests (in-app) + +`Ctrl+Shift+Alt+T` öffnet den Test-Runner. Relevante Suiten: +- `scene store — markers` / `script tracks & frames` / `button clips & instances` +- `actions — evalAction with mock runtime` +- `actions — script type expands via evalAction` +- `scriptDsl — parser` +- `button runtime — state machine + action wiring` +- `scene store — tick fires script frames forward-only` + +Alle sollten grün laufen. + +--- + +## Bekannte Einschränkungen + +- **Kein Button-State-Editor in der UI:** Die 4 States sind beim Seed mit + farbigen Rects vorausgefüllt. Um die Optik anzupassen müsste man + aktuell `scene.buttonClips[i].states[…]` direkt im gespeicherten + Projekt-JSON editieren. Ein eigener Edit-Modus ist geplant, aber + nicht implementiert. +- **Server-Render (PNG-Sequence / MP4)** bakt Script-Actions und + Button-Interaktionen bewusst nicht ein — das wäre keine deterministische + Animation mehr. Scripts wirken nur in der interaktiven + Browser-Laufzeit (Editor + `AnimatrPlayer`-HTML-Export). + +--- + +## Devtools-Cheat-Sheet + +Für Tests ohne UI: +```js +// Pinia store im Devtools: +const s = __pinia.state.value.scene +const store = useSceneStore() // im Vue-Devtools verfügbar + +// Button-Instanz direkt einen bestimmten State geben: +const rt = useButtonRuntime() +rt.setState(instanceId, 'pressed') +rt.reset() + +// Alle Marker sehen: +console.table(store.scene.markers) + +// Alle Button-Instanzen: +console.table(store.scene.buttonInstances) +```