Skip to content

feat(devtools): tape v2 sparse touch track#164

Draft
doodlewind wants to merge 1 commit into
feat/kinetic-scrollerfrom
feat/tape-touch-track
Draft

feat(devtools): tape v2 sparse touch track#164
doodlewind wants to merge 1 commit into
feat/kinetic-scrollerfrom
feat/tape-touch-track

Conversation

@doodlewind

Copy link
Copy Markdown
Collaborator

Part 3/6 of the touch-input series (stacked on #163).

What

  • Tape v2 (framework/src/devtools.ts): sparse touch: [frameIndex, packed[]][] track using the __packTouch wire words. Sparse-by-frame beats RLE for drags and costs zero bytes on idle frames.
    • Recorder ring allocates lazily on the first contact frame — touch-free sessions (every PSP session) pay nothing and still export v:1 byte-identical to pre-touch tapes.
    • Replay owns every input track: v2 tapes drive touches() frame-exact, v1 tapes replay as no-contacts, and live hardware contacts are never leaked into a replay (previously guaranteed by force-dropping touch; now guaranteed with the track).
  • Sim host (hosts/sim/sim.ts): ScriptEvent.touch (level-triggered like hold/analog, [] releases), expansion in scriptToMasks, and touchGlide(x0,y0,x1,y1,t0,t1) — a one-line per-frame glide on the 60 Hz grid for fling journeys. runScenario feeds the third frame argument.
  • CLI (tools/tape.ts): record --touch "f:id,x,y[+id,x,y];f:-"; replay/tree feed all three expanded tracks — incidentally fixing CLI replays silently dropping the analog track.

Tests

6 new devtools cases (sparse export shape, v1 byte-stability, v2 replay + live-leak suppression, round-trip, v1 expansion) + script-expansion/glide cases; tests/sim.test.ts regression green; tsc --noEmit clean.

Unblocks: sim touch journeys for VirtualList/OSK (parts 4–5) and scripted Vita touch goldens (part 6).

🤖 Generated with Claude Code

Tapes recorded only buttons + analog, and replay force-dropped touch
(`touch = undefined`) — touch interactions were unrecordable and
unreplayable, which blocks deterministic testing of any touch UX.

Tape v2 adds a sparse `touch: [frameIndex, packed[]][]` track (contacts vary
per frame mid-drag, so RLE degenerates; idle frames cost zero bytes). The
recorder ring allocates lazily on the first frame that has contacts — every
touch-free session (all of PSP) records exactly as before and still exports
v:1 byte-identical. Replay now owns all three tracks: a v2 tape drives
touches() frame-exact, a v1 tape replays every frame as no-contacts, and
live hardware contacts never leak into either.

hosts/sim: ScriptEvent gains a level-triggered `touch` track (same
convention as hold/analog; [] releases), scriptToMasks expands it to packed
words, and touchGlide() emits a per-frame linear glide on the 60 Hz grid so
a fling is one line in a scenario. runScenario feeds the third frame arg.

tools/tape: record grows --touch "f:id,x,y;f:-" (level-triggered); replay
and tree now feed all three expanded tracks — this also fixes the analog
track being silently dropped in CLI replays.

Tests: sparse export shape, v1 byte-stability, v2 replay determinism +
live-leak suppression, expandTapeTouch round-trip, script touch levels,
touchGlide grid math. Sim suite stays green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant