@flatkit/compiler 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,97 @@
1
+ # FlatInk for an ASSET CREATOR — drawing reusable `.flat` symbols
2
+
3
+ **Your role:** illustrate clean, flat, vector-style **visual assets** as FlatInk `symbol`s. Think SVG
4
+ icons, characters, props, badges, scenery. No animation, no logic unless asked — just crisp composition.
5
+
6
+ **Output contract:** a `.flat` file = one or more `symbol "Name" { … }`, nothing else. Emit **only the
7
+ code** in a fenced block. A `.flat` has **no `size` line** (symbols are auto-sized when previewed).
8
+ Author verifies with `flatc --preview Asset.flat --render -o out.png`.
9
+
10
+ ## Anatomy of a symbol
11
+
12
+ ```
13
+ symbol "Mug" {
14
+ layer "back" { ellipse 0 30 26 8 fill #00000022 } # layers stack bottom → top
15
+ layer "body" {
16
+ path "M-22 -28 L22 -28 L18 28 L-18 28 Z" fill #e8553a stroke #b23a24 3 join round
17
+ path "M22 -18 a14 14 0 0 1 0 28" nofill stroke #b23a24 5 cap round # handle
18
+ }
19
+ }
20
+ ```
21
+
22
+ - Draw around a **centered local origin `0,0`** so the asset places and pivots naturally later.
23
+ - `group "Part" at x,y pivot px,py { layer "…" { … } }` to nest movable/structured parts.
24
+
25
+ ## Drawing toolkit
26
+
27
+ ```
28
+ circle cx cy r ellipse cx cy rx ry
29
+ rect x y w h [r | rx ry] path "M… L… C… Z" # raw SVG path data
30
+ text "Hi" font "sans-serif" size 24 align center line 1.2 color #fff box 200 40 [bold] [italic]
31
+ image "id" w h at -w/2,-h/2 # needs: asset "id" "file.png" image (declared in the .flatink that uses it)
32
+ ```
33
+
34
+ Paint & finish:
35
+ ```
36
+ fill #rrggbb | nofill
37
+ stroke #rrggbb <width> [cap butt|round|square] [join round|bevel|miter] [miter n] [dash a,b]
38
+ opacity 0..1 # or 8-digit hex alpha #rrggbbaa
39
+ fill linear(90, 0:#bdecff, 1:#2f8fe0) # angle 0 = →, 90 = ↓
40
+ fill radial(0.5, 0.5, 0.5, 0:#fff, 1:#000) # cx, cy, r in 0..1, then stops
41
+ filter glow <blur> <color> | shadow <dx> <dy> <blur> <color> | blur <r> | adjust <b> <c> <s> <h>
42
+ tint <color> <amount(0..1)> nohit # nohit = drawn but click-through
43
+ ```
44
+
45
+ ## Repetition without copy-paste (compile-time)
46
+
47
+ ```
48
+ def n = 6
49
+ layer "rays" {
50
+ repeat i from 0 to n { rect -2 -40 4 16 fill #ffd24d } # $(…) interpolates compile-time math
51
+ }
52
+ ```
53
+ `$(expr)` injects arithmetic into any coordinate: `circle $(60 + i*40) 80 6 …`. Nested loops = grids.
54
+
55
+ ## Make the asset RESTYLEABLE — `params {}`
56
+
57
+ Publish a typed interface so a consumer can recolor/tune the asset without touching internals:
58
+
59
+ ```
60
+ symbol "Boat" {
61
+ params {
62
+ color hull = #c0392b "Hull color"
63
+ color sail = #2980b9 "Sail color"
64
+ bool flag = true "Show the pennant"
65
+ }
66
+ layer "body" {
67
+ path "M-40 0 L40 0 L24 20 L-24 20 Z" fill hull # a color param used as a fill…
68
+ path "M0 -50 L0 0 L26 -10 Z" fill sail # …or stroke <param> <width>
69
+ }
70
+ }
71
+ ```
72
+ - Types: `color`, `number` (`number wave = 1 range 0 2 "…"`), `bool`.
73
+ - `color` params go anywhere a `#color` literal goes (`fill hull`, `stroke hull 3`).
74
+ - Preview a restyle: `flatc --preview Boat.flat --render --set hull=#1a5f3a -o boat.png`.
75
+
76
+ ## GOTCHAS for drawing
77
+
78
+ 1. **No `size` in a `.flat`.** That belongs to the `.flatink` program that places your symbols.
79
+ 2. **Rings / holes / cutouts = ONE `path` with multiple closed subpaths.** Fill is **even-odd**, so a
80
+ nested subpath punches a hole. Don't fake a ring with `nofill stroke`:
81
+ `path "M-30 -30 L30 -30 L30 30 L-30 30 Z M-15 -15 L15 -15 L15 15 L-15 15 Z" fill #c33`.
82
+ 3. **`stroke`, `opacity`, `filter` all exist on `path` AND `text`.** Outline text with
83
+ `text "…" color #fff stroke #000 4 join round` (stroke drawn behind fill) — never stack two texts.
84
+ 4. **`image` origin is top-left** → center with `at -w/2,-h/2`.
85
+ 5. **Text never wraps unless you add `wrap`** (`… box W H wrap`); otherwise only explicit `\n` breaks.
86
+ Also, `at x,y` on `text`/`image` must come **right after the content**, before `font`/`box`/`fill`
87
+ (`text "…" at x,y box W H`, not `… box W H at x,y`).
88
+ 6. **Filters are cheap only on static decor** (auto-cached). Fine here since your assets are static —
89
+ but a large blurred plane is costly; for big soft shadows prefer a "baked" offset copy in `#00000028`.
90
+ 7. **Layer order = z-order.** Bottom layer drawn first. Put shadows/backings on lower layers.
91
+ 8. **Don't hand-compute Bezier circles** — use `circle`/`ellipse`/`rect` sugar; they normalize to paths.
92
+ 9. **Center art on `0,0`** so the asset rotates/scales cleanly when someone animates it later.
93
+
94
+ ## Self-check
95
+ - File is only `symbol "…" { … }` blocks, no `size`, no behavior.
96
+ - Holes use even-odd subpaths; outlines use `stroke`, not duplicated shapes.
97
+ - Art centered on the origin; layers ordered back-to-front; params (if any) are typed with docs.
@@ -0,0 +1,180 @@
1
+ # FlatInk for a CODER — interactive `.flatink` programs
2
+
3
+ **Your role:** build **interactive scenes** — state, events, drag/drop, gesture interactors, scoring,
4
+ and the declarative factoring sugar. You wire behavior to named scene items.
5
+
6
+ **Output contract:** a `.flatink` program. Emit **only the code** in a fenced block. Verify and test
7
+ headlessly (no browser):
8
+ ```
9
+ flatc game.flatink --check # semantic + layout lint (exit ≠0 on ERROR)
10
+ flatc game.flatink --play --script gestures.json --trace # replay gestures, see sends + var diffs
11
+ ```
12
+
13
+ ## File shape — TWO grammars, one file
14
+
15
+ ```
16
+ size 480 320 # REQUIRED, first line
17
+ background #0a0e1c
18
+ use "collision" # stdlib: collision | easing | gesture | feedback
19
+ var score = 0 # global runtime state (top of file)
20
+
21
+ scene { # ── HALF 1: composition (what you see) ──
22
+ layer "game" {
23
+ circle 240 160 40 fill #ffcc00 as "Sun" # `as` names an item for behavior
24
+ instance "Card" as "C1" at 100,100
25
+ }
26
+ }
27
+
28
+ object "Sun" { # ── HALF 2: behavior, attaches by name ──
29
+ when clicked { score = score + 1 }
30
+ rotation = time * 90 # channel binding, evaluated every frame
31
+ }
32
+ every frame { if (score >= 10) { send "win" } }
33
+ ```
34
+ **Drawing keywords (`circle`, `path`, `group`…) live ONLY in `scene`. Logic keywords (`var`, `when`,
35
+ `object`, `fn`, `if`) live ONLY after it.** They don't share a grammar.
36
+
37
+ ## State, events, actions
38
+
39
+ ```
40
+ var score = 0 var slots = [0,0,0] var seen = fill(8, 0) # arrays via literal or fill(n,v)
41
+ ```
42
+ Events (in `object "Name"`): `when clicked | hovered | unhovered | pressed | released | dragged | held
43
+ | dropped on <Zone> [at pointer]`. Scene-wide: `when loaded`, `every frame`, `at frame <n>`.
44
+
45
+ Actions — **one per line**:
46
+ ```
47
+ <var> = <expr> arr[<expr>] = <expr> # `set` keyword optional; nested indices ok
48
+ if <c> { … } [else if <c> { … }] [else { … }]
49
+ repeat <n> times { … } repeat i from a to b { … } # RUNTIME loops (bounded)
50
+ play pause go to frame <n> [and play|and pause] go to "<label>" [and play]
51
+ send "<evt>" [, <expr> | , text("<id>") | , { a = <expr>, b }] sound "<assetId>" <fn>(<args>)
52
+ ```
53
+
54
+ ## Channel bindings & expressions
55
+
56
+ Drive `x y scaleX scaleY rotation opacity` (absolute) every frame, plus `dx dy` — additive position
57
+ offsets, `pos = at + (dx, dy)`:
58
+ ```
59
+ object "Needle" {
60
+ rotation = atan2(mouse.y - 160, mouse.x - 240) # RADIANS
61
+ opacity = lit ? 1 : 0.3
62
+ dx = 30 * sin(clock) # sways AROUND its declared at — no base to re-inject
63
+ }
64
+ ```
65
+ Chase a target with inertia instead of snapping to it:
66
+ ```
67
+ object "Dial" { spring rotation = aim { stiffness 0.08 damping 0.86 } } # smooth y = target { k 0.15 }
68
+ ```
69
+ Pure numeric expressions (no booleans — logic/compares yield `1`/`0`). Operators `?: || && == != < >
70
+ <= >= + - * / % - ! . [] fn()`. Built-ins: `sin cos tan atan2 abs sqrt pow exp log floor ceil round
71
+ sign min max hypot clamp(x,lo,hi) lerp(a,b,t) mod(a,b) between(x,lo,hi) rad deg turns`. Constants
72
+ `PI TAU E`. Reserved: `time` (s), `frame`, `value`, `mouse.x/y`, `keys.<Key>`, `self.*`, `<Name>.*`.
73
+
74
+ Functions: `fn dist(ax,ay,bx,by) = hypot(ax-bx, ay-by)` (value) · `fn reset() { score = 0 }` (procedure).
75
+
76
+ ## Drag, drop & interactors (each writes into your vars; all take `{ enabled <expr> }`)
77
+
78
+ ```
79
+ object "Piece" {
80
+ drag px, py { confine to Board · snap 20 } # dragX / dragY for one axis
81
+ x = px y = py # USE the vars it writes
82
+ when dropped on Slot at pointer { placed = 1 }
83
+ }
84
+ turn <angle> around x,y [{ snap <deg> }] # → RADIANS → rotation = <angle> directly
85
+ turnDeg <angle> around x,y [{ snap <deg> }] # → DEGREES → pair with rotationDeg = <angle>
86
+ trace <progress> along <Group> [{ tolerance <px> }] # follow path → 0..1 monotone
87
+ reveal <progress> [{ brush <px> }] # scratch/wipe grabbed area → 0..1 cumulative
88
+ link endX,endY,target to <Group> # elastic thread; target = hit index 1..n (0=none), WORLD coords
89
+ ```
90
+
91
+ ## Feedback (reactions without handlers)
92
+
93
+ ```
94
+ object "Tile" {
95
+ x = tx y = ty
96
+ feedback lift tilt dim shake(wrongZone) # lift=hover grow · tilt=grab squash · dim=hover dim · shake=wobble
97
+ }
98
+ ```
99
+ Or read state directly: `scaleX = self.hovered ? 1.06 : 1`, `scaleY = self.grabbed ? 0.94 : 1`.
100
+
101
+ ## Factoring — compile-time, zero runtime cost
102
+
103
+ ```
104
+ def gap = 70
105
+ repeat i from 0 to 4 { circle $(40 + i*gap) 80 6 fill #ffd98a } # $(…) = compile-time math
106
+ symbol "Key"(label) { layer "c" { rect -28 -28 56 56 fill #e8e8e8
107
+ text "$(label)" font "sans-serif" size 24 align center line 1.2 color #111 box 56 56 } }
108
+ scene { layer "Pad" {
109
+ repeat i from 0 to 8 { instance "Key"($(i+1)) as "K$(i)" at $(70 + (i%3)*80),$(80 + floor(i/3)*80) }
110
+ } }
111
+ each "Key" as i { when clicked { input = input*10 + (i+1) } } # one handler per generated instance
112
+ ```
113
+ `match` factors a whole drag+drop matching activity:
114
+ ```
115
+ match Word1, Word2 onto Good, Bad {
116
+ correct Word1 -> Good, Word2 -> Bad
117
+ lock on wrong # optional; absent = retryable
118
+ on correct as it { send "found", text(it) }
119
+ on done { send "win" }
120
+ }
121
+ ```
122
+ It generates per item `<Item>_placed` / `<Item>_ok` / `<Item>_zone`; you keep the visual
123
+ (`var <Item>_x`/`_y` + your channel expressions).
124
+
125
+ ## CRITICAL GOTCHAS
126
+
127
+ 1. **`size W H` first line, required.** Then `scene { … }`, then behavior.
128
+ 2. **Two grammars — don't cross them.** No `var`/`when`/`if` inside `scene`; no `circle`/`path` inside
129
+ `object`. Drawing in the scene half, logic in the behavior half.
130
+ 3. **One action per line.** `x = 1 y = 2` errors. `send "evt", x = 1` is a footgun error (a `send`
131
+ carries at most one payload: `send "evt"`, `send "evt", <expr>`, `send "evt", text("id")`, or the
132
+ record `send "evt", { a = <expr>, b }` — several NAMED numbers in one event, `{ b }` = `{ b = b }`).
133
+ 4. **Radians by default; `*Deg` twins for degrees.** `rotation`, `sin/cos/atan2`, `gesture.angle`, and the
134
+ **`turn`** interactor are radians — wire directly: `rotation = angle(self.x, self.y, mouse.x, mouse.y)`,
135
+ or `turn a around c` then `rotation = a`. To author in degrees, bind **`rotationDeg`** (sugar for
136
+ `rotation = rad(…)`) and use **`turnDeg`** (writes degrees). Ad-hoc convert with `rad()`/`deg()`/`turns()`.
137
+ 5. **`def` / `repeat … from`(scene) / `$()` / parameterized symbols are COMPILE-TIME** — they vanish from
138
+ the model. For runtime state use `var`. ⚠️ `repeat … times` / `repeat i from..to` **inside `object`**
139
+ is a *runtime* loop (different thing). A symbol param body sees only its params, not an outer `repeat`'s `i`.
140
+ A `def` is **not** a runtime variable — don't use it bare in a behavior expression; inject with
141
+ `$(name)` (`angle($(hubx), $(huby), …)`) or a literal.
142
+ 6. **Use the vars an interactor writes.** `drag px, py` only moves the object if you bind `x = px y = py`.
143
+ Outputs accept array elements (`drag hx[i], hy[i]`) — the natural form under `each` (array must exist).
144
+ 7. **Drop test = object CENTER** by default. `when dropped on Zone at pointer` tests the pointer;
145
+ `group "Zone" … hitbox W H { … }` sets an explicit drop rectangle. Several `when dropped on` per
146
+ object run in declaration order (right-zone / wrong-zones pattern).
147
+ 8. **Event order on release:** `when released` fires **BEFORE** the drop test; `link`/`drag` write their
148
+ output vars before `released`/`dragged`, so a release handler can read `<target>` already.
149
+ 9. **`reveal`/`trace` progress is monotone** (never decreases; reveal is cumulative across grabs).
150
+ `link` is in WORLD coords — place sources and targets at the scene root.
151
+ 10. **Distinct instance names** under `each`/`repeat` (`as "K$(i)"`) so each handler targets its own item.
152
+ 11. **`object "X"` must name a group / instance / text / image.** A shape *can* take `as "N"` (addressable,
153
+ e.g. `text … along "N"`) but carries no pose and can never be animated; a LAYER can't either — naming
154
+ one is a **compile error**. Wrap the shape: `group "N" { layer "art" { … } }`. Opacities MULTIPLY, so an
155
+ `opacity 0` shape cancels its group's fade-in. `as "…"`/`at x,y` go **right after the geometry/content**,
156
+ before `font`/`box`/`fill` (`text "…" at x,y box W H`, not `… box W H at x,y`). Stable text id for
157
+ payloads: `text "…" as "txt_id" …`.
158
+ 12. Test with `--play --script` using **semantic gestures** (by name): `{"type":"drag","source":"Card1",
159
+ "target":"ZoneA"}`, `tap`, `scratch`, `connect`, `wait`(frames), `key`(name/frames = hold a key),
160
+ `expect`(sends/vars). Unknown name = hard error.
161
+ 13. **`x`/`y` REPLACE the group's `at` — they are not deltas.** `object "G" { x = bump }` overwrites the
162
+ local x of a group declared `at X,Y` (x → `bump` ≈ 0, so it snaps to the edge). To move **around** the
163
+ anchor bind the additive offsets: **`dx = bump`** (`pos = at + (dx, dy)`) — no base to re-inject, and it
164
+ survives a re-layout. Re-injecting (`x = $(X) + bump`) is only for a genuinely absolute position. The
165
+ most common "anim shows up in the wrong place."
166
+ 14. **`time` WRAPS every `durationFrames` (2.5 s by default); `clock` is monotone.** Any instant you capture
167
+ and compare later must use `clock` — `when wrong { shown = clock }` + `opacity = pulse(shown, 4)`.
168
+ On `time`, a one-shot end-of-game ramp replays for ever and a `shake` skips on every loop.
169
+ 15. **`{ enabled <expr> }` gates the GESTURE, not the handlers** — `when pressed`/`released`/`clicked` keep
170
+ firing. Guard the body: `when released { if done == 0 { … } }`. (A `link`'s target index resolves to 0.)
171
+ 16. **Check the program as `.flatink`** — a `.flat` is a symbol library, so a program under that name is not
172
+ verified at all (`flatc` refuses it now). `--no-libs` ignores the `.flat` scratch files next to it.
173
+
174
+ ## Self-check
175
+ - First line `size`; drawing vs logic in the correct half; one action per line.
176
+ - Every behavior target (`object "X"`, drop zones, `align/link/trace` groups) is a named scene item
177
+ **and is a group / instance / text / image** — never a bare shape or a layer.
178
+ - Instants captured with `clock`, not `time`; `{ enabled … }`-gated handlers guard their own body.
179
+ - Interactor output vars are actually consumed by channel bindings; arrays pre-allocated.
180
+ - Radians where required; compile-time (`def`/`$()`) vs runtime (`var`) used correctly.
@@ -0,0 +1,171 @@
1
+ # FlatInk for a MOTION DESIGNER — animating `.flat` symbols
2
+
3
+ **Your role:** make symbols **move** — the Flash-style timeline/cel/pose model, tweens, easing, spin,
4
+ pivots, expression-driven channels, and named states. You think in keyframes, arcs, and timing.
5
+
6
+ **Output contract:** usually a `.flat` (animated `symbol`s). Emit **only the code** in a fenced block.
7
+ A `.flat` has **no `size`**. Author previews with:
8
+ ```
9
+ flatc --preview Wheel.flat --render -o wheel.png # PNG of one frame (default --bbox all, union)
10
+ flatc --preview Wheel.flat -o wheel.flatpack # playable file for the browser
11
+ flatc --preview Door.flat --render --set door=0.5 -o half.png # a state / param value
12
+ ```
13
+
14
+ ## The model in one paragraph
15
+
16
+ A symbol owns a **timeline** (`timeline <fps> <durationFrames>`, loops over `[0, dur)`). An animated
17
+ **layer** is a time track: a sequence of **cels** (keyframes). Each cel lists the **poses** of the
18
+ containers in the layer's **roster** (declared ONCE above the cels). Between two cels the layer either
19
+ **holds** the last key or **tweens** toward the next.
20
+
21
+ ```
22
+ symbol "Wheel" {
23
+ timeline 24 24
24
+ layer "spin" {
25
+ group "Rim" at 100,100 pivot 0,0 { # roster: declared once, posed below
26
+ layer "art" { circle 0 0 40 nofill stroke #333 8 }
27
+ }
28
+ cel 0 tween { pose "Rim" rotate 0 }
29
+ cel 24 { pose "Rim" rotate 360 } # one full turn around the pivot, in DEGREES
30
+ }
31
+ }
32
+ ```
33
+
34
+ ## `pose` — a container's keyframe
35
+
36
+ ```
37
+ pose "Name" [at x,y] [rotate <deg>] [scale s | scaleX sx scaleY sy]
38
+ [opacity o] [tint #color amt] [spin cw|ccw] [turns n] [filter …]
39
+ ```
40
+ - **Human units:** `rotate` in **degrees**, `scale` a **multiplier**, around the group's **`pivot`**.
41
+ No matrices, no radians. (`matrix(a,b,c,d,e,f)` exists as an escape hatch — rarely needed.)
42
+ - **`at x,y`** places the local origin in parent space.
43
+ - **A pose is a PATCH:** it inherits every channel it doesn't mention from the roster declaration.
44
+ `pose "Boat" opacity 0.5` keeps the Boat's position/rotation/scale, only dims it.
45
+
46
+ ## Tweens, easing, spin
47
+
48
+ - `cel N tween { … }` interpolates this cel → the next for containers present in both. No `tween` = hold.
49
+ - `ease linear | easeIn | easeOut | easeInOut | cubic(a,b,c,d)` on the cel.
50
+ - `spin cw|ccw` + `turns <n>`: force direction and add whole turns over the tween (so 350°→10° can go
51
+ the short way `ccw`, or wind several times `turns 2`). Always around the pivot.
52
+ - `morph` on a cel tweens the **shape** of the cel's `matter` toward the next key.
53
+
54
+ ## Frame-by-frame — one drawing per cel (`matter`)
55
+
56
+ A cel carries not only poses but the layer's **drawing**, in a `matter { … }` block. A new one per cel =
57
+ classic cel animation (no tween):
58
+ ```
59
+ layer "draw" {
60
+ cel 0 { matter { circle 0 0 30 fill #e33 } }
61
+ cel 1 { matter { rect -30 -30 60 60 fill #3a3 } }
62
+ cel 2 { matter { path "M -30 30 L 0 -30 L 30 30 Z" fill #33e } }
63
+ }
64
+ ```
65
+ - The matter **holds** until the next cel defining one → a drawing kept for several frames is written
66
+ once. `morph` on the cel tweens its shape instead of cutting. `matter { }` (empty) blanks it.
67
+ - A cel can carry both `matter { … }` and `pose "…"` (matter draws behind the posed containers).
68
+ - Drawings that already exist as objects: put each in a roster `group`/`image` and pose only the wanted
69
+ one per cel (an unposed container disappears).
70
+ - **A layer with cels draws NOTHING ELSE** — a bare shape left in such a layer is silently never drawn.
71
+
72
+ ## Carrying poses & exits — `hold`
73
+
74
+ A cel is a **full snapshot**: a container is shown only on cels that `pose` it; omit it and it
75
+ **disappears** there (that's how a symbol exits). To avoid re-typing unchanged containers:
76
+ ```
77
+ cel 0 tween { pose "Base" at 0,0 pose "Ring" scale 1 }
78
+ cel 30 hold tween { pose "Ring" scale 4 } # Base carried forward automatically
79
+ cel 60 hold { pose "Ring" scale 1 }
80
+ ```
81
+ Or keep a truly static element on its **own cel-less layer** (rendered every frame, declared once).
82
+
83
+ ## Expression-driven channels (no keyframes)
84
+
85
+ Bind a channel on a container to a formula:
86
+ ```
87
+ group "Fan" pivot 0,0 expr rotation "turns(time)" { … } # one turn per second
88
+ ```
89
+ - Channels: `x y scaleX scaleY rotation opacity` (absolute), plus **`dx` / `dy`** — additive position
90
+ offsets, `pos = at + (dx, dy)`. Prefer them for motion AROUND a rest position: `expr dx "30*sin(clock)"`
91
+ sways a group without overwriting its `at`, so re-laying the scene out doesn't break the animation.
92
+ - **`expr rotation` is in RADIANS.** Stay in degrees with helpers: `rad(45)`, `turns(n)`
93
+ (`turns(time)` = 1 turn/sec, `turns(time*0.5)` = slower), `deg(rad)`.
94
+ - Math available: `sin cos tan atan2 abs sqrt floor round min max clamp lerp mod …`, `frame`, and
95
+ **`clock`** (monotone) — prefer it to `time`, which restarts on every timeline loop.
96
+
97
+ ## Stateful easing — `spring` / `smooth`
98
+
99
+ A channel that CHASES its target instead of jumping to it. State lives per instance, costs nothing when
100
+ unused, and **snaps to the target on a seek** — so tune it by PLAYING the preview, never by scrubbing.
101
+
102
+ ```
103
+ symbol "Cable" {
104
+ params { number hookX = 0 range -1 1 "Hook offset" } # the target must be a NAME this scope knows
105
+ timeline 24 24
106
+ layer "a" {
107
+ group "Swing" spring rotation "hookX" stiffness 0.08 damping 0.86 { # 2nd order: overshoots, settles
108
+ layer "c" { rect -4 0 8 60 fill #333333 }
109
+ }
110
+ }
111
+ }
112
+ group "Leaf" smooth y "target" k 0.15 { … } # 1st order: no overshoot
113
+ ```
114
+ - `stiffness` / `damping` / `k` are all `0..1`. Low stiffness = lazy; damping near 1 = few oscillations.
115
+ - The target is a quoted expression, and its names must EXIST in that scope (a symbol `param`, a scene
116
+ variable). `--check` reports an unknown one as `spring rotation: unknown variable "…"`.
117
+ - It can also read `velocity(<expr>)` for a trailing reaction — a cable that swings from the hook's
118
+ speed rather than its position. `velocity()` is valid ONLY inside a spring/smooth target.
119
+
120
+ ## Named states — expose points on the timeline
121
+
122
+ A door animates `closed`(frame 0) → `open`(frame 24) and exposes a single switchable param:
123
+ ```
124
+ symbol "Door" {
125
+ timeline 24 24
126
+ states door { closed at 0 open at 24 initial closed transition 12 ease easeInOut }
127
+ layer "panel" {
128
+ group "Panel" at 60,10 pivot 0,0 { layer "art" { rect 0 0 40 80 fill #884422 } }
129
+ cel 0 tween { pose "Panel" rotate 0 } # closed
130
+ cel 24 { pose "Panel" rotate 80 } # open
131
+ }
132
+ }
133
+ ```
134
+ - The param **drives the symbol's local playhead**: `door=0`→frame 0, `door=1`→frame 24,
135
+ `door=0.5`→frame 12 (the authored in-between). Animating 0→1 plays the open animation.
136
+ - `timeline`, `params`, `states` header blocks may appear in **any order** before the layers.
137
+ - A program drives it by name: `FrontDoor.door = open` (plays the `transition`); each instance keeps
138
+ its own state.
139
+
140
+ ## CRITICAL GOTCHAS for motion
141
+
142
+ 1. **Pivot or it ORBITS.** `pivot` (local coords on the roster container, default `0,0`) is the center
143
+ of rotation **and** scale **and** tween interpolation. Off-center art with no pivot orbits instead of
144
+ spinning in place. Set the pivot to the visual center / hub.
145
+ - **In a TWEEN this causes drift:** the pivot's position lerps in a straight line while rotation arcs
146
+ around it. So adding a `rotate` to a cel whose pivot is off-center makes the body swing sideways — a
147
+ "sinking boat" slides right. Keep the pivot centered, match `at x` across the cels, and do the
148
+ descent with `at y` rather than a large tilt.
149
+ 2. **Degrees vs radians by context.** `pose rotate`/`scale` = degrees & multipliers. `expr rotation`
150
+ and `sin/cos/atan2` = **radians** → use `rad()`, `turns()`, `deg()`.
151
+ 3. **A pose is a patch, not a replace.** Don't re-state `at x,y` in every cel just to change one channel.
152
+ 4. **Per-keyframe, not per-frame.** Three keyframes = three poses, not one per frame. A container must
153
+ be posed on **every cel of the span** it's visible (or use `hold`, or a cel-less layer).
154
+ 5. **A layer with cels draws ONLY the cel's `matter` + the containers that cel poses.** A bare shape
155
+ written straight into such a layer is **silently never drawn** — put it in a `cel N { matter { … } }`
156
+ or on a cel-less layer. Render order: the `matter` draws **behind** posed containers and declaration
157
+ order isn't preserved; to put a static shape in front, give it its **own layer above** (or wrap it in a
158
+ group → it becomes a posed container too). `flatc --check` warns on the silent drops.
159
+ 6. **Preview is union-framed and stable.** `--preview` defaults to `--bbox all` (union over all frames),
160
+ so drifting/growing motion is never clipped, and the canvas is auto-sized once — the object moves
161
+ *inside* a fixed frame, it doesn't jump. Use `--bbox frame0` / `--pad N` to adjust.
162
+ 7. **Filters on animated elements recomposite every frame** — keep them small. Static decor filters are
163
+ cached (cheap).
164
+ 8. **Stroke width scales with the group** (drawn in scaled space) — a `pose scale 0.4` thins strokes
165
+ proportionally; don't compensate by hand.
166
+
167
+ ## Self-check
168
+ - Everything that turns/scales in place has a `pivot` at its visual center.
169
+ - Radians vs degrees correct for every channel (`pose` deg, `expr rotation` rad).
170
+ - Each persistent container is posed on every cel of its span, or carried via `hold` / a cel-less layer.
171
+ - States/params header before layers; preview command would show the full motion (`--bbox all`).
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/flatc.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// flatc — the \"modern SWF\" command-line compiler.\n//\n// The VSCode-first flow: you write a `.flatink` program (composition + logic, DSL)\n// + `.flat` asset libs (visuals, exported by the editor) + media, then:\n//\n// flatc game.flatink hero.flat decor.flat -o game.flatpack\n//\n// → a single `.flatpack` (the baked Doc as JSON) that the player runs. Media referenced\n// by `asset \"id\" \"path\" kind` are EMBEDDED (paths relative to the program).\n// ─────────────────────────────────────────────────────────────────────────────\nimport { readFileSync, writeFileSync, existsSync, readdirSync, watch, mkdirSync, copyFileSync } from 'node:fs'\nimport { resolve, dirname, basename, extname, join, relative, isAbsolute } from 'node:path'\nimport { compileFlatpack, packToJSON, type MediaMap } from '../compile'\nimport { parseProgramFull, parseFlatLib, behaviorDiagnostics, objectTargetDiagnostics } from '@flatkit/engine/flatFormat'\nimport { hasPackage } from '@flatkit/engine/stdlib'\nimport { parseUnits } from '@flatkit/engine/dsl'\nimport { sanitizeDoc } from '@flatkit/engine/validateDoc'\nimport { unitsToFunctions } from '@flatkit/engine/scriptDoc'\nimport { containerBBox, containerBBoxUnion } from '@flatkit/engine/groups'\nimport { isInstance, isGroup } from '@flatkit/engine/layers'\nimport { IDENTITY } from '@flatkit/engine/transform'\nimport { lintDocReport, docHasErrors } from '../programDoc'\nimport { playHeadless, type Gesture } from '@flatkit/player/debug'\nimport type { FuncDef } from '@flatkit/engine/actions'\nimport type { Doc, Instance, Item, Layer, SymbolDef } from '@flatkit/types'\n\nconst MIME: Record<string, string> = {\n '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif',\n '.webp': 'image/webp', '.svg': 'image/svg+xml', '.avif': 'image/avif',\n '.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.ogg': 'audio/ogg', '.m4a': 'audio/mp4',\n // Fonts (RFC 8081 media types) — matches the editor's import (`font/woff2` default, FontFace API).\n '.woff2': 'font/woff2', '.woff': 'font/woff', '.ttf': 'font/ttf', '.otf': 'font/otf',\n // NB: video (.mp4/.webm/…) intentionally omitted — no video runtime in the editor or player yet.\n}\nconst mimeFor = (path: string): string => MIME[extname(path).toLowerCase()] ?? 'application/octet-stream'\n\n/**\n * True if `target` resolves to a file inside `baseDir` (or baseDir itself). Guards against a hostile\n * program escaping its folder via `../` in a media path or a `use` package name — compiling an untrusted\n * `.flatink` must never read (and embed) arbitrary host files.\n */\nfunction isWithin(baseDir: string, target: string): boolean {\n const rel = relative(baseDir, target)\n return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))\n}\n\nfunction printHelp(): void {\n process.stdout.write(`flatc — compile a FlatInk program into a .flatpack\n\nUsage:\n flatc <program.flatink> [assets.flat …] [-o output.flatpack]\n flatc <program.flatink> --watch\n flatc --play <program.flatink | scene.flatpack> --script <gestures.json>\n flatc --render <program.flatink | scene.flatpack> -o out.png [--frame N] [--at k=v[,k2=v2]] [--scale S]\n flatc --preview <library.flat> [--symbol NAME] [-o out.flatpack | --render -o out.png]\n flatc <library.flat> [more.flat …] --check\n\n program.flatink the program (composition + logic, text DSL)\n assets.flat visual asset libs (default: every .flat in the program's folder)\n -o, --out output file (default: <program>.flatpack — the CANONICAL name, JSON inside)\n --assets MODE media baking: 'inline' (default, base64 in the .flatpack) or 'external'\n (sidecar <out>.assets/ folder; asset.data = relative key — serve the folder and\n play with sameOriginAssetResolver(<flatpackUrl>))\n --check semantic lint only (no .flatpack); exits ≠0 on ERROR (warnings do not stop). Lints a\n program .flatink OR an asset library .flat (per-symbol; several .flat are merged)\n --no-libs do NOT auto-discover the .flat files sitting next to the program (use it in a working\n folder, where a neighbouring scratch file is not a dependency)\n --watch recompile on every change in the folder (agent → player loop)\n --play run the file WITHOUT a canvas, replay --script and print { sends, vars } (JSON)\n --trace (with --play) HUMAN-READABLE log per gesture: emitted sends + variable diff (debug)\n --script <f> JSON gesture script: [{ \"type\": \"down|move|up|cancel\", \"x\", \"y\" }, { \"type\": \"set\", \"name\", \"value\" }, { \"type\": \"wait\", \"frames\": N }, { \"type\": \"wheel\", \"dy\": N }]\n semantic (by NAME, the engine resolves coords): { \"type\": \"drag\", \"source\", \"target\" } · { \"type\": \"tap\", \"target\" }\n · { \"type\": \"scratch\", \"target\" } (sweeps a reveal zone) · { \"type\": \"connect\", \"source\", \"target\" } (pulls a link wire)\n { \"type\": \"key\", \"name\": \"ArrowRight\", \"frames\": N } holds a key (keys.<name> = 1) N steps, then releases it\n \"wait\" lets the simulation run N fixed steps (60 Hz): \"every frame\" + playhead advance like in real playback\n \"expect\" self-verifies: { \"type\": \"expect\", \"sends\": [\"done\"], \"vars\": { \"score\": 3 } } → exits ≠0 on mismatch\n (sends = sequence of names emitted SINCE the last expect; vars = current state). Great in CI.\n --render render a PNG IMAGE (headless skia): see what we draw (positioning)\n --preview wrap ONE symbol of a <library.flat> into a playable Doc (a single centered instance on an\n auto-sized stage) → a .flatpack to drop in the browser player, or a PNG with --render.\n No wrapper .flatink to author by hand. Output defaults to <library>.<symbol>.flatpack/.png\n --symbol NAME (with --preview) which symbol to wrap (default: the first in the lib)\n --bbox all|frame0 (with --preview) auto-size to the UNION over all frames (default 'all', no clipping of\n drifting/rotating/growing motion) or just frame 0 ('frame0', the old behavior)\n --pad N (with --preview) padding in px around the symbol's bounds (default 24)\n --set p=v[,p2=v2] (with --preview) set the symbol's exposed params; a state param takes a state NAME\n or a number (e.g. --set door=open), others take a number → baked into the preview\n --frame N (with --render) target frame (default 0)\n --at k=v[,k2=v2] (with --render) force variables → capture a given state (e.g. a step of an escape)\n --steps N (with --render) run N fixed sim steps (60 Hz, every-frame) BEFORE capture → see a\n stateful act unfold without forcing every derived variable by hand in --at\n --scale S|auto (with --render) resolution factor (default 2); 'auto' picks one from the canvas size\n (enlarges small/thin assets so fine filaments stay legible, large assets stay 1x)\n -h, --help this help\n\nMedia referenced by 'asset \"id\" \"path\" kind' are embedded (paths relative to the program).\n`)\n}\n\n/** How media is baked: `inline` = base64 data-URI in the .flatpack; `external` = relative key + sidecar files. */\ntype AssetMode = 'inline' | 'external'\ntype MediaCopy = { src: string; key: string } // external mode: source file → relative key (forward slashes)\ntype BuildResult = { doc: Doc; flatLibs: number; packages: number; media: number; mediaCopies: MediaCopy[]; behaviorDiags: ReturnType<typeof behaviorDiagnostics>; src: string }\n\n/**\n * Reads a `.flatink`, resolves libs/packages/media, compiles → standalone Doc. Throws on compile error.\n * `assetMode`: `inline` embeds each media as a base64 data-URI (default); `external` keeps `asset.data` as a\n * relative key (`<assetsDir>/<path>`) and returns the files to copy beside the .flatpack (no base64 bloat).\n */\nfunction buildDocFromProgram(programPath: string, explicitFlats: string[] = [], assetMode: AssetMode = 'inline', assetsDir = '', noLibs = false): BuildResult {\n const baseDir = dirname(programPath)\n const programSrc = readFileSync(programPath, 'utf8')\n const prog = parseProgramFull(programSrc)\n\n // .flat libs: explicit if provided, otherwise auto-discover the .flat files in the program's folder\n // (`--no-libs` opts out — in a working folder, a neighbouring scratch file is not a dependency).\n const flatPaths = new Set<string>(explicitFlats.map((p) => resolve(p)))\n if (!flatPaths.size && !noLibs) for (const f of readdirSync(baseDir).filter((f) => f.endsWith('.flat'))) flatPaths.add(join(baseDir, f))\n\n // PACKAGES: non-stdlib `use \"x\"` → local files inlined (x.flatink = functions, x.flat = symbols).\n const pkgFunctions: FuncDef[] = []\n const localResolved = new Set<string>()\n for (const name of prog.imports ?? []) {\n if (hasPackage(name)) continue // stdlib → left as a reference\n const fink = join(baseDir, name + '.flatink')\n const fflat = join(baseDir, name + '.flat')\n if (!isWithin(baseDir, fink) || !isWithin(baseDir, fflat)) { process.stderr.write(`flatc: package outside the program folder (ignored): \"${name}\"\\n`); continue }\n let found = false\n if (existsSync(fink)) { for (const f of unitsToFunctions(parseUnits(readFileSync(fink, 'utf8')).units)) pkgFunctions.push(f, { ...f, name: `${name}.${f.name}` }); found = true }\n if (existsSync(fflat)) { flatPaths.add(fflat); found = true }\n if (found) localResolved.add(name)\n else process.stderr.write(`flatc: package not found: \"${name}\" (neither stdlib, nor ${name}.flatink / ${name}.flat)\\n`)\n }\n // Parse each lib HERE so a failure names the FILE. Libs are auto-discovered from the folder, so the one\n // that fails is often a neighbour the author never mentioned — a bare \"compile error: …\" sent them hunting\n // through their own program for a fault that was never in it.\n const assetSrcs = [...flatPaths].map((p) => {\n const src = readFileSync(p, 'utf8')\n try { parseFlatLib(src) } catch (e) { throw new Error(`${basename(p)}: ${(e as Error).message} (pass --no-libs to ignore the .flat files sitting next to the program)`, { cause: e }) }\n if (programConstructsIn(src).length) process.stderr.write(`flatc: ${basename(p)}: looks like a PROGRAM saved as .flat — loaded as a symbol library, so its scene/object blocks are ignored. Rename it to .flatink, or pass --no-libs.\\n`)\n return src\n })\n\n // Media: each `asset … \"path\" …` resolved relative to the program. `inline` → base64 data-URI baked in;\n // `external` → `asset.data` becomes a relative key and the file is copied next to the .flatpack.\n const media: MediaMap = {}\n const mediaCopies: MediaCopy[] = []\n for (const a of prog.assets ?? []) {\n const mp = resolve(baseDir, a.data)\n if (!isWithin(baseDir, mp)) { process.stderr.write(`flatc: media outside the program folder (ignored): ${a.data}\\n`); continue }\n if (!existsSync(mp)) { process.stderr.write(`flatc: missing media (ignored): ${a.data}\\n`); continue }\n const mime = mimeFor(mp)\n if (assetMode === 'external') {\n const key = `${assetsDir}/${a.data.replace(/\\\\/g, '/')}` // URL-form relative key (resolved by the host)\n media[a.data] = { mime, data: key }\n mediaCopies.push({ src: mp, key })\n } else {\n media[a.data] = { mime, data: `data:${mime};base64,${readFileSync(mp).toString('base64')}` }\n }\n }\n\n let doc = compileFlatpack(programSrc, assetSrcs, media)\n if (pkgFunctions.length) doc = { ...doc, functions: [...(doc.functions ?? []), ...pkgFunctions] }\n const stdImports = (doc.imports ?? []).filter(hasPackage)\n doc = { ...doc, imports: stdImports.length ? stdImports : undefined }\n // Both are source-based (exact positions) and both are ERRORS: a parse-level drop inside a block, and a\n // block that binds to no animatable item at all.\n return { doc, flatLibs: flatPaths.size, packages: localResolved.size, media: Object.keys(media).length, mediaCopies, src: programSrc, behaviorDiags: [...behaviorDiagnostics(programSrc), ...objectTargetDiagnostics(programSrc)] }\n}\n\n/** Compile once (write or --check). Returns the exit code. */\nfunction compileOnce(programPath: string, explicitFlats: string[], out: string, checkOnly: boolean, assetMode: AssetMode = 'inline', noLibs = false): number {\n const outPath = out ? resolve(out) : join(dirname(programPath), basename(programPath, extname(programPath)) + '.flatpack')\n // External mode: sidecar folder next to the .flatpack, e.g. `game.flatpack` → `game.assets/`.\n const assetsDir = assetMode === 'external' ? basename(outPath, extname(outPath)) + '.assets' : ''\n let built: BuildResult\n try { built = buildDocFromProgram(programPath, explicitFlats, assetMode, assetsDir, noLibs) }\n catch (e) { process.stderr.write(`flatc: compile error: ${(e as Error).message}\\n`); return 1 }\n const { doc } = built\n // Behavior parse errors (unknown channels / malformed statements inside `object` blocks) that the\n // Doc-based linter can't see — they were dropped before reaching the model. Always ERRORS.\n const behaviorReport = built.behaviorDiags.map(({ scope, diag }) => `[${scope}] ${diag.line}:${diag.col}: error: ${diag.message}`).join('\\n')\n // Dedupe exact-duplicate lines: a scene parse error IS reported by both paths (both now read the source).\n const report = [...new Set([behaviorReport, lintDocReport(doc, built.src)].flatMap((r) => r.split('\\n')).filter(Boolean))].join('\\n')\n const hasErrors = docHasErrors(doc, built.src) || built.behaviorDiags.length > 0\n if (checkOnly) {\n if (report) process.stderr.write(report + '\\n')\n if (hasErrors) return 1\n // Success line deliberately avoids the word \"error\" (the report on a FAILURE already prints \"error\" to\n // stderr + exits ≠0) so a `grep error` over the output can't false-positive — the real signal is the exit\n // code; on success, only warnings remain (non-blocking), surfaced as a count.\n const warnings = report ? report.split('\\n').filter(Boolean).length : 0\n process.stdout.write(`flatc: check passed ✓${warnings ? ` · ${warnings} warning(s)` : ''}\\n`)\n return 0\n }\n if (report) process.stderr.write(report + '\\n') // compile anyway: diagnostics as warnings\n writeFileSync(outPath, packToJSON(doc))\n const outDir = dirname(outPath)\n for (const c of built.mediaCopies) {\n const dest = join(outDir, ...c.key.split('/'))\n if (!isWithin(outDir, dest)) continue // defensive: never write outside the output folder\n mkdirSync(dirname(dest), { recursive: true })\n copyFileSync(c.src, dest)\n }\n const where = assetMode === 'external' ? ` (external → ${assetsDir}/)` : ''\n process.stdout.write(`flatc: ${basename(outPath)} ✓ ${doc.symbols.length} symbol(s) · ${built.flatLibs} lib(s) · ${built.packages} package(s) · ${built.media} media${where}\\n`)\n return 0\n}\n\n/** PROGRAM-only constructs found in what is supposed to be a `.flat` symbol library. `parseFlatLib` reads a\n * `.flat` as a bag of symbols and silently ignores everything else, so a whole program saved under the wrong\n * extension parsed to \"0 symbol(s)\" and passed `--check` with nothing verified — the worst possible answer\n * for tooling, since a check written against the wrong extension ALWAYS passes and looks like a safety net.\n * Both constructs are anchored at line start: only a real block matches, not a mention inside a string. */\nfunction programConstructsIn(src: string): string[] {\n const found: string[] = []\n if (/^[ \\t]*scene\\s*\\{/m.test(src)) found.push('a `scene { … }` block')\n if (/^[ \\t]*object\\s+\"/m.test(src)) found.push('`object \"…\" { … }` blocks')\n return found\n}\n\n/**\n * `--check` for a `.flat` asset LIBRARY (one or several): parse via `parseFlatLib` (NOT the program parser,\n * which would choke on `symbol`/`params`/`layer`), merge the symbols into an empty-scene Doc, and run the SAME\n * Doc lint as a program -> per-symbol diagnostics (`[<Symbol>] line:col: …`). Reuses `lintDocReport`/\n * `docHasErrors`, so every existing check (params-in-expr, undeclared color param in a paint, unknown\n * functions/objects…) applies for free, with the same `[scope] line:col: level: msg` format and exit code.\n * No `behaviorDiagnostics` (those are scene-level — a pure lib has no scene).\n */\nfunction checkFlatLibs(flatPaths: string[]): number {\n const symbols: SymbolDef[] = []\n for (const p of flatPaths) {\n let src: string\n try { src = readFileSync(p, 'utf8') } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n const disguised = programConstructsIn(src)\n if (disguised.length) { // a PROGRAM saved as `.flat` — see programConstructsIn\n process.stderr.write(`flatc: ${basename(p)}: this is a PROGRAM, not a symbol library — it contains ${disguised.join(' and ')}, which a .flat never carries and which --check therefore does NOT verify. Rename it to .flatink.\\n`)\n return 1\n }\n try { symbols.push(...parseFlatLib(src).symbols) } // ids are uid-unique across calls -> safe to merge libs\n catch (e) { process.stderr.write(`flatc: ${basename(p)}: ${(e as Error).message}\\n`); return 1 } // a malformed lib -> a clean parse error (not \"[scene] …\")\n }\n const doc: Doc = { width: 1, height: 1, timeline: { fps: 24, durationFrames: 1, tracks: [] }, variables: {}, layers: [], symbols }\n const report = lintDocReport(doc) // scene scope is empty -> only per-symbol diagnostics\n if (report) process.stderr.write(report + '\\n')\n if (docHasErrors(doc)) return 1\n // \"check passed\", NOT \"no errors\" — the word \"error\" must not appear on success (a `grep error` trap); the\n // exit code is the signal, and any remaining lines are warnings (non-blocking), reported as a count.\n const warnings = report ? report.split('\\n').filter(Boolean).length : 0\n process.stdout.write(`flatc: check passed ✓ ${symbols.length} symbol(s)${warnings ? ` · ${warnings} warning(s)` : ''}\\n`)\n return 0\n}\n\n/** Loads a Doc from a `.flatink` (compiled) or a `.flatpack`/`.flatpack.json` (already-baked JSON). */\nfunction loadDoc(filePath: string): Doc {\n if (filePath.endsWith('.flatink')) return buildDocFromProgram(filePath).doc\n // .flatpack (canonical) or .flatpack.json (alias): untrusted JSON → normalize before use.\n return sanitizeDoc(JSON.parse(readFileSync(filePath, 'utf8')))\n}\n\n/** --play: runs the file headless, replays --script, prints { sends, vars }. */\nfunction playOnce(filePath: string, scriptPath: string, trace: boolean): number {\n if (!scriptPath) { process.stderr.write('flatc: --play requires --script <gestures.json>\\n'); return 1 }\n if (!existsSync(scriptPath)) { process.stderr.write(`flatc: script not found: ${scriptPath}\\n`); return 1 }\n let doc: Doc, gestures: Gesture[]\n try { doc = loadDoc(filePath) } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n try { gestures = JSON.parse(readFileSync(scriptPath, 'utf8')) as Gesture[] } catch (e) { process.stderr.write(`flatc: invalid JSON script: ${(e as Error).message}\\n`); return 1 }\n if (!Array.isArray(gestures)) { process.stderr.write('flatc: the script must be an array of gestures\\n'); return 1 }\n const res = playHeadless(doc, gestures, { trace })\n if (!trace) process.stdout.write(JSON.stringify(res, null, 2) + '\\n')\n else // --trace: readable log (one gesture per line) → inspection / debug-player.\n for (const s of res.steps ?? []) {\n // `name` · `name=value` · `name{a=1, b=2}` (record payload) — the three shapes the host receives.\n const send = (e: { name: string; value?: number | string; fields?: Record<string, number> }): string =>\n e.fields ? `${e.name}{${Object.entries(e.fields).map(([k, v]) => `${k}=${v}`).join(', ')}}`\n : e.value !== undefined ? `${e.name}=${e.value}` : e.name\n const sends = s.sends.length ? ' sends:[' + s.sends.map(send).join(', ') + ']' : ''\n const vars = Object.entries(s.changed).map(([k, [a, b]]) => `${k}:${JSON.stringify(a)}→${JSON.stringify(b)}`)\n process.stdout.write(`${s.gesture.padEnd(28)}${sends}${vars.length ? ' vars{' + vars.join(' ') + '}' : ''}\\n`)\n }\n // `expect`: any detected mismatch → stderr log + exit code ≠0 (CI self-verification).\n if (res.expectFailures?.length) {\n for (const f of res.expectFailures) process.stderr.write(`flatc: ✗ ${f}\\n`)\n return 1\n }\n return 0\n}\n\n/** Parses `--at`: \"k=v[,k2=v2]\" → variable table (state override for rendering). */\nfunction parseVars(spec: string, into: Record<string, number>): void {\n for (const pair of spec.split(',')) {\n const i = pair.indexOf('=')\n if (i < 0) continue\n const k = pair.slice(0, i).trim(); const v = Number(pair.slice(i + 1).trim())\n if (k && Number.isFinite(v)) into[k] = v\n }\n}\n\n/** `--scale auto`: pick a resolution factor from the canvas size — enlarge small/thin content (so fine\n * filaments stay legible) while leaving large content at 1×. `max(160/long, 48/short)`, clamped [1, 8]. */\nfunction autoScale(w: number, h: number): number {\n const maxSide = Math.max(1, w, h), minSide = Math.max(1, Math.min(w, h))\n return Math.max(1, Math.min(8, Math.round(Math.max(160 / maxSide, 48 / minSide))))\n}\n\n/** Renders a Doc to a PNG file (headless skia). Async (SVG decode + raster). Shared by --render and --preview. */\nasync function renderDocToFile(doc: Doc, outPath: string, frame: number, vars: Record<string, number>, scale: number, steps: number): Promise<number> {\n try {\n const { renderDocToPng } = await import('./render')\n const png = await renderDocToPng(doc, { frame, vars: Object.keys(vars).length ? vars : undefined, scale, steps: steps || undefined })\n writeFileSync(outPath, png)\n } catch (e) {\n process.stderr.write(`flatc: render failed: ${(e as Error).message}\\n`)\n if (process.env.FLATC_DEBUG && (e as Error).stack) process.stderr.write(`${(e as Error).stack}\\n`) // FLATC_DEBUG=1 → full stack for diagnosis\n return 1\n }\n process.stdout.write(`flatc: ${basename(outPath)} ✓ ${doc.width}×${doc.height} ×${scale}${frame ? ` · frame ${frame}` : ''}${steps ? ` · ${steps} step(s)` : ''}${Object.keys(vars).length ? ` · ${Object.entries(vars).map(([k, v]) => `${k}=${v}`).join(' ')}` : ''}\\n`)\n return 0\n}\n\n/** --render: renders the file to PNG (headless skia). Async (SVG decode + raster). */\nasync function renderOnce(filePath: string, out: string, frame: number, vars: Record<string, number>, scale: number, steps: number, scaleAuto: boolean): Promise<number> {\n let doc: Doc\n try { doc = loadDoc(filePath) } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n const outPath = out ? resolve(out) : join(dirname(filePath), basename(filePath, extname(filePath)) + '.png')\n return renderDocToFile(doc, outPath, frame, vars, scaleAuto ? autoScale(doc.width, doc.height) : scale, steps)\n}\n\nconst gcd = (a: number, b: number): number => { a = Math.abs(a); b = Math.abs(b); while (b) { const t = a % b; a = b; b = t } return a || 1 }\nconst lcm = (a: number, b: number): number => Math.max(1, Math.round((a / gcd(a, b)) * b))\n\n/** Every instance in a symbol's subtree (descends into local groups; does NOT cross into other symbols). */\nfunction* instancesOf(sym: SymbolDef): Generator<Instance> {\n const stack: Item[] = []\n for (const l of sym.layers) stack.push(...l.items)\n for (let it = stack.pop(); it; it = stack.pop()) {\n if (isInstance(it)) yield it\n else if (isGroup(it)) for (const l of it.layers) stack.push(...l.items)\n }\n}\n\n/**\n * Preview window length (frames). A `synced` instance loops on the PARENT's frame, so the symbol's own\n * duration suffices — that's the historical behavior, kept for every symbol with no MovieClip descendant.\n * But an `independent` (`loop`) descendant runs on its OWN duration, immune to the parent's wrap: to SHOW it\n * loop CLEANLY the window must be a common multiple of every such clip's duration (and the root's) — its\n * \"loop seam\". `once` clips only need the window to REACH their last frame (they hold afterwards). We walk\n * the subtree, fold each independent clip's duration into the seam (LCM), and extend past the longest clip,\n * keeping the window a whole number of seams. Capped, so coprime durations can't blow the window up.\n */\nfunction previewDuration(root: SymbolDef, symbols: SymbolDef[]): number {\n const byId = new Map(symbols.map((s) => [s.id, s]))\n const seen = new Set<string>()\n let seam = Math.max(1, root.timeline?.durationFrames ?? 1) // clean-loop period (multiple of every loop clip)\n let longest = seam // window must reach the last frame of any clip\n const walk = (sym: SymbolDef | undefined): void => {\n if (!sym || seen.has(sym.id)) return\n seen.add(sym.id)\n for (const it of instancesOf(sym)) {\n const child = byId.get(it.symbolId)\n const cdur = Math.max(1, child?.timeline?.durationFrames ?? 1)\n const mode = it.playback?.mode\n if (mode === 'independent') { seam = lcm(seam, cdur); longest = Math.max(longest, cdur) }\n else if (mode === 'once') longest = Math.max(longest, cdur)\n walk(child)\n }\n }\n walk(root)\n let dur = seam\n while (dur < longest) dur += seam // keep a clean loop seam while covering the longest MovieClip\n return Math.min(dur, 6000) // hard cap (~4 min @24fps) against a pathological coprime-duration blow-up\n}\n\n/**\n * Wraps ONE symbol from a `.flat` library into a minimal, playable Doc: a single centered instance on a\n * canvas auto-sized to the symbol's frame-0 bounds (+ padding). Lets you preview a library asset without\n * hand-authoring a wrapper `.flatink`. The root timeline borrows the symbol's own fps and a duration long\n * enough to show every nested MovieClip (`loop`/`once`) loop cleanly (`previewDuration`). Throws if the lib\n * is empty or the named symbol is missing.\n */\nfunction buildPreviewDoc(flatPath: string, symbolName: string, pad: number, bboxMode: 'all' | 'frame0', setSpec: Record<string, string> = {}): { doc: Doc; symbol: SymbolDef; others: string[] } {\n const { symbols } = parseFlatLib(readFileSync(flatPath, 'utf8'))\n if (!symbols.length) throw new Error('no symbols found in this .flat library')\n let symbol = symbols[0]\n if (symbolName) {\n const found = symbols.find((s) => s.name === symbolName)\n if (!found) throw new Error(`symbol \"${symbolName}\" not found — available: ${symbols.map((s) => s.name).join(', ')}`)\n symbol = found\n }\n\n const instance: Instance = { id: 'preview_instance', kind: 'instance', name: symbol.name, transform: { ...IDENTITY }, symbolId: symbol.id }\n const layer: Layer = { id: 'preview_layer', name: 'preview', visible: true, locked: false, opacity: 1, items: [instance] }\n const tl = symbol.timeline\n const dur = previewDuration(symbol, symbols)\n const timeline = { fps: tl?.fps ?? 24, durationFrames: dur, tracks: [] }\n // ALL symbols stay in the library (the chosen one may instance the others) — only `instance` is on stage.\n let doc: Doc = { width: 1, height: 1, layers: [layer], symbols, timeline }\n\n // Auto-size & center. Default `--bbox all`: UNION over every frame of the symbol (sub-timelines NOT\n // frozen) so motion that drifts/rotates/grows is never clipped. `--bbox frame0` keeps the old frame-0\n // measure (+`--pad` to absorb motion).\n // Sample at most ~240 evenly-spaced frames (+ the last) so a long/abusive `durationFrames` can't blow\n // up memory/time; a sparse union is virtually as tight as every-frame for real motion.\n const sampleFrames = (n: number): number[] => {\n const step = Math.max(1, Math.ceil(n / 240))\n const fs: number[] = []\n for (let f = 0; f < n; f += step) fs.push(f)\n if (fs[fs.length - 1] !== n - 1) fs.push(n - 1)\n return fs\n }\n const bb = bboxMode === 'all' ? containerBBoxUnion(doc, instance, sampleFrames(dur)) : containerBBox(doc, instance, 0)\n if (bb) {\n doc = { ...doc, width: Math.max(1, Math.ceil(bb.maxX - bb.minX) + pad * 2), height: Math.max(1, Math.ceil(bb.maxY - bb.minY) + pad * 2) }\n instance.transform = { ...IDENTITY, e: pad - bb.minX, f: pad - bb.minY }\n } else {\n doc = { ...doc, width: 512, height: 512 } // empty/degenerate symbol: fall back to a fixed centered stage\n instance.transform = { ...IDENTITY, e: 256, f: 256 }\n }\n\n // `--set param=value`: set the preview instance's exposed params (call-site values, raw literals). The\n // renderer resolves them per the symbol's ParamDef / state machines (color → fill, number/bool → scope,\n // state name → driven frame). A light validation warns on names the symbol does not expose.\n const entries = Object.entries(setSpec)\n if (entries.length) {\n const known = new Set([...(symbol.states ?? []).map((s) => s.param), ...(symbol.params ?? []).map((p) => p.name)])\n for (const [k, v] of entries) {\n if (!known.has(k)) process.stderr.write(`flatc: --set ${k}: \"${symbol.name}\" exposes no such param (${[...known].join(', ') || 'none'})\\n`)\n else (instance.params ??= {})[k] = v\n }\n }\n return { doc, symbol, others: symbols.filter((s) => s !== symbol).map((s) => s.name) }\n}\n\n/** --preview: wraps one symbol of a `.flat` into a playable Doc, then writes a .flatpack (default) or a PNG (with --render). */\nasync function previewOnce(flatPath: string, symbolName: string, out: string, frame: number, vars: Record<string, number>, scale: number, steps: number, doRender: boolean, pad: number, bboxMode: 'all' | 'frame0', setSpec: Record<string, string>, scaleAuto: boolean): Promise<number> {\n let built: { doc: Doc; symbol: SymbolDef; others: string[] }\n try { built = buildPreviewDoc(flatPath, symbolName, pad, bboxMode, setSpec) }\n catch (e) { process.stderr.write(`flatc: ${(e as Error).message}\\n`); return 1 }\n const { doc, symbol, others } = built\n const stem = `${basename(flatPath, extname(flatPath))}.${symbol.name}`\n let code: number\n if (doRender) {\n // auto scale from the CONTENT size (minus the padding), so thin filaments still trigger an upscale.\n const sc = scaleAuto ? autoScale(doc.width - 2 * pad, doc.height - 2 * pad) : scale\n code = await renderDocToFile(doc, out ? resolve(out) : join(dirname(flatPath), stem + '.png'), frame, vars, sc, steps)\n } else {\n const outPath = out ? resolve(out) : join(dirname(flatPath), stem + '.flatpack')\n writeFileSync(outPath, packToJSON(doc))\n process.stdout.write(`flatc: ${basename(outPath)} ✓ preview of \"${symbol.name}\" · ${doc.width}×${doc.height} · play it in the browser player\\n`)\n code = 0\n }\n if (!symbolName && others.length) process.stderr.write(`flatc: previewed \"${symbol.name}\"; other symbols in this lib: ${others.join(', ')} (pick with --symbol <name>)\\n`)\n return code\n}\n\nexport function run(argv: string[]): number | Promise<number> {\n const args = argv.slice(2)\n let out = '', scriptPath = '', symbolName = ''\n let checkOnly = false, doWatch = false, doPlay = false, doRender = false, doTrace = false, doPreview = false, noLibs = false\n let frame = 0, scale = 2, steps = 0, pad = 24\n let scaleAuto = false\n let bboxMode: 'all' | 'frame0' = 'all'\n let assetMode: AssetMode = 'inline'\n const vars: Record<string, number> = {}\n const setSpec: Record<string, string> = {} // `--set param=value` (state name or number) for --preview\n const positional: string[] = []\n for (let i = 0; i < args.length; i++) {\n const a = args[i]\n if (a === '-o' || a === '--out') out = args[++i] ?? ''\n else if (a === '--script') scriptPath = resolve(args[++i] ?? '')\n else if (a === '--assets') assetMode = args[++i] === 'external' ? 'external' : 'inline'\n else if (a === '--check') checkOnly = true\n else if (a === '--no-libs') noLibs = true\n else if (a === '--watch') doWatch = true\n else if (a === '--play') doPlay = true\n else if (a === '--trace') doTrace = true\n else if (a === '--render') doRender = true\n else if (a === '--preview') doPreview = true\n else if (a === '--symbol') symbolName = args[++i] ?? ''\n else if (a === '--pad') pad = Math.max(0, Number(args[++i] ?? '24') || 0)\n else if (a === '--bbox') bboxMode = args[++i] === 'frame0' ? 'frame0' : 'all'\n else if (a === '--frame') frame = Number(args[++i] ?? '0') || 0\n else if (a === '--steps') steps = Math.max(0, Number(args[++i] ?? '0') || 0)\n else if (a === '--scale') { const v = args[++i] ?? '2'; if (v === 'auto') scaleAuto = true; else scale = Number(v) || 2 }\n else if (a === '--at') parseVars(args[++i] ?? '', vars)\n else if (a === '--set') for (const pair of (args[++i] ?? '').split(',')) { const j = pair.indexOf('='); if (j > 0) setSpec[pair.slice(0, j).trim()] = pair.slice(j + 1).trim() }\n else if (a === '-h' || a === '--help') { printHelp(); return 0 }\n else positional.push(a)\n }\n if (!positional.length) { printHelp(); return 1 }\n\n const filePath = resolve(positional[0])\n if (!existsSync(filePath)) { process.stderr.write(`flatc: not found: ${filePath}\\n`); return 1 }\n\n const explicitFlats = positional.slice(1)\n if (doPreview) return previewOnce(filePath, symbolName, out, frame, vars, scale, steps, doRender, pad, bboxMode, setSpec, scaleAuto)\n if (doRender) return renderOnce(filePath, out, frame, vars, scale, steps, scaleAuto)\n if (doPlay) return playOnce(filePath, scriptPath, doTrace)\n // `--check <library>.flat`: a `.flat` first positional is an asset LIB, not a program → lint via parseFlatLib\n // (the following positionals are more `.flat` libs to merge). Every other path is unchanged.\n const action: () => number = checkOnly && filePath.endsWith('.flat')\n ? () => checkFlatLibs([filePath, ...explicitFlats])\n : () => compileOnce(filePath, explicitFlats, out, checkOnly, assetMode, noLibs)\n if (doWatch) {\n const code = action()\n const baseDir = dirname(filePath)\n let timer: ReturnType<typeof setTimeout> | undefined\n // We ignore changes to the OUTPUT (.flatpack) — otherwise writing it would re-trigger the compile in a loop.\n watch(baseDir, { recursive: false }, (_e, filename) => {\n if (filename && (filename.endsWith('.flatpack') || filename.endsWith('.flatpack.json'))) return\n clearTimeout(timer); timer = setTimeout(action, 80)\n })\n process.stdout.write(`flatc: watching ${baseDir} … (Ctrl+C to stop)\\n`)\n return code\n }\n return action()\n}\n"],"mappings":"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","names":["f"]}