@idle-screens/schema 3.10.0 → 3.11.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.
- package/FORMAT.md +38 -4
- package/dist/index.d.ts +28 -1
- package/dist/index.js +241 -91
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/saver-spec.schema.json +33 -1
package/FORMAT.md
CHANGED
|
@@ -45,7 +45,8 @@ the `fade` transition, `role` on text sprites, and `text: 'crossfade'` on
|
|
|
45
45
|
sequence-level) (2026-09-10 — the print look); `timeline` (keyframes on the
|
|
46
46
|
scene's own clock), paint-level layer `opacity` and `transform`,
|
|
47
47
|
`position.dx` / `dy`, `wrapMorph` on the sequence envelope and
|
|
48
|
-
`text: 'dip'` on `morph` (2026-09-25 — timed scenes)
|
|
48
|
+
`text: 'dip'` on `morph` (2026-09-25 — timed scenes); layer `groups` and
|
|
49
|
+
`transform.origin` (2026-09-26 — groups and origin).
|
|
49
50
|
|
|
50
51
|
## Safety invariants
|
|
51
52
|
|
|
@@ -111,7 +112,8 @@ must exist, have `count: 1`, and not themselves orbit a layer.
|
|
|
111
112
|
"finish": { "grain": 0.5, "dither": 0.3 }, // optional; print screen over the finished frame
|
|
112
113
|
"background": { ... }, // optional; defaults to black
|
|
113
114
|
"layers": [ { ... }, ... ], // 1..36, rendered back-to-front
|
|
114
|
-
"timeline": { ... }
|
|
115
|
+
"timeline": { ... }, // optional; authored keyframes — see **Timeline**
|
|
116
|
+
"groups": { "moon": { ... } } // optional; named paint groups — see **Groups**
|
|
115
117
|
}
|
|
116
118
|
```
|
|
117
119
|
|
|
@@ -289,7 +291,8 @@ own `finish` is not steerable; steer a segment's, or republish.
|
|
|
289
291
|
| `key` | string | none | addressable name → `setParam("key.count", …)` for a layer field, `setParam("key.sprite.color", …)` for a sprite field (the path mirrors the JSON: sprite fields sit under `sprite`) |
|
|
290
292
|
| `position` | `{x, y, dx?, dy?}` — `x`/`y` 0..1, `dx`/`dy` ±2 (±17280 px under `units: "px"`) | none | exact placement; **requires `count: 1`** — except with a `list`/`table` layout, where it anchors the block's top-left; overrides `region`. `dx`/`dy` offset the point in **`min(w, h)` units** (px under `units: "px"`): `x`/`y` are fractions of width and height while every size is a fraction of `min(w, h)`, so parts placed at computed fractions only register at the aspect they were computed for — anchor a compound form's parts on one shared fraction (the centre is the only aspect-safe one) and offset each with `dx`/`dy`. Placement (structural). **Native:** tvOS ignores the offset |
|
|
291
293
|
| `opacity` | number 0..1 | `1` | **paint-level** layer opacity: multiplies every entity's `alpha` and the `life` envelope at draw time. Unlike `alpha` (a range baked into each entity), it is outside the structural signature, so `setParam`, a `timeline` key or a `morph` **glides** it instead of re-seeding the layer. `0` skips the layer. **Native:** ignored ⇒ 1 |
|
|
292
|
-
| `transform` | `{x?, y?, scale?, scaleX?, rotate?}` | identity | **paint-level** transform of the whole layer about the viewport centre: translate `x`/`y` (±2 in `min(w, h)` units; px under `units: "px"`, ±17280), `rotate` (degrees, ±3600), `scale` (0..8) and `scaleX` (±8, × `scale` horizontally — toward 0 reads as a turn about the vertical axis, negative mirrors). Outside the structural signature: a camera for a timed piece, a slow drift for an ambient one, and it glides under steering. Sprites are not re-rasterised, so a large `scale` enlarges pixels of soft sprites, not detail. **Native:** ignored ⇒ identity |
|
|
294
|
+
| `transform` | `{x?, y?, scale?, scaleX?, rotate?, origin?}` | identity | **paint-level** transform of the whole layer, about the viewport centre — or, with `origin: "anchor"`, about the layer's own anchor (its `position` point with `dx`/`dy`; a `list`/`table` block's anchor; without `position`, the centre of its `region`), so a word scales **in place** on every aspect (`origin` is an enum: not a steer or key target, and it steps across a morph — keep one origin per layer): translate `x`/`y` (±2 in `min(w, h)` units; px under `units: "px"`, ±17280), `rotate` (degrees, ±3600), `scale` (0..8) and `scaleX` (±8, × `scale` horizontally — toward 0 reads as a turn about the vertical axis, negative mirrors). Outside the structural signature: a camera for a timed piece, a slow drift for an ambient one, and it glides under steering. Sprites are not re-rasterised, so a large `scale` enlarges pixels of soft sprites, not detail. **Native:** ignored ⇒ identity |
|
|
295
|
+
| `group` | string | none | the name of a `groups` entry this layer paints through — see **Groups**. **Native:** ignored |
|
|
293
296
|
|
|
294
297
|
`links`: `{ k: 1..8, maxDist, color?, alpha?, width?, mode?, falloff?, closed? }`.
|
|
295
298
|
`mode: "nearest"` (default) wires each entity to its k nearest neighbors within
|
|
@@ -754,6 +757,34 @@ it genuinely cuts to a different set of layers.
|
|
|
754
757
|
base as the piece's rest state** (its end card), and a timed piece degrades
|
|
755
758
|
to a valid ambient scene.
|
|
756
759
|
|
|
760
|
+
## Groups — one handle for a multi-layer subject
|
|
761
|
+
|
|
762
|
+
A subject drawn from several layers (a character's body, eyes and mouth; a
|
|
763
|
+
record's grooves and label) can be moved, scaled and faded as one thing:
|
|
764
|
+
|
|
765
|
+
```jsonc
|
|
766
|
+
"groups": { "moon": { "transform": { "scale": 1, "y": 0 }, "opacity": 1 } },
|
|
767
|
+
"layers": [ { "key": "face", "group": "moon", ... }, { "key": "eyes", "group": "moon", ... } ]
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
- A member paints through its group: the group's `transform` wraps the
|
|
771
|
+
layer's own (a point lands at *group(layer(p))*), and the group's `opacity`
|
|
772
|
+
multiplies the layer's. A group's transform always turns about the viewport
|
|
773
|
+
centre — it is a camera; `origin: "anchor"` is for a layer's own transform.
|
|
774
|
+
- Up to 16 groups; names are 1–32 letters, digits, `-` or `_`, starting with a
|
|
775
|
+
letter. A layer's `group` must name one of them.
|
|
776
|
+
- **Paint**, outside the structural signature: `setParam("groups.moon.opacity", 0)`,
|
|
777
|
+
a `timeline` key on `groups.moon.transform.scale`, or a sequence `morph`
|
|
778
|
+
glides the whole subject — one path instead of one per layer. A group present
|
|
779
|
+
on only one end of a morph glides from the identity (no transform, opacity 1).
|
|
780
|
+
- Membership is fixed per scene: `layers.N.group` is not a steer or `timeline`
|
|
781
|
+
target. A sequence `morph` where a layer joins or leaves a group glides (the
|
|
782
|
+
end without the group paints it at the identity); moving a layer from one
|
|
783
|
+
group to another steps on the morph's first frame.
|
|
784
|
+
|
|
785
|
+
**Native:** ignored ⇒ identity transform, opacity 1 — author the base so the
|
|
786
|
+
subject reads without the group's paint.
|
|
787
|
+
|
|
757
788
|
## Seeing without eyes — the perception API
|
|
758
789
|
|
|
759
790
|
`src/perceive.ts` translates a spec into modalities a **non-vision agent** can
|
|
@@ -818,7 +849,10 @@ moves and scales its positions and sizes (sprite rotation is not modelled).
|
|
|
818
849
|
text layer. Glyphs are invisible in the luminance maps, so this is the only
|
|
819
850
|
way to confirm *what words* are on screen and how big. (Also on
|
|
820
851
|
`perceiveScene().text`.)
|
|
821
|
-
- `adviseSpec(spec)` — non-blocking advisories (
|
|
852
|
+
- `adviseSpec(spec)` — non-blocking advisories (a layer whose paint opacity —
|
|
853
|
+
its own × its group's — is 0 in the base scene and at every key boundary of
|
|
854
|
+
its `timeline` never shows, so it is not judged and its entities do not count
|
|
855
|
+
toward `dense-scene`; coverage is weighed by paint opacity) (also on
|
|
822
856
|
`perceiveScene().advisories`). Two of them are **spatial**, for static text:
|
|
823
857
|
`text-off-screen` (a text/textBlock box crosses the viewport edge by more
|
|
824
858
|
than 1%) and `text-overlap` (two static text layers share more than 10% of
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ interface SaverSpec {
|
|
|
52
52
|
* ignored ⇒ the base spec (author it as the piece's rest state).
|
|
53
53
|
*/
|
|
54
54
|
timeline?: Timeline;
|
|
55
|
+
/** Named layer groups — see `LayerGroup`. Absent ⇒ no layer is grouped (today's behaviour). */
|
|
56
|
+
groups?: Record<string, LayerGroup>;
|
|
55
57
|
/** Dimensional unit system. 'viewport' (default) = all sizes/speeds/distances are fractions of min(w,h). */
|
|
56
58
|
units?: 'viewport' | 'px';
|
|
57
59
|
/**
|
|
@@ -161,6 +163,28 @@ interface LayerTransform {
|
|
|
161
163
|
scale?: number;
|
|
162
164
|
scaleX?: number;
|
|
163
165
|
rotate?: number;
|
|
166
|
+
/**
|
|
167
|
+
* What `scale` / `scaleX` / `rotate` turn about. `'viewport'` (default) is
|
|
168
|
+
* the viewport centre — a camera move. `'anchor'` is the layer's own
|
|
169
|
+
* `position` point (with `dx`/`dy`; for a `list`/`table` layout, the block's
|
|
170
|
+
* anchor; without `position`, the centre of its `region`) — a slam word
|
|
171
|
+
* punches in place, on every aspect. Group transforms always turn about the
|
|
172
|
+
* viewport centre. **Native:** ignored with the rest of `transform`.
|
|
173
|
+
*/
|
|
174
|
+
origin?: 'viewport' | 'anchor';
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* A named set of layers painted through one shared `transform` and
|
|
178
|
+
* `opacity` (`SaverSpec.groups`, joined by `LayerSpec.group`): the group's
|
|
179
|
+
* transform wraps each member's own (it turns about the viewport centre, a
|
|
180
|
+
* camera), and its opacity multiplies theirs. Paint — outside the structural
|
|
181
|
+
* signature — so a steer (`groups.<name>.transform.scale`), a `timeline` key
|
|
182
|
+
* or a `morph` glides a whole multi-layer subject as one thing. **Native:**
|
|
183
|
+
* ignored ⇒ identity, opacity 1.
|
|
184
|
+
*/
|
|
185
|
+
interface LayerGroup {
|
|
186
|
+
transform?: LayerTransform;
|
|
187
|
+
opacity?: number;
|
|
164
188
|
}
|
|
165
189
|
/** One authored key of a `Timeline`: at scene time `t` (ms), glide `path` to `value` over `dur` ms. */
|
|
166
190
|
interface TimelineKey {
|
|
@@ -300,6 +324,8 @@ interface LayerSpec {
|
|
|
300
324
|
opacity?: number;
|
|
301
325
|
/** Paint-level transform of the whole layer — see `LayerTransform`. */
|
|
302
326
|
transform?: LayerTransform;
|
|
327
|
+
/** The name of a `SaverSpec.groups` entry this layer is painted through (see `LayerGroup`). */
|
|
328
|
+
group?: string;
|
|
303
329
|
/**
|
|
304
330
|
* Inter-entity links. `mode` picks the wiring:
|
|
305
331
|
* - 'nearest' (default): each entity's k nearest neighbors within maxDist.
|
|
@@ -835,6 +861,7 @@ declare const LIMITS: {
|
|
|
835
861
|
readonly maxLayerTransformOffsetPx: 17280;
|
|
836
862
|
readonly maxLayerTransformScale: 8;
|
|
837
863
|
readonly maxLayerTransformRotate: 3600;
|
|
864
|
+
readonly maxGroups: 16;
|
|
838
865
|
readonly maxEmitEvery: 600000;
|
|
839
866
|
readonly minEmitLife: 500;
|
|
840
867
|
readonly maxEmitGrow: 8;
|
|
@@ -2541,4 +2568,4 @@ declare const EXAMPLE_SPECS: SaverSpec[];
|
|
|
2541
2568
|
/** Lookup by saver id. */
|
|
2542
2569
|
declare const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>>;
|
|
2543
2570
|
|
|
2544
|
-
export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CapabilityTier, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, DEFAULT_KEY_DUR, DITHER_ALPHA, DITHER_TILE, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SEQUENCES, EXAMPLE_SPECS, type Entity, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, type FieldBackground, type FieldDrift, type FinishPass, type FinishSpec, GRAIN_ALPHA, GRAIN_TILE, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LayerTransform, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, MURMUR_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PHASE_DUET_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SHARD_FALL_SPEC, SIGNAL_BOARD_SPEC, SNOWFALL_SPEC, SPARSE_NIGHT_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type ScreenOp, type SequenceExample, type SequenceFramePerception, type SequenceMountContext, type SequenceSaverInstance, type SequenceSaverPlugin, type SequenceSegment, type SequenceTransition, type SpecError, type SpecMountContext, type SpecWarning, type SpriteSpec, type SteerDelta, THERMAL_FIELD_SPEC, THREE_MOVEMENTS_SEQUENCE, TYPED_CUE_SPEC, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type Timeline, type TimelineKey, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, WEB_WORK_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, canMorph, canWrapMorph, canonicalSpecPath, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, ignoredPropertyPaths, latticeHash, layerCohesion, lerpSpec, lerpValue, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, nextKeyAfter, normalizeSeed, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, readSpecPath, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, resolveTimelineAt, revealState, rgb255Luma, rotationAt, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sequenceWantsFinish, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, timelineLocalTime, timelineSampleTimes, timelineSampleTimesAfter, timelineTracks, validateSequence, validateSpec, validateSpecPaths, withoutTimeline };
|
|
2571
|
+
export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CapabilityTier, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, DEFAULT_KEY_DUR, DITHER_ALPHA, DITHER_TILE, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SEQUENCES, EXAMPLE_SPECS, type Entity, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, type FieldBackground, type FieldDrift, type FinishPass, type FinishSpec, GRAIN_ALPHA, GRAIN_TILE, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerGroup, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LayerTransform, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, MURMUR_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PHASE_DUET_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SHARD_FALL_SPEC, SIGNAL_BOARD_SPEC, SNOWFALL_SPEC, SPARSE_NIGHT_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type ScreenOp, type SequenceExample, type SequenceFramePerception, type SequenceMountContext, type SequenceSaverInstance, type SequenceSaverPlugin, type SequenceSegment, type SequenceTransition, type SpecError, type SpecMountContext, type SpecWarning, type SpriteSpec, type SteerDelta, THERMAL_FIELD_SPEC, THREE_MOVEMENTS_SEQUENCE, TYPED_CUE_SPEC, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type Timeline, type TimelineKey, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, WEB_WORK_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, canMorph, canWrapMorph, canonicalSpecPath, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, ignoredPropertyPaths, latticeHash, layerCohesion, lerpSpec, lerpValue, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, nextKeyAfter, normalizeSeed, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, readSpecPath, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, resolveTimelineAt, revealState, rgb255Luma, rotationAt, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sequenceWantsFinish, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, timelineLocalTime, timelineSampleTimes, timelineSampleTimesAfter, timelineTracks, validateSequence, validateSpec, validateSpecPaths, withoutTimeline };
|