@idle-screens/saver-metaquarium 0.9.0 → 0.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.
@@ -18,7 +18,7 @@ var ENVIRONMENTS = [
18
18
  floor: "dunes",
19
19
  rays: { strength: 0.5, color: "#bfefff", y: 900 },
20
20
  seedSalt: 162,
21
- palette: { fog: "#0a3d5c", floor: "#123c50", mote: "#bfe8ff" }
21
+ palette: { fog: "#0a3d5c", floor: "#123c50", mote: "#bfe8ff", tint: "#6fd6ff" }
22
22
  },
23
23
  {
24
24
  name: "kelp",
@@ -27,7 +27,7 @@ var ENVIRONMENTS = [
27
27
  floor: "ridges",
28
28
  rays: { strength: 0.4, color: "#9ef5d0", y: 820 },
29
29
  seedSalt: 163,
30
- palette: { fog: "#07271e", floor: "#0c2f22", mote: "#a5f2c6" }
30
+ palette: { fog: "#07271e", floor: "#0c2f22", mote: "#a5f2c6", tint: "#8fd07a" }
31
31
  },
32
32
  {
33
33
  name: "ice",
@@ -36,7 +36,7 @@ var ENVIRONMENTS = [
36
36
  floor: "flat",
37
37
  rays: { strength: 0.6, color: "#eaf8ff", y: 1e3 },
38
38
  seedSalt: 164,
39
- palette: { fog: "#12283c", floor: "#1b3d59", mote: "#d8f2ff" }
39
+ palette: { fog: "#12283c", floor: "#1b3d59", mote: "#d8f2ff", tint: "#cdeeff" }
40
40
  },
41
41
  {
42
42
  name: "vent",
@@ -54,7 +54,7 @@ var ENVIRONMENTS = [
54
54
  floor: "dunes",
55
55
  rays: { strength: 0.55, color: "#fff3b0", y: 950 },
56
56
  seedSalt: 166,
57
- palette: { fog: "#0d453f", floor: "#6e4457", mote: "#eafff4" }
57
+ palette: { fog: "#0d453f", floor: "#6e4457", mote: "#eafff4", tint: "#7ff0d8" }
58
58
  },
59
59
  {
60
60
  name: "universe",
@@ -82,6 +82,11 @@ function affordableLayers(budget, preset) {
82
82
  }
83
83
  return { floor: true, water, rayCount };
84
84
  }
85
+ function roomColor(p, room) {
86
+ const authored = p.resolvedDefault !== p.manifestDefault || p.tracked;
87
+ if (room && !authored) return room;
88
+ return p.current === void 0 ? void 0 : String(p.current);
89
+ }
85
90
 
86
91
  // src/swim.ts
87
92
  var SWIM_STYLES = [
@@ -1873,11 +1878,16 @@ function parseVignette(script, marks) {
1873
1878
  const tg = target(word.slice(1));
1874
1879
  if (tg) for (const i of who) state[i] = { ...state[i], faceActor: tg.actor === i ? null : tg.actor, facePoint: tg.point };
1875
1880
  } else if (word === "circle" || word === "follow") {
1876
- const tg = target(words[w + 1] ?? "");
1881
+ const targetName = words[w + 1] ?? "";
1882
+ const tg = target(targetName);
1877
1883
  w += 1;
1878
1884
  if (!tg) continue;
1885
+ if (word === "follow" && tg.actor === null) {
1886
+ problems.push(`beat ${bi + 1}: "follow ${targetName}" needs another actor, not a mark`);
1887
+ continue;
1888
+ }
1879
1889
  for (const i of who) {
1880
- if (word === "follow" && tg.actor !== null && tg.actor !== i) state[i] = { ...state[i], follow: tg.actor };
1890
+ if (word === "follow" && tg.actor !== i) state[i] = { ...state[i], follow: tg.actor };
1881
1891
  else if (word === "circle") state[i] = { ...state[i], circle: tg, faceActor: null };
1882
1892
  }
1883
1893
  for (const i of who) {
@@ -1891,6 +1901,9 @@ function parseVignette(script, marks) {
1891
1901
  }
1892
1902
  }
1893
1903
  }
1904
+ state.forEach((sb, i) => {
1905
+ if (sb.circle) state[i] = { ...sb, to: at[i] };
1906
+ });
1894
1907
  state.forEach((sb, i) => {
1895
1908
  if (sb.follow === null) return;
1896
1909
  const lead = state[sb.follow].to;
@@ -2159,9 +2172,13 @@ var PARAM_DOCS = {
2159
2172
  cameraAzimuth: "Orbit bearing in degrees. 0 looks at the village from the front.",
2160
2173
  cameraElevation: "Degrees above the floor. 8\u201315 is eye level with the fish; 40+ looks down on a castle.",
2161
2174
  cameraDistance: "Distance from the tank centre. 80 is a close-up, 170\u2013220 a village, 300+ a landmark.",
2175
+ shot: "A named framing to cut to: `orbit` (default), `hero` (three-quarter establishing), `front` (level, long lens), `low` (among the plants looking up), `top` (steep, the floor as a map), `surface` (looking up at the water's underside), `macro` (close on the landmark nearest the front). Azimuth and autoRotate turn it; distance scales it.",
2176
+ cameraFollow: "Ride with one fish (cast slot, 0 = first); -1 is the orbit camera. Orbit params are ignored while following. Pair with `followSpot` on the same slot for a spotlit chase.",
2177
+ followDistance: "How far behind the followed fish the camera rides, along its own path (40\u201370 a chase). Under ~18 it is the fish's eye and the fish is hidden.",
2162
2178
  autoRotate: "Turntable speed, degrees/second. 0 holds the shot (stages, vignettes); 1\u20132 is a slow reveal.",
2163
2179
  // cast
2164
2180
  fishCount: "How many fish when `fishMix` is empty (all are `fishUrl`).",
2181
+ finish: "A final full-screen pass: gentle grade, soft vignette, dither against banding, and restrained bloom on high-end devices (0 = none; never on the low tier).",
2165
2182
  fishUrl: "The single model used when `fishMix` is empty. ipfs:// or https.",
2166
2183
  fishMix: "The cast: `id[:count][@style]`, comma-separated. `100:2@drift, 257:1, seahorse:3`. Overrides fishCount/fishUrl.",
2167
2184
  dracoPath: "Where the Draco decoder lives; leave empty on a channel.",
@@ -2173,25 +2190,37 @@ var PARAM_DOCS = {
2173
2190
  maneuver: "Which set-piece moves the cast may break into.",
2174
2191
  maneuverRate: "How often maneuvers happen.",
2175
2192
  maneuverIntensity: "How big they are.",
2176
- bodyWiggle: "Body yaw while swimming, for models without an animation clip.",
2193
+ bodyWiggle: "Body yaw while swimming, for models without an animation clip. A fish the swim wave bends (`swimWave` > 0) ignores it.",
2177
2194
  lightSeek: "How much fish are drawn toward light sources.",
2178
2195
  formationBreathe: "How much a formation swells and tightens.",
2196
+ shoal: "An ambient school of small fish swimming as one body beside the cast; the odd one wanders out and back (0 = none). Up to 2.5\xD7 the device's fish cap.",
2197
+ shoalKind: "Who the school is: `neon` (blue line, red rear), `rummynose` (red face, barred tail) or `ember` (orange).",
2198
+ shoalSpeed: "How fast the school travels (0.3\u20132, default 0.8), independent of `swimSpeed`. It swims above the plants, across the front of the shot unless the camera orbits.",
2179
2199
  // look
2180
2200
  fishLighting: "`lit` (default) lights fish with a studio rig and their own glow parts; `flat` is the unlit original.",
2201
+ fishAmbient: "The water's light on the fish in lit mode: the sunlit water on their backs, the water around on their flanks, the floor under their bellies, mirrored in metal plates. Fixes fish reading dark; 0.6\u20131 in bright tanks. Dims with a follow-spot's house lights.",
2181
2202
  fishGlow: "How strongly GLOW- parts of a fish bloom and light their neighbours and the floor.",
2182
2203
  fishMetal: "`on` (default) gives METAL- parts a polished, reflective finish.",
2204
+ swimWave: "Fish bend as they swim: a wave runs nose to tail and the body curls into turns (0 = rigid wiggle). Skips the turtle, seahorse, crab, jellies and fish that already have a skeleton.",
2183
2205
  eyeLife: "Eyes blink, look, and emote (0 = painted on). Redraws each token's own pixel-grid eye; black and white only.",
2184
2206
  // water and room
2185
2207
  fogColor: "The water colour; also the background. Dark blues and purples make light sources read.",
2186
2208
  fogNear: "Where fog starts.",
2187
2209
  fogFar: "Where everything has dissolved into the water. Raise to 700\u20131000 for castles and horizons.",
2188
2210
  floorColor: "Sea-floor colour.",
2211
+ water: "Water instead of fog: red fades with distance first, then green, blue last \u2014 a red fish goes blue-green before it goes into the murk. 0.6\u20131 for most scenes; 0 is plain fog.",
2212
+ waterClarity: "With `water` on: 0 murky (colour lost fast, short reach), 0.5 as before, 1 clear (colour kept, reach \xD71.5). Bright tanks want 0.7\u20131.",
2213
+ waterTint: "The sunlit water, `#rrggbb`: distant things fade into it looking up, half of it on the level, none looking down, and the background becomes that gradient. Empty = off; with `water` on, reef, kelp, ice and lagoon bring their own.",
2214
+ dither: "`on` adds an invisible dither that removes colour banding in dark fogged gradients on TVs. Recommended with `water`; `off` (default) is byte-exact with older scenes.",
2189
2215
  moteDensity: "Suspended motes.",
2190
2216
  moteColor: "Their colour.",
2191
2217
  environment: "A room preset (floor, ceiling, light shafts). `void` for the mineral-world scenes.",
2192
2218
  floorKind: "Flat floor or terrain.",
2193
2219
  waterY: "Height of the water ceiling; -1 = the environment's own.",
2194
2220
  rayStrength: "Light shafts from the surface.",
2221
+ caustics: "The dancing net of light from the surface on the floor, rocks, plants and fish (0 = none). Sharp near the top, soft and dim deep down.",
2222
+ causticScale: "Size of the caustic cells: below 1 a fine shimmer, above 1 broad slow bands.",
2223
+ surfaceMirror: "The surface from below: a window up to the light and a rippling mirror of the tank around it (0 = the plain sheet). Needs reef, kelp, ice or lagoon; pays off on the `surface` and `low` shots. High tier reflects the real tank, mid tier the deep water.",
2195
2224
  // world
2196
2225
  propMix: "Crystals: `crystal[:count][@habit][/palette][*size]`. Habits lotus\xB7spire\xB7druse\xB7scatter\xB7coral; palettes env\xB7rainbow or a colour (blue hotpink purple seafoam yellow orange cyan white glass); `*6` is tower-sized. `crystal:3@druse/rainbow`.",
2197
2226
  envProps: "`on` lets the environment preset plant its own crystals when `propMix` is empty.",
@@ -2206,6 +2235,9 @@ var PARAM_DOCS = {
2206
2235
  interior: "`geode` sets the whole scene INSIDE a geode home: furniture, chandelier, marks like `table`, `bed`, `door`.",
2207
2236
  floraDensity: "Voxel plants around each crystal: grass, tube anemones, bulbs, sea fans, kelp \u2014 swaying, lit, shedding spores.",
2208
2237
  bubbleVents: "Bubbles from chimneys, fissures and crystals.",
2238
+ bubbleStyle: "How vent bubbles live: `classic` loops puffs; `live` grows each bubble at the vent, lets it go, rises it to the water surface (if the environment has one) and pops it, and rests a vent for a minute now and then. Distant bubbles dim instead of fattening.",
2239
+ pearling: "Oxygen pearls on the plants: beads grow on the leaves over half a minute or more, sway with them and let go (0 = none). Needs floraDensity > 0; with no flora there is nothing to pearl on.",
2240
+ co2Mist: "A fine haze of tiny bubbles from the vents, drifting on a slow current (0 = none).",
2209
2241
  marineSnow: "Drifting lit particles; gives the water depth.",
2210
2242
  skyLanterns: "The sky motif: voxel jellyfish lanterns overhead (three species), pulsing, lighting what is under them.",
2211
2243
  skyHeight: "How high the lanterns ride. 1 overhead; ~0.3 brings them down among the houses.",
@@ -2477,8 +2509,8 @@ var RECIPES = [
2477
2509
  }
2478
2510
  ];
2479
2511
  var recipe = (id) => RECIPES.find((r) => r.id === id);
2480
- function recipeTrack(params) {
2481
- return { deltas: Object.entries(params).map(([path, value]) => ({ t: 0, path, value })) };
2512
+ function recipeTrack(params, seed = 0) {
2513
+ return { program: "metaquarium", seed, deltas: Object.entries(params).map(([path, value]) => ({ t: 0, path, value })) };
2482
2514
  }
2483
2515
  function validateMetaquariumParams(params) {
2484
2516
  const out = [];
@@ -2519,6 +2551,18 @@ var METAQUARIUM_PARAMS = {
2519
2551
  cameraElevation: { type: "number", default: 15, min: -5, max: 60, ease: "smooth" },
2520
2552
  /** Camera distance from tank center, world units. */
2521
2553
  cameraDistance: { type: "number", default: 110, min: 80, max: 400, ease: "smooth" },
2554
+ /** A named framing: `orbit` (the classic camera), hero, front, low, top,
2555
+ * surface (looking up at the water's underside) or macro (close on the
2556
+ * landmark nearest the front). Azimuth and autoRotate still turn it;
2557
+ * distance scales it. A change is a cut. */
2558
+ shot: { type: "enum", default: "orbit", options: ["orbit", "hero", "front", "low", "top", "surface", "macro"], ease: "step" },
2559
+ /** Ride with one fish (a cast slot, 0 = first); -1 (default) is the orbit
2560
+ * camera. The orbit params are ignored while following. */
2561
+ cameraFollow: { type: "number", default: -1, min: -1, max: 23, ease: "step" },
2562
+ /** How far behind the followed fish the camera rides, along the path it
2563
+ * swam. Under about one body length (18) it is the fish's own eye, and the
2564
+ * fish itself is hidden. */
2565
+ followDistance: { type: "number", default: 45, min: 0, max: 160, ease: "smooth" },
2522
2566
  /** Continuous orbit speed, degrees/second. Zero by default: the tank is
2523
2567
  * still, letting the fish movement carry the scene. Steer up for an orbit. */
2524
2568
  autoRotate: { type: "number", default: 0, min: 0, max: 12, ease: "smooth" },
@@ -2553,6 +2597,23 @@ var METAQUARIUM_PARAMS = {
2553
2597
  /** Fog full-opacity distance. Kept under the camera far plane (1400);
2554
2598
  * the tank enforces far > near + 20. */
2555
2599
  fogFar: { type: "number", default: 500, min: 120, max: 1100, ease: "smooth" },
2600
+ /** Water instead of fog: red is lost with distance first, green next, blue
2601
+ * last (blue keeps today's fog curve, so everything still meets the
2602
+ * background at `fogFar`). 0 (default) is today's fog exactly. */
2603
+ water: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2604
+ /** How clear the water is, when `water` is on: 0 murky (colour lost fast,
2605
+ * a short reach), 0.5 the water as it has been, 1 clear (colour kept, the
2606
+ * far fade pushed back half again). */
2607
+ waterClarity: { type: "number", default: 0.5, min: 0, max: 1, ease: "smooth" },
2608
+ /** The sunlit water, '#rrggbb' (empty = off): what distant things fade into
2609
+ * looking up toward the light, half of it on the level, none looking down
2610
+ * into the deep — and the background with it. With \`water\` on, a room's
2611
+ * own tint applies when this is empty. */
2612
+ waterTint: { type: "string", default: "", ease: "step" },
2613
+ /** Output dither (±½ of an 8-bit step) on every material: the cure for
2614
+ * banding in dark fogged gradients on TV panels. Costs nothing per frame;
2615
+ * off by default only because turning it on recompiles every material. */
2616
+ dither: { type: "enum", default: "off", options: ["on", "off"], ease: "step" },
2556
2617
  /** Plankton mote density, 0-1 of the device tier's mote budget. Default 0
2557
2618
  * = off, so the baseline look is untouched until steered. */
2558
2619
  moteDensity: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
@@ -2583,6 +2644,18 @@ var METAQUARIUM_PARAMS = {
2583
2644
  * same sentinel reason: ramping -1 → 0 would read as FULL strength until it
2584
2645
  * snapped off. */
2585
2646
  rayStrength: { type: "number", default: -1, min: -1, max: 1, ease: "step" },
2647
+ /** Caustics: the net of light a rippled surface throws on the floor, rocks,
2648
+ * plants and fish — sharp near the surface, broad and dim deep down,
2649
+ * brightest on faces that look up. 0 compiles the stock programs. */
2650
+ caustics: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2651
+ /** Size of the caustic cells (1 = about two-thirds of a fish). */
2652
+ causticScale: { type: "number", default: 1, min: 0.4, max: 3, ease: "smooth" },
2653
+ /** The water's surface seen from below: a window straight up to the light
2654
+ * (Snell's window), a mirror of the tank everywhere else. The high tier
2655
+ * reflects the real tank when it can be seen (the \`surface\` and \`low\`
2656
+ * shots); mid tier reflects the deep water; low tier: off. Needs an
2657
+ * environment with a surface (reef, kelp, ice, lagoon). */
2658
+ surfaceMirror: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2586
2659
  /** How the fish move. `loop` is exactly the pre-style behaviour, so the
2587
2660
  * default changes nothing. A small named set on purpose: a silhouette of
2588
2661
  * movement you can name is one you can choose from. `auto` lets each
@@ -2642,6 +2715,14 @@ var METAQUARIUM_PARAMS = {
2642
2715
  * slow (~15 s) cycle. 0 (default) is the rigid lattice; 1 opens it by up
2643
2716
  * to a fifth. Only ever expands, so the spacing guarantee holds. */
2644
2717
  formationBreathe: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2718
+ /** An ambient school of small voxel fish swimming as one body beside the
2719
+ * cast — relaxed formation, burst-and-coast tails, the odd fish wandering
2720
+ * out and back. The amount sets the count (up to 2.5× the tier's fish cap). */
2721
+ shoal: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2722
+ shoalKind: { type: "enum", default: "neon", options: ["neon", "rummynose", "ember"], ease: "step" },
2723
+ /** How fast the school travels its route — its own speed, not the cast's `swimSpeed`,
2724
+ * so a slow, contemplative scene still has a school that goes somewhere. */
2725
+ shoalSpeed: { type: "number", default: 0.8, min: 0.3, max: 2, ease: "smooth" },
2645
2726
  // ---- The look. These three are the RENDERER, not settings a scene must
2646
2727
  // carry: every tank is lit, glowing and reflective with no params at all,
2647
2728
  // and the room, the cast and the camera never need to know. Each exists only
@@ -2657,8 +2738,18 @@ var METAQUARIUM_PARAMS = {
2657
2738
  * a glowing fin colours the body beside it. `flat` is the original unlit
2658
2739
  * look. Read at mount. */
2659
2740
  fishLighting: { type: "enum", default: "lit", options: ["lit", "flat"], ease: "step" },
2741
+ /** The water's light on the fish (lit mode): the bright water above on
2742
+ * their backs, the water around on their flanks, the floor under their
2743
+ * bellies — and mirrored in silvered plates. 0 is the studio alone. */
2744
+ fishAmbient: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2745
+ /** The finish: one full-screen pass — a gentle grade, dither against
2746
+ * banding, and restrained bloom on high-end devices. 0 draws straight to
2747
+ * the screen as before; the low tier never runs it. */
2748
+ finish: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2660
2749
  /** Metallic plates read as metal (a generated chrome matcap — reflection
2661
- * with no environment map and no lights). `off` is the flat unlit atlas. */
2750
+ * with no environment map and no lights). `off` is non-metallic instead —
2751
+ * still lit under `fishLighting: 'lit'`; pair with `fishLighting: 'flat'`
2752
+ * for the original unlit atlas look. */
2662
2753
  fishMetal: { type: "enum", default: "on", options: ["on", "off"], ease: "step" },
2663
2754
  /** Eye life, 0..1: blinks on a personal clock, idle saccades, pupils that
2664
2755
  * lead a turn or a climb, eyes on whoever a vignette has it talking to, a
@@ -2667,6 +2758,9 @@ var METAQUARIUM_PARAMS = {
2667
2758
  * stock eye program, byte for byte — because every param this saver adds
2668
2759
  * defaults to the previous look; a scene opts in with 1. */
2669
2760
  eyeLife: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2761
+ /** A body wave from nose to tail, beating with distance swum and curling
2762
+ * into turns. 0 keeps the legacy rigid wiggle and the stock programs. */
2763
+ swimWave: { type: "number", default: 0, min: 0, max: 1, ease: "smooth" },
2670
2764
  /** Independent mineral-world layers. Zero preserves legacy scenes; counts
2671
2765
  * are reduced by the device's existing prop budget. All motion is analytic. */
2672
2766
  rockDensity: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
@@ -2710,6 +2804,15 @@ var METAQUARIUM_PARAMS = {
2710
2804
  interior: { type: "enum", default: "none", options: ["none", "geode"], ease: "step" },
2711
2805
  floraDensity: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2712
2806
  bubbleVents: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2807
+ /** `live` puts the vents on a real bubble life: each one grows at the mouth,
2808
+ * lets go, rises, sits at the water surface and pops; a vent coughs and goes
2809
+ * quiet for a minute now and then. `classic` is the looping puffs. */
2810
+ bubbleStyle: { type: "enum", default: "classic", options: ["classic", "live"], ease: "step" },
2811
+ /** Oxygen pearls: beads that grow on the flora's leaves over half a minute
2812
+ * or more, sway with the leaf, and let go. Needs `floraDensity`. */
2813
+ pearling: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2814
+ /** A fine CO₂ mist of tiny bubbles from the vents, drifting on a current. */
2815
+ co2Mist: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2713
2816
  marineSnow: { type: "number", default: 0, min: 0, max: 1, ease: "step" },
2714
2817
  /** The sky motif: voxel jellyfish lanterns drifting in the water overhead,
2715
2818
  * pulsing as they rise and sink; a few hang far out as fogged silhouettes.
@@ -2857,6 +2960,7 @@ export {
2857
2960
  LAYER_COST,
2858
2961
  RAY_COUNT,
2859
2962
  affordableLayers,
2963
+ roomColor,
2860
2964
  SWIM_STYLES,
2861
2965
  AUTO_STYLE_BY_BREED,
2862
2966
  autoStyleFor,
@@ -2936,4 +3040,4 @@ export {
2936
3040
  paramSpaceWith,
2937
3041
  coerceNum
2938
3042
  };
2939
- //# sourceMappingURL=chunk-PHXRMLJT.js.map
3043
+ //# sourceMappingURL=chunk-YCW7OXBF.js.map