Describe onFrame, the frame queue of the render loop (#129)

Architecture was missing the rule a drag now follows: work that costs
more per pointer event than a frame is worth is collected per key and
run once, before the frame it belongs in.

Tests: none, wiki text only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
adminandClaude Opus 5 committed 2026-09-20 21:55:24 +02:00
1 parent 919834f432
commit 84680ba1cf
1 file changed
+10
+10
@@ -204,6 +204,16 @@ just as well on a screen that froze a minute ago. The drawn-frame counter is the
`__gm.renderStats()` gives it, and step 33 is the check that the editor really does go quiet and
really does wake up again.
**Work that costs more per pointer event than a frame is worth waits for the frame** —
`onFrame(key, fn)` runs `fn` once before the next frame is drawn, however often it was asked for
under that key, and `cancelFrameWork(key)` drops it. A drag writes the model on every pointer
move, and a model event rebuilds the panels, the run in the editor and any picture drawn from the
model: on a busy scene that measured 36 ms per pointer move, while a mouse reports around 125
times a second and the screen takes 60. Without coalescing the pointer outruns the drawing and the
editor only catches up once the hand stops. The work runs **before** `app.render()`, not after,
so what it writes is in the frame it waited for. The Vector art tab's drag uses it; while the
gesture runs, its own copy of the rings is the truth and it never reads the model back.
The toolbar's right edge shows the frame rate in edit and play mode alike; `__gm.fps()` exposes
the same number to tests. It counts **drawn** frames over the time the renderer was **awake**:
idle seconds are not slow seconds, so the readout answers "how smooth is it while it moves" and