arthur/docs/one-grid-plan.md

67 lines
3.6 KiB
Markdown
Raw Permalink Normal View History

# The editing grid is the symbol's own frames
## What was wrong
Every number a person authors — a span, a `:time :at`, a key, a cut — is in the
frame space of the symbol it lives in (`docs/time.md`, and that part is right).
The timeline, though, drew its ruler in OUTPUT frames: `clip/output-frames`, the
transport's length. In a 12fps project holding 30fps symbols those two spaces sit
at a ratio of 2.5, so:
* a clip at symbol frame 31 was drawn at ruler frame 12.4 — **no clip edge landed
on a frame mark**, because almost none of them can;
* a gesture measured in ruler frames had to be multiplied into the symbol's
frames and rounded (`nest/dragged`), so dragging one ruler frame moved the clip
2 or 3 symbol frames — **0.8 or 1.2 ruler frames, never the 1 the pointer
said**. That is the jumpiness;
* the preview drew the gesture's own number of ruler frames while the commit
wrote the rounded one, so **the ghost sat somewhere the settled clip did not**;
* before the rounding was added, the fraction went into the document and every
later edge edit on that clip was refused for ever (`span/*` refuses a
fractional edge, as it should).
One cause, four symptoms. None of them is an edge case to patch.
## The model
1. **A symbol's own frames are the only coordinate anything authored lives in.**
Unchanged.
2. **The editor edits in the open symbol's frames.** The ruler, the marks, the
playhead's position on it, every pointer→frame answer, every drop frame and
every drag delta are the open symbol's frames. No multiplication anywhere in
the gesture path, so no rounding and nothing fractional to refuse.
3. **The output grid is playback's alone** — the clock, the audio mix, export,
and the frame the stage draws. Exactly two pure functions cross between them
and nothing else does:
* `clip/shown-frame clip sid f` — which of `sid`'s frames output frame `f`
shows (`cadence/frame`: the latest at or before it).
* `clip/first-output-frame clip sid n` — the output frame that first shows
symbol frame `n`; the inverse, for seeking from the ruler.
4. `nest/inside`, `nest/placement`, `nest/spans` and the gestures take the
subject symbol's OWN frame. They used to take an output frame and multiply it
secretly, which is what made every caller's units a guess. A caller holding
the playhead converts with `clip/shown-frame`, at its own edge, visibly.
## The gestures
5. **One pointer→frame function** for the whole timeline, `frame-under`. A drag's
delta is the difference of two of its answers, never a pixel ratio rounded
separately — so the preview and the commit are the same number by
construction.
6. **The junction between two clips is one handle with one meaning**: roll. It
moves the end of the left clip and the start of the right one together, which
is `span/roll`, which is already nothing but `resize-out` then `resize-in`.
The three 4px-wide zones it used to pick between — trim-left, roll,
trim-right, inside twelve pixels — were the "it just picks one" the handle
was accused of. An edge that is not shared still has its own in/out handles.
## Audio goes with the picture it belongs to
A take's sound lived inside the take symbol, so placing the take brought it and
placing the FACE the take is made of brought nothing. A symbol now says what it
sounds like — `:audio`, a sound source — and placing one places a linked audio
node beside the clip. Detection sets it on the face it extracts, which is the
automatic link; `::ui/link-audio` sets or clears it by hand, which is the manual
one. `:linked-to` on the audio node already existed and already follows a moved
picture.