Model palette tracks as typed symbol lanes

This commit is contained in:
Your Name 2026-10-02 10:06:05 -04:00
parent dff23d7994
commit 26fab9392e
20 changed files with 371 additions and 123 deletions

View file

@ -718,28 +718,33 @@ scope does not define resolves to the loud magenta, like any other missing index
### The scope rule
`:palette` on a timeline is a channel like any other:
`:palette-track` points to an ordinary lane symbol. Its clips are instances of
restricted palette symbols: a palette symbol owns no nodes and points at exactly
one project palette.
```clojure
{:frames 91
:palette {:animated? true :interp :hold :keys {0 :day, 48 :dusk, 72 :night}}
:nodes {...}}
{:id :shot :frames 91 :palette :day :palette-track :shot-palettes :nodes {...}}
{:id :shot-palettes :type :palette-track :display :lane :frames 91
:nodes {:day-clip {:kind :instance :source {:symbol :day-palette} ...}
:dusk-clip {:kind :instance :source {:symbol :dusk-palette} ...}}}
{:id :day-palette :type :palette :palette-ref :day :frames 1 :nodes {}}
```
**Absent means inherit** from the instancing context. **Present means this
timeline's content is read in that ramp, and it travels with the timeline** — a
symbol authored against `:night` stays night wherever it is placed. That is
lexical scope, and deliberately: a character with their own palette is a
character, not a decoration of whichever scene they were dropped into.
`:palette` is the symbol's authoring/preview palette. It seeds evaluation only
when that symbol is the viewed root; nested symbols do not replace the root's
choice merely because they were authored under another ramp. When absent, the
project default seeds evaluation.
Composition is the same walk as `:time` — down the instance chain, **innermost
set palette wins**. An enclosing timeline's palette therefore applies to
everything inside it that does not set its own, which is adjustment-layer
behaviour with no adjustment layer in it. It is just scope.
And because it is an ordinary channel, a project switches palette over time with
keys on the root timeline, a child timeline switches on its own, and neither
knows about the other.
Covered clips of the viewed root's palette track override that seed. An
uncovered lane interval is a genuine gap, restoring the authoring palette or
project default. Palette clips use the same trim, roll, slide, claim-time and
undo commands as visual clips; palette code does not duplicate those edits.
Thus palette-track coverage, authoring preview, and project fallback are
separate facts rather than three accidental meanings of one field. There is no
second keyed palette control on symbols or instances: time-varying palette
changes are authored only as clips in the palette lane.
### One index space, partitioned by palette