pixi-effects 0.26.1 → 0.26.2

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/ai/chat-template.html +3 -3
  4. package/dist/Composition-H4QA24MV.js +7 -0
  5. package/dist/{Composition-Z2VY3KWZ.js.map → Composition-H4QA24MV.js.map} +1 -1
  6. package/dist/Composition-HM4YT5L7.cjs +16 -0
  7. package/dist/{Composition-THQPG4E5.cjs.map → Composition-HM4YT5L7.cjs.map} +1 -1
  8. package/dist/{chunk-H3RHEH5W.cjs → chunk-555URQHQ.cjs} +59 -59
  9. package/dist/{chunk-H3RHEH5W.cjs.map → chunk-555URQHQ.cjs.map} +1 -1
  10. package/dist/{chunk-YEVAUQ6Y.js → chunk-GBUM7X2S.js} +3 -3
  11. package/dist/{chunk-YEVAUQ6Y.js.map → chunk-GBUM7X2S.js.map} +1 -1
  12. package/dist/{chunk-EABL3UKJ.cjs → chunk-WPXDRSGN.cjs} +162 -9
  13. package/dist/chunk-WPXDRSGN.cjs.map +1 -0
  14. package/dist/{chunk-JHJNEIDI.js → chunk-X3HB4DSR.js} +162 -9
  15. package/dist/chunk-X3HB4DSR.js.map +1 -0
  16. package/dist/index.cjs +29 -29
  17. package/dist/index.js +5 -5
  18. package/dist/loader.css +1 -1
  19. package/dist/{music-AF4VTFAF.js → music-3O5MDQXY.js} +52 -6
  20. package/dist/music-3O5MDQXY.js.map +1 -0
  21. package/dist/{music-KB7YZLHP.cjs → music-4O367SPR.cjs} +52 -6
  22. package/dist/music-4O367SPR.cjs.map +1 -0
  23. package/dist/three.cjs +5 -5
  24. package/dist/three.js +1 -1
  25. package/docs/dsl.md +2 -2
  26. package/llms-full.txt +5 -4
  27. package/package.json +1 -1
  28. package/skills/pixi-effects/SKILL.md +1 -1
  29. package/skills/pixi-effects/reference/cheatsheet.md +1 -1
  30. package/skills/pixi-effects/reference/pitfalls.md +1 -0
  31. package/skills/pixi-effects/template.html +6 -6
  32. package/dist/Composition-THQPG4E5.cjs +0 -16
  33. package/dist/Composition-Z2VY3KWZ.js +0 -7
  34. package/dist/chunk-EABL3UKJ.cjs.map +0 -1
  35. package/dist/chunk-JHJNEIDI.js.map +0 -1
  36. package/dist/music-AF4VTFAF.js.map +0 -1
  37. package/dist/music-KB7YZLHP.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.26.2
4
+
5
+ **Fixed**
6
+
7
+ - **`music`: `G7`, `A7`, `E7`, `Bb7`, `C6`, `C5`, `D9` were read as single notes** (`G7` = the note G in octave 7, about 3 kHz) instead of chords, with no warning, and the documented example `G7:4` had the bug. The rule is now one line: **a capital letter starts a chord, a lowercase one is a note** (`G7` the chord, `g7` the note). A bare note in capitals (`Bb2`) is refused with its lowercase spelling (`bb2`), inside brackets any case is a note, and an unknown chord kind suggests the nearest (`Cmin7` → `Cm7`, `Csus` → `Csus4`). Scores that wrote notes in capitals (the gallery's spring-marquee did) need lowercase.
8
+
9
+ **Changed**
10
+
11
+ - **Video layers read frames in one decoder pass, not one seek per frame.** A render with a video layer is much faster: 1080p, 8 s, one layer 10.6 s → 6.1 s (the same as no video), four layers of one file 22.5 s → 6.8 s, reverse playback 11 s → 6.7 s (measured on an M1 Pro; a `getSample` per frame cost 19-25 ms, a pass under 1 ms). The pictures are the same (a snapshot of 125 frames in order, out of order, at speed 2 / 0.5 / -1 and looped matched the old reader byte for byte). Live playback is smoother too (measured by reading which frame is on screen every animation frame, 1080p, 6 s): the old reader fell behind as soon as the footage was heavy or there were several layers (one heavy layer: 79 % of the frames late, 14.5 distinct frames a second; four heavy layers: 95 % late, 6.6 a second); the new one keeps 30 a second in every case tried (0 to 0.3 % late), and a 30 s loop with two heavy layers showed no warning. Dragging the playhead forward costs about 4 ms a step instead of 62 ms; a far jump (a seek) is one frame as before (about 65 ms on heavy footage); reverse play and dragging backwards are much faster on average but still pause for 0.1-0.2 s about every 30 frames and at each loop wrap. A video layer now holds decoded frames up to about 96 MB (never fewer than 3) instead of 30 whatever the size, so a 4K layer no longer holds hundreds of MB.
12
+
3
13
  ## 0.26.1
4
14
 
5
15
  **Fixed**
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pixi-effects
2
2
 
3
- > **Status**: experimental — current release `0.26.1`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
3
+ > **Status**: experimental — current release `0.26.2`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
4
4
 
5
5
  **[Guide →](https://yjmtmtk.github.io/pixi-effects/guide/)** · **[Gallery →](https://yjmtmtk.github.io/pixi-effects/examples/gallery/)** · 50 portfolio pieces written as plain data by AI models · **[Examples →](https://yjmtmtk.github.io/pixi-effects/examples/)** · 15 numbered examples, a music lab + an in-browser playground.
6
6
 
@@ -51,8 +51,8 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
51
51
  "gsap": "https://esm.sh/gsap@3.12.5",
52
52
  "gsap/PixiPlugin": "https://esm.sh/gsap@3.12.5/PixiPlugin",
53
53
  "mediabunny": "https://esm.sh/mediabunny",
54
- "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/index.js",
55
- "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/Controller.js"
54
+ "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/index.js",
55
+ "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Controller.js"
56
56
  }
57
57
  }
