67 lines
3.6 KiB
Markdown
67 lines
3.6 KiB
Markdown
|
|
# 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.
|