arthur/docs/creating-in.md

156 lines
7 KiB
Markdown
Raw Normal View History

2026-10-03 00:39:07 -04:00
# Creating in
Revised 2026-10-02.
Arthur's creation model is a layer list plus a playhead. The primary active row
is the preferred place for a new thing. The playhead decides whether that row is
present in the current occurrence and supplies the frame at which the thing is
created.
This is editor behavior, not document structure. A saved clip has symbols,
instances and spans; it does not have timeline rows or a creation target.
## Selection and the active row
The selection set names the objects affected by copy, delete and transform. Its
primary member is also the active row, analogous to the active layer in a paint
program. There is no second targeting gesture for a user to maintain.
- Clicking a row label, its timeline body, or the same occurrence on the stage
makes that occurrence primary.
- Shift/marquee selection may retain several objects, but only the primary row
anchors creation.
- Clicking blank stage or timeline space returns the active row to the symbol in
the current tab.
- Row disclosure is independent. Selecting or creating never implicitly expands
a row.
The selection does not change merely because the playhead moves. An off-frame
object remains available for copying, deletion and inspection.
## Resolving the active row at the playhead
Resolution starts with the structural destination implied by the primary row:
- A lane row means the lane symbol itself.
- An ordinary symbol-instance row means the symbol placed by that occurrence.
- A non-instance row means the symbol containing that node.
- No row means the symbol in the current tab.
For an ordinary symbol occurrence, the playhead must be within that occurrence's
extent in the current nested context. Extents are tested after walking all parent
time maps and use the half-open interval `[in, out)`. If the preferred occurrence
is not present, resolution walks outward to the nearest parent whose occurrence
is present. A containing lane is therefore the natural fallback from an inactive
cel. If no nested occurrence is present, the current tab is the destination.
The preferred row is retained during fallback. Scrubbing back into its extent
makes it the effective destination again.
A lane differs only in what its row means. It is an insertion surface across its
containing timeline and does not require an existing cel under the playhead. A
cel within the lane is still an ordinary symbol occurrence with an extent.
For `A -> B -> lane C -> cel D`:
- over D, with D primary, creation happens inside D;
- past D but while C is available, creation inserts a new cel in C;
- outside C's containing occurrence but inside B, creation happens inside B;
- outside every nested occurrence, creation happens in A, the current tab.
## What creation does
Once resolved, every creation command follows the destination kind.
### Lane destination
- A new or dropped symbol is instantiated directly in the lane at the playhead.
- Its interval claims that time. Existing cels under the interval are removed or
trimmed by the lane's ordinary claim-time command.
- Beginning a drawing creates a new one-frame drawing symbol in the lane and the
finished shape is a child of that drawing.
- Selecting an existing cel changes the destination from the lane to the symbol
placed by that cel; subsequent symbols and shapes become children there.
2026-10-03 02:15:27 -04:00
Double-clicking a lane creates an empty cel at the playhead; beginning a drawing
creates a drawing cel there. These are the same lane-creation operation with
different payloads. The pointer chooses the lane, never a second creation time.
The resulting cel is selected, so it immediately becomes the preferred target:
drawing again enters that cel's symbol instead of replacing it.
2026-10-03 00:39:07 -04:00
Thus no separate "new cel" versus "add inside" mode is needed. Selecting the
lane header says new cel; selecting a cel says add inside.
### Ordinary symbol destination
- A new symbol is instantiated as a child at the mapped playhead frame.
- A new shape is authored directly in the symbol at that frame.
- Stage coordinates are transformed through the occurrence into the destination
symbol's local coordinates.
### Explicit timeline drop
A timeline drop uses the row and frame under the pointer, not the stored active
row and playhead. Dropping onto a lane therefore always instantiates in that lane
and claims the pointer's interval. A stage drop uses the resolved active row and
the playhead.
Paste, imported symbols and converted footage obey the same resolver as direct
creation. They must not each reconstruct nesting or extent fallback separately.
## Multi-selection and paste
Multi-selection does not create multiple insertion targets. Copy and cut take
the canonical forest of selected roots as one ordered payload; the primary
(last-selected) occurrence alone supplies the preferred row for a later paste.
At paste time that row and the current playhead resolve one effective
destination, and every root in the payload is inserted there in one transaction.
The earliest finite root start is aligned to the destination frame. Other roots
keep their timing offsets, hierarchy, and clipboard order. In an ordinary symbol
the roots may overlap. In a lane every root must have a finite span and the
payload's root spans must not overlap one another; valid spans claim their times
and trim or remove existing cels as a batch. An invalid member refuses the whole
paste rather than inserting a partial payload.
After paste, all new roots form the selection and the final root is primary, so
it becomes the preferred row for the next creation. Pasting one payload into
several selected destinations is intentionally not implicit: that would be a
separate distribute command. Duplicate is also distinct from paste—it stays
beside each source in its original owner and does not consult the playhead or
creation target.
## Palette lanes
Palette lanes use the same row-and-playhead resolution. Their content filter and
transition command remain palette-specific: only palettes and palette
transitions can be inserted there. This is a type restriction, not a second
targeting model.
## Implementation boundary
One pure resolver returns the effective destination:
```clojure
{:kind :lane | :symbol
:sid destination-symbol
:path effective-occurrence-path
:frame destination-local-frame
:matrix destination-to-current-tab-transform}
```
Callers may add the unchanged document as `:clip` or rename `:frame` to `:at`,
but they must not reinterpret the active row. Polygon creation, symbol creation,
stage drops, paste, import and footage conversion all consume this answer.
Explicit timeline drops use the same structural row rule with the row and frame
under the pointer; unlike playhead resolution, an invalid pointer destination is
refused rather than allowed to fall outward.
The invariants are:
1. The primary row is the preferred structural destination.
2. The playhead validates occurrences and supplies creation time.
3. Inactive targets fall outward; selection does not follow them.
4. A lane row inserts a cel, while a cel row enters its symbol.
5. Stage creation uses the playhead; timeline drops use pointer time.