58
58
  </script>
@@ -63,7 +63,7 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
63
63
  </script>
64
64
  ```
65
65
 
66
- Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.26.1/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
66
+ Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.26.2/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
67
67
 
68
68
  > **Using three.js?** Add two more entries (`three` and `pixi-effects/three`) to this importmap — see [Adding three.js](#adding-threejs-optional) below.
69
69
  >
@@ -79,7 +79,7 @@ Add two more entries to the importmap above: three.js itself, and the `pixi-effe
79
79
  "imports": {
80
80
  "...": "(everything from the importmap above)",
81
81
  "three": "https://esm.sh/three@0.178.0",
82
- "pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/three.js"
82
+ "pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/three.js"
83
83
  }
84
84
  }
85
85
  </script>
@@ -173,7 +173,7 @@ sequences: [
173
173
  This library is designed to be written by AI: a video is plain data, and every mistake we found while having AI sessions build test animations is either warned about at runtime or written down.
174
174
 
175
175
  - [`llms.txt`](./llms.txt) / [`llms-full.txt`](./llms-full.txt) — index and full text for LLM tooling (generated from the files below).
176
- - [`skills/pixi-effects/SKILL.md`](./skills/pixi-effects/SKILL.md) — a [skill](https://docs.claude.com/en/docs/claude-code/skills) (workflow, rules, verification loop). Copy the `ai/` folder to `~/.claude/skills/pixi-effects/` (or your project's `.claude/skills/`) to have Claude load it automatically when you ask for a video.
176
+ - [`skills/pixi-effects/SKILL.md`](./skills/pixi-effects/SKILL.md) — a [skill](https://docs.claude.com/en/docs/claude-code/skills) (workflow, rules, verification loop). Install it with `npx skills add yjmtmtk/pixi-effects` (or copy the `skills/pixi-effects/` folder to `~/.claude/skills/pixi-effects/` or your project's `.claude/skills/`) and your agent loads it by itself when you ask for a video.
177
177
  - [`skills/pixi-effects/reference/cheatsheet.md`](./skills/pixi-effects/reference/cheatsheet.md), [`recipes.md`](./skills/pixi-effects/reference/recipes.md) (tested), [`pitfalls.md`](./skills/pixi-effects/reference/pitfalls.md), and a starter [`skills/pixi-effects/template.html`](./skills/pixi-effects/template.html).
178
178
 
179
179
  - **Look at a page with its timeline, and scrub one with the other:** `npx pixi-effects view my-video.html` (or `node ai/tools/view.mjs …`) opens your browser on a viewer: the page on top, the timeline of every layer under it with a playhead that follows the movie. Click or drag the timeline to seek, click a layer's name to jump to where it starts, Space plays, ← / → step a frame, + / − (or Ctrl/⌘ + wheel) zoom, the names stay in place. For the human who wants to see what the AI made.
@@ -61,9 +61,9 @@
61
61
  "gsap": "https://cdn.jsdelivr.net/npm/gsap@3.12.5/+esm",
62
62
  "gsap/PixiPlugin": "https://cdn.jsdelivr.net/npm/gsap@3.12.5/PixiPlugin/+esm",
63
63
  "mediabunny": "https://cdn.jsdelivr.net/npm/mediabunny@1.61.3/+esm",
64
- "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/index.js",
65
- "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/Controller.js",
66
- "pixi-effects/presenter": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.1/dist/Presenter.js"
64
+ "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/index.js",
65
+ "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Controller.js",
66
+ "pixi-effects/presenter": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Presenter.js"
67
67
  }
68
68
  }
69
69
  </script>
@@ -0,0 +1,7 @@
1
+ export { CompositionSequence } from './chunk-GBUM7X2S.js';
2
+ import './chunk-X3HB4DSR.js';
3
+ import './chunk-AXZUKNXF.js';
4
+ import './chunk-TLYTYBWX.js';
5
+ import './chunk-BXOCEZ4U.js';
6
+ //# sourceMappingURL=Composition-H4QA24MV.js.map
7
+ //# sourceMappingURL=Composition-H4QA24MV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-Z2VY3KWZ.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-H4QA24MV.js"}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var chunk555URQHQ_cjs = require('./chunk-555URQHQ.cjs');
4
+ require('./chunk-WPXDRSGN.cjs');
5
+ require('./chunk-3DLYAPK7.cjs');
6
+ require('./chunk-ECA2WNRX.cjs');
7
+ require('./chunk-TWZNOUM7.cjs');
8
+
9
+
10
+
11
+ Object.defineProperty(exports, "CompositionSequence", {
12
+ enumerable: true,
13
+ get: function () { return chunk555URQHQ_cjs.CompositionSequence; }
14
+ });
15
+ //# sourceMappingURL=Composition-HM4YT5L7.cjs.map
16
+ //# sourceMappingURL=Composition-HM4YT5L7.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-THQPG4E5.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-HM4YT5L7.cjs"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkEABL3UKJ_cjs = require('./chunk-EABL3UKJ.cjs');
3
+ var chunkWPXDRSGN_cjs = require('./chunk-WPXDRSGN.cjs');
4
4
  var chunk3DLYAPK7_cjs = require('./chunk-3DLYAPK7.cjs');
5
5
  var chunkECA2WNRX_cjs = require('./chunk-ECA2WNRX.cjs');
6
6
  var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
@@ -34,10 +34,10 @@ var KIND_ALIASES = {
34
34
  fill: "ambient"
35
35
  };
36
36
  function lightKindProblem(kind) {
37
- if (kind === void 0 || typeof kind === "string" && chunkEABL3UKJ_cjs.LIGHT_KINDS.includes(kind)) return null;
38
- const guess = typeof kind === "string" ? KIND_ALIASES[kind.toLowerCase()] ?? chunkTWZNOUM7_cjs.suggestName(kind, chunkEABL3UKJ_cjs.LIGHT_KINDS) : null;
37
+ if (kind === void 0 || typeof kind === "string" && chunkWPXDRSGN_cjs.LIGHT_KINDS.includes(kind)) return null;
38
+ const guess = typeof kind === "string" ? KIND_ALIASES[kind.toLowerCase()] ?? chunkTWZNOUM7_cjs.suggestName(kind, chunkWPXDRSGN_cjs.LIGHT_KINDS) : null;
39
39
  const shown = typeof kind === "string" ? `"${kind}"` : String(kind);
40
- return `kind ${shown} is not a light kind${guess ? `; did you mean "${guess}"?` : ""} (use ${chunkEABL3UKJ_cjs.LIGHT_KINDS.join(", ")}); point is used`;
40
+ return `kind ${shown} is not a light kind${guess ? `; did you mean "${guess}"?` : ""} (use ${chunkWPXDRSGN_cjs.LIGHT_KINDS.join(", ")}); point is used`;
41
41
  }
42
42
  var LIGHT_ALIASES = {
43
43
  pointOfInterest: 'did you mean "lookAtX / lookAtY / lookAtZ"?',
@@ -62,24 +62,24 @@ function lightLayerProblems(spec) {
62
62
  const raw = spec;
63
63
  const kind = lightKindProblem(raw.kind);
64
64
  if (kind) out.push(kind);
65
- if (raw.falloff !== void 0 && !chunkEABL3UKJ_cjs.FALLOFFS.includes(raw.falloff)) {
66
- const guess = typeof raw.falloff === "string" ? chunkTWZNOUM7_cjs.suggestName(raw.falloff, chunkEABL3UKJ_cjs.FALLOFFS) : null;
67
- out.push(`falloff ${JSON.stringify(raw.falloff)} is not supported${guess ? `; did you mean "${guess}"?` : ""} (use ${chunkEABL3UKJ_cjs.FALLOFFS.join(", ")}); none is used`);
65
+ if (raw.falloff !== void 0 && !chunkWPXDRSGN_cjs.FALLOFFS.includes(raw.falloff)) {
66
+ const guess = typeof raw.falloff === "string" ? chunkTWZNOUM7_cjs.suggestName(raw.falloff, chunkWPXDRSGN_cjs.FALLOFFS) : null;
67
+ out.push(`falloff ${JSON.stringify(raw.falloff)} is not supported${guess ? `; did you mean "${guess}"?` : ""} (use ${chunkWPXDRSGN_cjs.FALLOFFS.join(", ")}); none is used`);
68
68
  }
69
69
  for (const k of Object.keys(raw)) {
70
- if (chunkEABL3UKJ_cjs.LIGHT_PROPS.includes(k) || k === "intensity" || k === "shadowDarkness" || k === "shadowDiffusion") {
70
+ if (chunkWPXDRSGN_cjs.LIGHT_PROPS.includes(k) || k === "intensity" || k === "shadowDarkness" || k === "shadowDiffusion") {
71
71
  out.push(`"${k}" must go inside initial / keyframes, not on the light itself`);
72
72
  } else if (LIGHT_ALIASES[k]) out.push(`"${k}" is not a property \u2014 ${LIGHT_ALIASES[k]}`);
73
73
  }
74
74
  const explained = new Set(Object.keys(LIGHT_ALIASES));
75
75
  for (const k of chunkECA2WNRX_cjs.collectPropKeys(spec)) {
76
76
  if (LIGHT_ALIASES[k]) out.push(`"${k}" is not a property \u2014 ${LIGHT_ALIASES[k]}`);
77
- else if (!explained.has(k) && !chunkEABL3UKJ_cjs.LIGHT_PROPS.includes(k)) out.push(`"${k}" has no effect on a light (use ${chunkEABL3UKJ_cjs.LIGHT_PROPS.join(", ")})`);
77
+ else if (!explained.has(k) && !chunkWPXDRSGN_cjs.LIGHT_PROPS.includes(k)) out.push(`"${k}" has no effect on a light (use ${chunkWPXDRSGN_cjs.LIGHT_PROPS.join(", ")})`);
78
78
  }
79
79
  if (numbersOf(spec, "coneFeather").some((v) => v > 1 || v < 0)) out.push("coneFeather is 0..1 (the soft part of the cone edge, as a fraction of the half angle); it is clamped");
80
80
  const big = numbersOf(spec, "intensity").find((v) => v > 10);
81
81
  if (big !== void 0) out.push(`intensity ${big} looks like a percentage: it is a multiplier (1 = full, 0.25 = a quarter); did you mean ${big / 100}?`);
82
- const kindNow = typeof raw.kind === "string" && chunkEABL3UKJ_cjs.LIGHT_KINDS.includes(raw.kind) ? raw.kind : "point";
82
+ const kindNow = typeof raw.kind === "string" && chunkWPXDRSGN_cjs.LIGHT_KINDS.includes(raw.kind) ? raw.kind : "point";
83
83
  const has = (...keys) => keys.filter((k) => bagsOf(spec).some((b) => b[k] !== void 0));
84
84
  const falloffOn = raw.falloff === "smooth" || raw.falloff === "inverseSquare";
85
85
  if (kindNow === "ambient" && raw.castsShadows) out.push("an ambient light has no direction, so it makes no shadow: castsShadows is ignored (put it on a point, spot or parallel light)");
@@ -107,17 +107,17 @@ function lightSetProblems(layers) {
107
107
  out.push("there is no ambient light, so what no light reaches is black; add { type: 'light', kind: 'ambient', initial: { intensity: 0.25 } }");
108
108
  }
109
109
  const direct = lights.filter((l) => kindOf(l) !== "ambient");
110
- if (direct.length > chunkEABL3UKJ_cjs.MAX_LIGHTS) {
111
- const dropped = direct.slice(chunkEABL3UKJ_cjs.MAX_LIGHTS).map((l) => nameOf(l, layers.indexOf(l)));
112
- out.push(`${direct.length} lights, but at most ${chunkEABL3UKJ_cjs.MAX_LIGHTS} are used (the first ${chunkEABL3UKJ_cjs.MAX_LIGHTS}, in layer order); ${dropped.join(", ")} and later are dropped. Use fewer lights`);
110
+ if (direct.length > chunkWPXDRSGN_cjs.MAX_LIGHTS) {
111
+ const dropped = direct.slice(chunkWPXDRSGN_cjs.MAX_LIGHTS).map((l) => nameOf(l, layers.indexOf(l)));
112
+ out.push(`${direct.length} lights, but at most ${chunkWPXDRSGN_cjs.MAX_LIGHTS} are used (the first ${chunkWPXDRSGN_cjs.MAX_LIGHTS}, in layer order); ${dropped.join(", ")} and later are dropped. Use fewer lights`);
113
113
  }
114
114
  const lightsCast = lights.some((l) => kindOf(l) !== "ambient" && l.castsShadows);
115
115
  const casters = layers.filter((l) => l.type !== "light" && l.castsShadows && l.threeD);
116
116
  if (casters.length > 0 && !lightsCast) out.push(`${casters.length} layer${casters.length > 1 ? "s have" : " has"} castsShadows but no light has castsShadows: add castsShadows: true to the light that should make the shadows`);
117
117
  if (lightsCast && casters.length === 0) out.push("a light has castsShadows but no layer has castsShadows: add castsShadows: true to the threeD layers that should cast a shadow");
118
- if (lightsCast && casters.length > chunkEABL3UKJ_cjs.MAX_CASTERS) {
119
- const dropped = casters.slice(chunkEABL3UKJ_cjs.MAX_CASTERS).map((c) => nameOf(c, layers.indexOf(c)));
120
- out.push(`${casters.length} layers cast shadows, but a layer receives shadows from at most ${chunkEABL3UKJ_cjs.MAX_CASTERS} (the first ${chunkEABL3UKJ_cjs.MAX_CASTERS}, in layer order); ${dropped.join(", ")} and later cast none`);
118
+ if (lightsCast && casters.length > chunkWPXDRSGN_cjs.MAX_CASTERS) {
119
+ const dropped = casters.slice(chunkWPXDRSGN_cjs.MAX_CASTERS).map((c) => nameOf(c, layers.indexOf(c)));
120
+ out.push(`${casters.length} layers cast shadows, but a layer receives shadows from at most ${chunkWPXDRSGN_cjs.MAX_CASTERS} (the first ${chunkWPXDRSGN_cjs.MAX_CASTERS}, in layer order); ${dropped.join(", ")} and later cast none`);
121
121
  }
122
122
  const softLights = lights.filter((l) => l.castsShadows && numbersOf(l, "shadowDiffusion").some((v) => v > 0));
123
123
  if (softLights.length >= SOFT_LIGHTS) {
@@ -302,9 +302,9 @@ var roundPixelsBit = {
302
302
  name: "round-pixels-bit",
303
303
  vertex: { header: `fn roundPixels(position: vec2<f32>, targetSize: vec2<f32>) -> vec2<f32> { return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0; }` }
304
304
  };
305
- var ML = chunkEABL3UKJ_cjs.MAX_LIGHTS;
306
- var MC = chunkEABL3UKJ_cjs.MAX_CASTERS;
307
- var TAPS = chunkEABL3UKJ_cjs.SHADOW_TAPS;
305
+ var ML = chunkWPXDRSGN_cjs.MAX_LIGHTS;
306
+ var MC = chunkWPXDRSGN_cjs.MAX_CASTERS;
307
+ var TAPS = chunkWPXDRSGN_cjs.SHADOW_TAPS;
308
308
  var SHADOW_KEYS = Array.from({ length: MC }, (_, j) => `uShadow${j}`);
309
309
  var WGSL_SHADOW_DECLS = SHADOW_KEYS.map((k, j) => ` @group(2) @binding(${4 + j}) var ${k}: texture_2d<f32>;`).join("\n");
310
310
  var WGSL_SHADOW_PICK = SHADOW_KEYS.map((k, j) => (j === 0 ? "" : "else ") + `if (j == ${j}) { a = textureSampleLevel(${k}, uSampler, uv, 0.0).a; }`).join(" ");
@@ -664,8 +664,8 @@ function readLayerTransform(target) {
664
664
  x: c.x,
665
665
  y: c.y,
666
666
  z: c.z ?? 0,
667
- rotationX: (c.rotationX ?? 0) * chunkEABL3UKJ_cjs.DEG,
668
- rotationY: (c.rotationY ?? 0) * chunkEABL3UKJ_cjs.DEG,
667
+ rotationX: (c.rotationX ?? 0) * chunkWPXDRSGN_cjs.DEG,
668
+ rotationY: (c.rotationY ?? 0) * chunkWPXDRSGN_cjs.DEG,
669
669
  rotationZ: c.rotation,
670
670
  scaleX: c.scale.x,
671
671
  scaleY: c.scale.y,
@@ -728,20 +728,20 @@ var Layer3D = class {
728
728
  if (!(needW >= 1 && needH >= 1) || !Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) return this.hide();
729
729
  const size = this.sizeFor(needW, needH);
730
730
  const frame = { x: bounds.x - pad, y: bounds.y - pad, width: size.w, height: size.h };
731
- const projected = chunkEABL3UKJ_cjs.projectLayer(readLayerTransform(target), frame, basis);
731
+ const projected = chunkWPXDRSGN_cjs.projectLayer(readLayerTransform(target), frame, basis);
732
732
  this.depth = projected.depth;
733
733
  {
734
734
  const lt = readLayerTransform(target);
735
- const o = chunkEABL3UKJ_cjs.layerToWorld(lt, frame.x, frame.y);
736
- const pu = chunkEABL3UKJ_cjs.layerToWorld(lt, frame.x + frame.width, frame.y);
737
- const pv = chunkEABL3UKJ_cjs.layerToWorld(lt, frame.x, frame.y + frame.height);
735
+ const o = chunkWPXDRSGN_cjs.layerToWorld(lt, frame.x, frame.y);
736
+ const pu = chunkWPXDRSGN_cjs.layerToWorld(lt, frame.x + frame.width, frame.y);
737
+ const pv = chunkWPXDRSGN_cjs.layerToWorld(lt, frame.x, frame.y + frame.height);
738
738
  this.world = { o, u: { x: pu.x - o.x, y: pu.y - o.y, z: pu.z - o.z }, v: { x: pv.x - o.x, y: pv.y - o.y, z: pv.z - o.z } };
739
739
  }
740
740
  if (!projected.visible) {
741
741
  if (!this.warnedBehind) {
742
742
  this.warnedBehind = true;
743
743
  if (this.seq.spec.hideBehindCamera) return this.hide();
744
- if (projected.depth > chunkEABL3UKJ_cjs.NEAR) {
744
+ if (projected.depth > chunkWPXDRSGN_cjs.NEAR) {
745
745
  console.warn(
746
746
  `pixi-effects: ${chunkECA2WNRX_cjs.describeLayer(this.seq.spec)}: part of it (a corner) reaches the camera plane (z = ${(target.z ?? 0).toFixed(0)}, rotationX ${(target.rotationX ?? 0).toFixed(0)}\xB0, rotationY ${(target.rotationY ?? 0).toFixed(0)}\xB0), and a layer is hidden whole when any corner is at or behind it. Tilt it less (rotationX / rotationY), make it smaller, or keep the camera further away from it (the default camera sits at z = (height/2)/tan(fov/2), about 989 for 720p at fov 40).`
747
747
  );
@@ -772,7 +772,7 @@ var Layer3D = class {
772
772
  */
773
773
  setBlur(radius) {
774
774
  const d = this.display;
775
- const r = radius > chunkEABL3UKJ_cjs.MIN_BLUR ? Math.min(radius, chunkEABL3UKJ_cjs.MAX_BLUR) : 0;
775
+ const r = radius > chunkWPXDRSGN_cjs.MIN_BLUR ? Math.min(radius, chunkWPXDRSGN_cjs.MAX_BLUR) : 0;
776
776
  this.blur = r;
777
777
  if (r === 0) {
778
778
  if (this.blurFilter) {
@@ -959,7 +959,7 @@ function lintSequence(spec, warn = defaultWarn) {
959
959
  function lintFocus(camera, siblings, warn = defaultWarn) {
960
960
  if (camera.type !== "camera") return;
961
961
  const who = chunkECA2WNRX_cjs.describeLayer(camera);
962
- for (const p of chunkEABL3UKJ_cjs.focusProblems(camera, siblings)) {
962
+ for (const p of chunkWPXDRSGN_cjs.focusProblems(camera, siblings)) {
963
963
  if (p.kind === "missing") {
964
964
  warn(`pixi-effects: ${who}: focus: no layer named "${p.name}"${p.hint ? `; did you mean "${p.hint}"?` : ""} (the z = 0 plane is used). Write a threeD layer's name or a z number`);
965
965
  } else if (p.kind === "not-threeD") {
@@ -1242,7 +1242,7 @@ var MatteSet = class {
1242
1242
  };
1243
1243
 
1244
1244
  // src/sequences/Composition.ts
1245
- var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1245
+ var CompositionSequence = class extends chunkWPXDRSGN_cjs.Sequence {
1246
1246
  _innerContainer = null;
1247
1247
  _compositionShape = null;
1248
1248
  _children = [];
@@ -1309,9 +1309,9 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1309
1309
  this.intrinsicWidth = width;
1310
1310
  this.intrinsicHeight = height;
1311
1311
  this._innerContainer = inner;
1312
- const base = chunkEABL3UKJ_cjs.timeRemapOf(this.spec);
1313
- const span = base ? chunkEABL3UKJ_cjs.contentLength(base, this.duration) : this.duration;
1314
- this._remap = base ? chunkEABL3UKJ_cjs.remapOf(this.spec, "time", span) : null;
1312
+ const base = chunkWPXDRSGN_cjs.timeRemapOf(this.spec);
1313
+ const span = base ? chunkWPXDRSGN_cjs.contentLength(base, this.duration) : this.duration;
1314
+ this._remap = base ? chunkWPXDRSGN_cjs.remapOf(this.spec, "time", span) : null;
1315
1315
  this._contentSpan = span;
1316
1316
  this._compositionShape = { width, height, duration: span };
1317
1317
  const lateKeyframes = [];
@@ -1328,7 +1328,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1328
1328
  if (crowd >= chunk3DLYAPK7_cjs.MANY_ADVANCED) {
1329
1329
  console.warn(`pixi-effects: ${chunkECA2WNRX_cjs.describeLayer(this.spec)}: ${crowd} layers with an advanced blendMode are on screen at once (a composition with one counts each layer inside it, since its children blend one by one); each is a full-frame pass (about 2 ms on WebGL). Put fewer layers in the blend (or draw the glow as one layer), or use add / screen / multiply`);
1330
1330
  }
1331
- this._children = await chunkEABL3UKJ_cjs.buildSequenceTree(
1331
+ this._children = await chunkWPXDRSGN_cjs.buildSequenceTree(
1332
1332
  this.spec.sequences ?? [],
1333
1333
  this._compositionShape,
1334
1334
  this.root
@@ -1339,22 +1339,22 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1339
1339
  if (matteNames.size > 0) {
1340
1340
  this._mattes = new MatteSet(inner, width, height);
1341
1341
  for (const name of matteNames) {
1342
- const source = this._children.find((c) => c.spec.name === name && !(c instanceof chunkEABL3UKJ_cjs.CameraSequence));
1342
+ const source = this._children.find((c) => c.spec.name === name && !(c instanceof chunkWPXDRSGN_cjs.CameraSequence));
1343
1343
  if (!source || !source.target || !canBeMatte(source.spec)) continue;
1344
1344
  const chain = [];
1345
1345
  for (let p = this._parentOf.get(source); p; p = this._parentOf.get(p)) chain.push(p);
1346
1346
  this._mattes.add(name, source, chain);
1347
1347
  }
1348
1348
  }
1349
- if (this._children.some((c) => c instanceof chunkEABL3UKJ_cjs.LightSequence)) {
1349
+ if (this._children.some((c) => c instanceof chunkWPXDRSGN_cjs.LightSequence)) {
1350
1350
  for (const message of lightSetProblems(this.spec.sequences ?? [])) console.warn(`pixi-effects: ${chunkECA2WNRX_cjs.describeLayer(this.spec)}: ${message}`);
1351
1351
  }
1352
1352
  const layerNames = new Set(this._children.map((c) => c.spec.name).filter((n) => !!n));
1353
1353
  for (const cam of this._children) {
1354
- if (!(cam instanceof chunkEABL3UKJ_cjs.CameraSequence)) continue;
1354
+ if (!(cam instanceof chunkWPXDRSGN_cjs.CameraSequence)) continue;
1355
1355
  cam.resolveFocusNames((name) => {
1356
1356
  const hit = this._children.find((c) => c.spec.name === name && c.spec.threeD);
1357
- return hit ? chunkEABL3UKJ_cjs.layerInitialZ(hit.spec, hit.scope()) : void 0;
1357
+ return hit ? chunkWPXDRSGN_cjs.layerInitialZ(hit.spec, hit.scope()) : void 0;
1358
1358
  }, layerNames);
1359
1359
  }
1360
1360
  const blendSaid = /* @__PURE__ */ new Map();
@@ -1364,11 +1364,11 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1364
1364
  else blendSaid.set(message, { spec, n: 1 });
1365
1365
  };
1366
1366
  for (const child of this._children) {
1367
- if (child instanceof chunkEABL3UKJ_cjs.CameraSequence) {
1367
+ if (child instanceof chunkWPXDRSGN_cjs.CameraSequence) {
1368
1368
  this._cameras.push(child);
1369
1369
  continue;
1370
1370
  }
1371
- if (child instanceof chunkEABL3UKJ_cjs.LightSequence) {
1371
+ if (child instanceof chunkWPXDRSGN_cjs.LightSequence) {
1372
1372
  this._lights.push(child);
1373
1373
  continue;
1374
1374
  }
@@ -1402,7 +1402,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1402
1402
  if (maskSrc.kind === "inline") {
1403
1403
  const maskSpec = maskSrc.spec;
1404
1404
  const lifetime = maskSpec.at === void 0 ? { at: child.at, duration: maskSpec.duration ?? child.duration } : {};
1405
- const built = await chunkEABL3UKJ_cjs.buildSequenceTree([{ ...maskSpec, ...lifetime }], this._compositionShape, this.root);
1405
+ const built = await chunkWPXDRSGN_cjs.buildSequenceTree([{ ...maskSpec, ...lifetime }], this._compositionShape, this.root);
1406
1406
  const maskSeq = built[0];
1407
1407
  if (maskSeq?.target) {
1408
1408
  child.maskSequence = maskSeq;
@@ -1490,11 +1490,11 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1490
1490
  this._clock = clock;
1491
1491
  const scope = this.scope();
1492
1492
  if (remap.start !== void 0 && remap.timeKfs.length === 0) clock.time = remap.start;
1493
- chunkEABL3UKJ_cjs.bindClock(timeline, clock, "time", remap, this.duration, offset + this.at, scope);
1493
+ chunkWPXDRSGN_cjs.bindClock(timeline, clock, "time", remap, this.duration, offset + this.at, scope);
1494
1494
  inner.time(inner.duration());
1495
1495
  inner.time(0);
1496
1496
  last = NaN;
1497
- this._warnUnreachable(chunkEABL3UKJ_cjs.clockTable(remap, "time", this.duration, offset + this.at, scope, offset + this.at + this.duration), offset + this.at, offset + this.at + this.duration);
1497
+ this._warnUnreachable(chunkWPXDRSGN_cjs.clockTable(remap, "time", this.duration, offset + this.at, scope, offset + this.at + this.duration), offset + this.at, offset + this.at + this.duration);
1498
1498
  }
1499
1499
  /**
1500
1500
  * A child the clock never dwells in is never visible: say so. Its `at` is in THIS composition's local time, so the usual mistake is
@@ -1532,7 +1532,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1532
1532
  for (let p = this._parentOf.get(seq); p; p = this._parentOf.get(p)) out.push(p);
1533
1533
  return out;
1534
1534
  };
1535
- return [...this._visual.map((v) => v.seq), ...this._nested].filter((seq) => !(seq instanceof chunkEABL3UKJ_cjs.NullSequence)).map((seq) => {
1535
+ return [...this._visual.map((v) => v.seq), ...this._nested].filter((seq) => !(seq instanceof chunkWPXDRSGN_cjs.NullSequence)).map((seq) => {
1536
1536
  const layer = this._visual.find((v) => v.seq === seq)?.layer ?? null;
1537
1537
  return {
1538
1538
  seq,
@@ -1541,24 +1541,24 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1541
1541
  carriers: carriersOf(seq),
1542
1542
  depthBlur: layer?.blur ?? 0,
1543
1543
  // how lit it is (threeD layers that receive the lights of the last frame only); computed here, not per frame
1544
- light: layer && this._lighting && layer.world && layer.spec.lit !== false ? chunkEABL3UKJ_cjs.lightLevel(layer.world, this._lighting.cam, this._lighting.states) : void 0
1544
+ light: layer && this._lighting && layer.world && layer.spec.lit !== false ? chunkWPXDRSGN_cjs.lightLevel(layer.world, this._lighting.cam, this._lighting.states) : void 0
1545
1545
  };
1546
1546
  });
1547
1547
  }
1548
1548
  /** Match every `parent: 'name'` to a null layer; anything that cannot work is said out loud and drawn unparented. */
1549
1549
  _resolveParents() {
1550
- const nulls = this._children.filter((c) => c instanceof chunkEABL3UKJ_cjs.NullSequence);
1550
+ const nulls = this._children.filter((c) => c instanceof chunkWPXDRSGN_cjs.NullSequence);
1551
1551
  const nullNames = nulls.map((n) => n.spec.name).filter((n) => !!n);
1552
1552
  const warned = /* @__PURE__ */ new Set();
1553
1553
  for (const child of this._children) {
1554
1554
  const want = child.spec.parent;
1555
1555
  if (want === void 0) continue;
1556
1556
  const who = chunkECA2WNRX_cjs.describeLayer(child.spec);
1557
- if (child instanceof chunkEABL3UKJ_cjs.CameraSequence) {
1557
+ if (child instanceof chunkWPXDRSGN_cjs.CameraSequence) {
1558
1558
  console.warn(`pixi-effects: ${who}: a camera cannot have a parent; ignored`);
1559
1559
  continue;
1560
1560
  }
1561
- if (child instanceof chunkEABL3UKJ_cjs.LightSequence) {
1561
+ if (child instanceof chunkWPXDRSGN_cjs.LightSequence) {
1562
1562
  console.warn(`pixi-effects: ${who}: a light cannot have a parent (parent "${want}" ignored: move the light with its own x / y / z keyframes)`);
1563
1563
  continue;
1564
1564
  }
@@ -1572,7 +1572,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1572
1572
  console.warn(`pixi-effects: ${who}: parent "${want}": no layer with that name${hint ? `; did you mean "${hint}"?` : ""} (the layer is drawn without a parent)`);
1573
1573
  continue;
1574
1574
  }
1575
- const holder = same.find((c) => c instanceof chunkEABL3UKJ_cjs.NullSequence);
1575
+ const holder = same.find((c) => c instanceof chunkWPXDRSGN_cjs.NullSequence);
1576
1576
  if (!holder) {
1577
1577
  console.warn(`pixi-effects: ${who}: parent "${want}" is a ${same[0].spec.type} layer; only { type: 'null' } layers can be parents (the layer is drawn without a parent)`);
1578
1578
  continue;
@@ -1617,8 +1617,8 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1617
1617
  childT,
1618
1618
  compEnd
1619
1619
  );
1620
- const cam = active ? active.cam.state() : chunkEABL3UKJ_cjs.homeCamera(width, height);
1621
- const basis = chunkEABL3UKJ_cjs.cameraBasis(cam, width, height);
1620
+ const cam = active ? active.cam.state() : chunkWPXDRSGN_cjs.homeCamera(width, height);
1621
+ const basis = chunkWPXDRSGN_cjs.cameraBasis(cam, width, height);
1622
1622
  for (const layer of this._layers3d) layer.update(host, basis);
1623
1623
  this._applyLighting(childT, compEnd, basis, active?.cam ?? null);
1624
1624
  this._applyDepthOfField(cam, basis);
@@ -1643,7 +1643,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1643
1643
  return t >= w.start && (t < w.end || w.end >= compEnd && t <= w.end);
1644
1644
  });
1645
1645
  const states = live.map((l) => l.state());
1646
- const packed = states.length > 0 ? chunkEABL3UKJ_cjs.packLights(states) : null;
1646
+ const packed = states.length > 0 ? chunkWPXDRSGN_cjs.packLights(states) : null;
1647
1647
  this._lighting = states.length > 0 ? { states, cam: { x: basis.cx, y: basis.cy, z: basis.cz } } : null;
1648
1648
  const shadowing = states.some((s) => s.castsShadows);
1649
1649
  const casters = shadowing ? this._layers3d.filter((l) => l.spec.castsShadows && l.display.visible && l.world && l.source) : [];
@@ -1652,7 +1652,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1652
1652
  const mat = l.setLit(true);
1653
1653
  if (!mat || !l.world) continue;
1654
1654
  const lit = l.spec.lit !== false;
1655
- const mine = lit ? casters.filter((c) => c !== l).slice(0, chunkEABL3UKJ_cjs.MAX_CASTERS).map((c) => ({ frame: c.world, source: c.source })) : [];
1655
+ const mine = lit ? casters.filter((c) => c !== l).slice(0, chunkWPXDRSGN_cjs.MAX_CASTERS).map((c) => ({ frame: c.world, source: c.source })) : [];
1656
1656
  mat.update(l.world, camInfo, lit ? packed : null, fog, mine);
1657
1657
  }
1658
1658
  }
@@ -1663,8 +1663,8 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1663
1663
  for (const l of this._layers3d) l.setBlur(0);
1664
1664
  return;
1665
1665
  }
1666
- const focusDepth = chunkEABL3UKJ_cjs.projectPoint(basis, { x: cam.lookAtX, y: cam.lookAtY, z: cam.focus ?? 0 }).depth;
1667
- if (!(focusDepth > chunkEABL3UKJ_cjs.NEAR)) {
1666
+ const focusDepth = chunkWPXDRSGN_cjs.projectPoint(basis, { x: cam.lookAtX, y: cam.lookAtY, z: cam.focus ?? 0 }).depth;
1667
+ if (!(focusDepth > chunkWPXDRSGN_cjs.NEAR)) {
1668
1668
  if (!this._dofSaid.behind) {
1669
1669
  this._dofSaid.behind = true;
1670
1670
  console.warn(`pixi-effects: ${chunkECA2WNRX_cjs.describeLayer(this.spec)}: the camera's focus (z = ${(cam.focus ?? 0).toFixed(0)}) is at or behind the camera, so nothing is blurred. Put focus in front of the camera (a z below the camera's z)`);
@@ -1674,10 +1674,10 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1674
1674
  }
1675
1675
  let blurred = 0;
1676
1676
  for (const l of this._layers3d) {
1677
- l.setBlur(l.display.visible ? chunkEABL3UKJ_cjs.blurRadius(aperture, basis.focal, l.depth, focusDepth) : 0);
1677
+ l.setBlur(l.display.visible ? chunkWPXDRSGN_cjs.blurRadius(aperture, basis.focal, l.depth, focusDepth) : 0);
1678
1678
  if (l.blur > 0) blurred++;
1679
1679
  }
1680
- if (blurred >= chunkEABL3UKJ_cjs.MANY_BLURRED && !this._dofSaid.many) {
1680
+ if (blurred >= chunkWPXDRSGN_cjs.MANY_BLURRED && !this._dofSaid.many) {
1681
1681
  this._dofSaid.many = true;
1682
1682
  console.warn(`pixi-effects: ${chunkECA2WNRX_cjs.describeLayer(this.spec)}: ${blurred} layers are blurred by depth of field at once; each costs a filter pass per frame (WebGPU more). Merge the far layers or lower aperture`);
1683
1683
  }
@@ -1693,7 +1693,7 @@ var CompositionSequence = class extends chunkEABL3UKJ_cjs.Sequence {
1693
1693
  const inner = [];
1694
1694
  for (const child of this._children) child.collectAudio(inner, 0);
1695
1695
  const lo = baseTime + this.at, hi = lo + this.duration;
1696
- const table = chunkEABL3UKJ_cjs.clockTable(remap, "time", this.duration, lo, this.scope(), hi);
1696
+ const table = chunkWPXDRSGN_cjs.clockTable(remap, "time", this.duration, lo, this.scope(), hi);
1697
1697
  for (const d of inner) {
1698
1698
  const prev = d.warp;
1699
1699
  out.push({ ...d, warp: (t) => t < lo || t > hi ? NaN : prev ? prev(table.at(t)) : table.at(t) });
@@ -1723,5 +1723,5 @@ function frameOf(child) {
1723
1723
 
1724
1724
  exports.CompositionSequence = CompositionSequence;
1725
1725
  exports.maskSourceOf = maskSourceOf;
1726
- //# sourceMappingURL=chunk-H3RHEH5W.cjs.map
1727
- //# sourceMappingURL=chunk-H3RHEH5W.cjs.map
1726
+ //# sourceMappingURL=chunk-555URQHQ.cjs.map
1727
+ //# sourceMappingURL=chunk-555URQHQ.cjs.map