The shot is as long as somebody said it was
Trim, move and blank, and the decision they all three walked into: is the shot's
length authored, or derived from what is in it?
AUTHORED. `:frames` is the symbol's window — how long the shot IS — and the
occupied extent of its lanes is a different fact, read off the occurrences. A
command grows the window when the caller says `:grow-symbol` and NEVER shrinks
it, so blanking the end of a shot leaves a shot with empty frames at the end.
That is a true statement about what somebody authored, and the alternative is
deleting the last drawing and quietly shortening the film. `finish` had the
right behaviour by accident — `(apply max (:frames sym) ...)` — and now says
which number is which: `needed` is where the occurrences reach, `:frames` is
what was authored, and the only thing that makes the second follow the first is
a caller asking.
The three commands turned out to be one piece of geometry, which is `split`'s.
A `:span` is in the occurrence's OWN frames and `:time` says where those land in
the lane, so moving an edge of an exposure is ONE WRITE to `:span` and `:time`
and `:playback` are never touched. `local` and `edged` are the whole of it, and
split now goes through them too.
trim narrows one edge and moves nothing else. Lengthening is `extend-hold`,
which carries a ripple policy and a shot-length policy because it needs
them; letting trim grow as well would give one gesture two sets of
rules and a way to overlap its neighbour.
move one write to `:time :at`, and a destination that would overlap is
REFUSED rather than rippled. Moving a drawing and re-timing the ones
around it are different intentions, and a move that pushed the rest
would be the second wearing the first one's name. Clear the room first.
blank leaves a gap and does not close it. Wholly inside the range goes,
overlapping an end is trimmed to it, spanning the range is split — the
one case that needs an ID, and it asks for one instead of inventing it.
Because the source clock is untouched, trimming the front of a playing insert
starts it LATER INTO its animation rather than restarting it, which is the
difference between trimming and slipping and the reason they stay two commands.
The test samples the frames it kept and asserts they show what they showed.
Blanking leaves the drawings in the library. A lane does not own its content,
and a drawing whose last exposure is gone is still a drawing somebody made.
Overwrite is now `blank` then `place` and needs no policy argument of its own,
which is why it still is not one.
424 tests, 5,749 assertions. The browser flow trims an exposure at the playhead,
moves it into the gap that made, blanks it, and checks the shot is still as long
as it was authored.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
72b57e3786
commit
76106d36ee
6 changed files with 380 additions and 23 deletions
|
|
@ -444,7 +444,7 @@ and carries its own playback clock, and `node/problems` rejects the old
|
|||
`[:source]` channel. What a lane IS lives in `arthur.domain.symbol` beside the
|
||||
other rules about a node map; `arthur.domain.sequence` holds the commands over
|
||||
one — add lane, place a drawing (new, reused or duplicated), make unique, split,
|
||||
and extend hold. Each is one history step, and each refuses rather than
|
||||
trim, move, blank and extend hold. Each is one history step, and each refuses rather than
|
||||
half-applying. The timeline draws a lane's occurrences as cel blocks on the
|
||||
lane's own row, and offers Make unique only where the selected exposure actually
|
||||
shares its drawing.
|
||||
|
|
@ -472,6 +472,32 @@ Content copies are shallow by default and keep their references to other
|
|||
symbols; `:deep? true` is the explicit copy that shares nothing, so the promise
|
||||
of independence is only made where it is kept.
|
||||
|
||||
THE SHOT LENGTH IS AUTHORED, which is the decision the range commands forced.
|
||||
`:frames` is the symbol's window — how long the shot IS — and the occupied
|
||||
extent of its lanes is a different fact derived from the occurrences. A command
|
||||
grows the window only when the caller says `:grow-symbol`, and never shrinks it:
|
||||
blanking the end of a shot leaves a shot with empty frames at the end, because
|
||||
that is a true statement about what somebody authored, and deriving the window
|
||||
from the extent would make deleting the last drawing quietly shorten the film.
|
||||
`finish` keeps the two numbers apart by name now rather than by a `max` that
|
||||
read like an accident.
|
||||
|
||||
Trim NARROWS one edge and moves nothing else; lengthening is `extend-hold`,
|
||||
which carries the ripple and shot-length policies because it needs them.
|
||||
Move is one write to `:time :at` and REFUSES a destination that would overlap,
|
||||
because moving a drawing and re-timing the ones around it are different
|
||||
intentions — clear the room with `blank` or `trim` first, which is the
|
||||
composition. Blank leaves a gap and does not close it; an exposure wholly inside
|
||||
the range goes, one overlapping an end is trimmed to it, and the one spanning
|
||||
the range is split. Their drawings stay in the library, since a lane does not
|
||||
own its content.
|
||||
|
||||
All three are the same geometry as `split`: a `:span` is in the occurrence's own
|
||||
frames, so moving an edge is one write and `:time` and `:playback` are never
|
||||
touched. That is why trimming the front of a playing insert starts it later into
|
||||
its animation instead of restarting it — the difference between trimming and
|
||||
slipping, and the reason they stay separate commands.
|
||||
|
||||
Correction layers EVALUATE. `channel/problems` used to refuse an `:over` stack
|
||||
and `value-at`/`cursor` used to throw on one; both now read it, and the
|
||||
agreement test that holds the optimized cursor to the specification covers
|
||||
|
|
@ -501,17 +527,23 @@ re-measurement for good; and an incompatible offset threw in the read path,
|
|||
which would have taken the stage down on exactly the case the model says to
|
||||
report.
|
||||
|
||||
Still unbuilt: overwrite as a placement policy (which is now `blank` then
|
||||
`place`, composed inside one transaction), slip source, retime, and deleting
|
||||
reused content. A lane cannot hold AUDIO occurrences — `sequence-problems`
|
||||
requires visual ones, though this document says a lane may hold either and
|
||||
should reject only a mixture.
|
||||
|
||||
What is NOT implemented is a command that produces a layer — the doc's Constant
|
||||
adjustment, Ramp and Return motion — and with it the question of how a view
|
||||
offers those three over a selected range, and how it offers a conflict for
|
||||
resolution. Overwrite, the range and retiming
|
||||
commands (blank, trim, move, slip source, retime) and the exposure-sheet view
|
||||
are also not implemented; a refusal is the current behavior where the model
|
||||
demands an explicit choice nobody has made yet. The suite stands at 414 tests
|
||||
and 5,696 assertions, with `frontend/test/browser/sequence.mjs` driving the
|
||||
demands an explicit choice nobody has made yet. The suite stands at 424 tests
|
||||
and 5,749 assertions, with `frontend/test/browser/sequence.mjs` driving the
|
||||
editor through create, hold, overflow, undo, reuse, make unique, duplicate,
|
||||
split and insert. Rewrite tests that encode superseded behavior rather than
|
||||
preserving behavior to keep them green.
|
||||
split, insert, trim, move and blank. Rewrite tests that encode superseded
|
||||
behavior rather than preserving behavior to keep them green.
|
||||
|
||||
Build small adversarial documents and test their domain operations before
|
||||
expanding the interface:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue