pixi-effects 0.21.0 → 0.22.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +6 -6
  3. package/ai/SKILL.md +1 -1
  4. package/ai/chat-template.html +3 -3
  5. package/ai/reference/cheatsheet.md +2 -2
  6. package/ai/reference/pitfalls.md +6 -2
  7. package/ai/reference/recipes.md +30 -0
  8. package/ai/template.html +5 -5
  9. package/ai/tools/check.mjs +14 -3
  10. package/dist/{Base-wYJQ2g5Q.d.cts → Base-BzlPgd-D.d.cts} +1 -1
  11. package/dist/{Base-CzfLGoDr.d.ts → Base-gu-5X0Cv.d.ts} +1 -1
  12. package/dist/Composition-BK5SH6J7.cjs +16 -0
  13. package/dist/{Composition-2UFPSNVN.cjs.map → Composition-BK5SH6J7.cjs.map} +1 -1
  14. package/dist/Composition-Q5TVG3HM.js +7 -0
  15. package/dist/{Composition-BVI236ZR.js.map → Composition-Q5TVG3HM.js.map} +1 -1
  16. package/dist/Controller.cjs +2 -2
  17. package/dist/Controller.d.cts +2 -2
  18. package/dist/Controller.d.ts +2 -2
  19. package/dist/Controller.js +1 -1
  20. package/dist/{Movie-CgYwa5QG.d.ts → Movie--_TJvdJa.d.ts} +1 -1
  21. package/dist/{Movie-mtX9AkQ-.d.cts → Movie-DMxOoTdW.d.cts} +1 -1
  22. package/dist/Presenter.cjs +2 -2
  23. package/dist/Presenter.d.cts +2 -2
  24. package/dist/Presenter.d.ts +2 -2
  25. package/dist/Presenter.js +1 -1
  26. package/dist/blendModes-5E4G2ZZQ.cjs +94 -0
  27. package/dist/blendModes-5E4G2ZZQ.cjs.map +1 -0
  28. package/dist/blendModes-HCP5XTNP.js +90 -0
  29. package/dist/blendModes-HCP5XTNP.js.map +1 -0
  30. package/dist/chunk-BPTW7L25.cjs +275 -0
  31. package/dist/chunk-BPTW7L25.cjs.map +1 -0
  32. package/dist/{chunk-DDIXIWXK.js → chunk-DC4JPY6A.js} +29 -276
  33. package/dist/chunk-DC4JPY6A.js.map +1 -0
  34. package/dist/chunk-E7RONUZ7.js +268 -0
  35. package/dist/chunk-E7RONUZ7.js.map +1 -0
  36. package/dist/{chunk-BPW42X7C.cjs → chunk-IFZOI3JQ.cjs} +47 -300
  37. package/dist/chunk-IFZOI3JQ.cjs.map +1 -0
  38. package/dist/chunk-K4JVI5HK.cjs +143 -0
  39. package/dist/chunk-K4JVI5HK.cjs.map +1 -0
  40. package/dist/{chunk-6JJC37ZD.cjs → chunk-MHOO2CVU.cjs} +124 -74
  41. package/dist/chunk-MHOO2CVU.cjs.map +1 -0
  42. package/dist/{chunk-MNM56B3X.js → chunk-NHICCDTC.js} +13 -3
  43. package/dist/chunk-NHICCDTC.js.map +1 -0
  44. package/dist/{chunk-NGYGFGDS.js → chunk-UQDEDYVM.js} +82 -32
  45. package/dist/chunk-UQDEDYVM.js.map +1 -0
  46. package/dist/{chunk-WTRKDIKH.cjs → chunk-UZTKEYFP.cjs} +13 -3
  47. package/dist/chunk-UZTKEYFP.cjs.map +1 -0
  48. package/dist/chunk-YEPDQ7I3.js +132 -0
  49. package/dist/chunk-YEPDQ7I3.js.map +1 -0
  50. package/dist/index.cjs +70 -67
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +4 -4
  53. package/dist/index.d.ts +4 -4
  54. package/dist/index.js +9 -6
  55. package/dist/index.js.map +1 -1
  56. package/dist/loader.css +1 -1
  57. package/dist/{music-CFEC7HKL.js → music-FUN7N225.js} +3 -3
  58. package/dist/{music-CFEC7HKL.js.map → music-FUN7N225.js.map} +1 -1
  59. package/dist/{music-UAN7DXK4.cjs → music-GEAH2XCT.cjs} +7 -7
  60. package/dist/{music-UAN7DXK4.cjs.map → music-GEAH2XCT.cjs.map} +1 -1
  61. package/dist/{sfx-EX4PUBMV.cjs → sfx-2DYTYNYW.cjs} +8 -8
  62. package/dist/{sfx-EX4PUBMV.cjs.map → sfx-2DYTYNYW.cjs.map} +1 -1
  63. package/dist/{sfx-U3GM2MED.js → sfx-3IDAJ3UZ.js} +3 -3
  64. package/dist/{sfx-U3GM2MED.js.map → sfx-3IDAJ3UZ.js.map} +1 -1
  65. package/dist/three.cjs +7 -6
  66. package/dist/three.cjs.map +1 -1
  67. package/dist/three.d.cts +2 -2
  68. package/dist/three.d.ts +2 -2
  69. package/dist/three.js +3 -2
  70. package/dist/three.js.map +1 -1
  71. package/dist/{types-YmUaViL1.d.ts → types-DBbZVKGS.d.cts} +7 -4
  72. package/dist/{types-YmUaViL1.d.cts → types-DBbZVKGS.d.ts} +7 -4
  73. package/docs/dsl.md +43 -2
  74. package/llms-full.txt +82 -7
  75. package/package.json +1 -1
  76. package/dist/Composition-2UFPSNVN.cjs +0 -14
  77. package/dist/Composition-BVI236ZR.js +0 -5
  78. package/dist/chunk-6JJC37ZD.cjs.map +0 -1
  79. package/dist/chunk-BPW42X7C.cjs.map +0 -1
  80. package/dist/chunk-DDIXIWXK.js.map +0 -1
  81. package/dist/chunk-MNM56B3X.js.map +0 -1
  82. package/dist/chunk-NGYGFGDS.js.map +0 -1
  83. package/dist/chunk-WTRKDIKH.cjs.map +0 -1
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ var chunkBPTW7L25_cjs = require('./chunk-BPTW7L25.cjs');
4
+ var chunkUZTKEYFP_cjs = require('./chunk-UZTKEYFP.cjs');
5
+
6
+ // src/core/blend.ts
7
+ var BASIC_BLEND_MODES = ["normal", "add", "screen", "multiply"];
8
+ var ADVANCED_BLEND_MODES = [
9
+ "overlay",
10
+ "soft-light",
11
+ "hard-light",
12
+ "color-dodge",
13
+ "color-burn",
14
+ "darken",
15
+ "lighten",
16
+ "difference",
17
+ "exclusion",
18
+ "hue",
19
+ "saturation",
20
+ "color",
21
+ "luminosity",
22
+ "linear-burn"
23
+ ];
24
+ var BLEND_MODES = [...BASIC_BLEND_MODES, ...ADVANCED_BLEND_MODES];
25
+ function isAdvancedBlend(mode) {
26
+ return typeof mode === "string" && ADVANCED_BLEND_MODES.includes(mode);
27
+ }
28
+ function blendProblem(mode) {
29
+ if (typeof mode === "string" && BLEND_MODES.includes(mode)) return null;
30
+ const guess = typeof mode === "string" ? chunkUZTKEYFP_cjs.suggestName(mode, BLEND_MODES) : null;
31
+ const shown = typeof mode === "string" ? `"${mode}"` : String(mode);
32
+ return `blendMode ${shown} is not supported${guess ? `; did you mean "${guess}"?` : ""} (use ${BLEND_MODES.join(", ")})`;
33
+ }
34
+ function usesAdvancedBlend(spec) {
35
+ const visit = (n) => {
36
+ if (!n || typeof n !== "object") return false;
37
+ if (Array.isArray(n)) return n.some(visit);
38
+ const o = n;
39
+ return isAdvancedBlend(o.blendMode) || visit(o.sequences) || visit(o.mask);
40
+ };
41
+ return visit(spec);
42
+ }
43
+ var sayNow = (message, spec) => console.warn(`pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(spec)}: ${message}`);
44
+ function blendUnavailableMessage(mode) {
45
+ return `blendMode "${mode}" could not be set up (the blend filters are not registered); the layer is drawn normal`;
46
+ }
47
+ function applyBlendMode(spec, display, report = sayNow) {
48
+ const mode = spec.blendMode;
49
+ if (mode === void 0) return null;
50
+ const problem = blendProblem(mode);
51
+ if (problem) {
52
+ report(problem, spec);
53
+ return null;
54
+ }
55
+ if (isAdvancedBlend(mode) && !blendRegistered()) {
56
+ report(blendUnavailableMessage(mode), spec);
57
+ return null;
58
+ }
59
+ const filters = display.filters;
60
+ if (Array.isArray(filters) && filters.length > 0) {
61
+ if (isAdvancedBlend(mode)) {
62
+ const blend = blendFilterFor(mode);
63
+ if (!blend) {
64
+ report(blendUnavailableMessage(mode), spec);
65
+ return null;
66
+ }
67
+ display.filters = [...filters, blend];
68
+ return blend;
69
+ }
70
+ filters[filters.length - 1].blendMode = mode;
71
+ return null;
72
+ }
73
+ display.blendMode = mode;
74
+ return null;
75
+ }
76
+ var factory = null;
77
+ function setBlendFilterFactory(f) {
78
+ factory = f;
79
+ }
80
+ function blendRegistered() {
81
+ return factory !== null;
82
+ }
83
+ function blendFilterFor(mode) {
84
+ return isAdvancedBlend(mode) && factory ? factory(mode) : null;
85
+ }
86
+ async function enableAdvancedBlend(renderer) {
87
+ try {
88
+ const { registerBlendModes } = await import('./blendModes-5E4G2ZZQ.cjs');
89
+ registerBlendModes();
90
+ } catch (e) {
91
+ const why = e instanceof Error ? e.message : String(e);
92
+ console.warn(`pixi-effects: the blend filters could not be loaded (${why}); layers with an advanced blendMode are drawn normal. Serve the whole dist/ folder (the filters are the blendModes-*.js file next to index.js)`);
93
+ return;
94
+ }
95
+ const bb = renderer.backBuffer;
96
+ if (bb) bb.useBackBuffer = true;
97
+ }
98
+ var MANY_ADVANCED = 10;
99
+ function drawnLeaves(sequences) {
100
+ if (!Array.isArray(sequences)) return 0;
101
+ let n = 0;
102
+ for (const s of sequences) {
103
+ if (!s || s.type === "null" || s.type === "camera" || s.type === "audio") continue;
104
+ n += s.type === "composition" ? drawnLeaves(s.sequences) : 1;
105
+ }
106
+ return n;
107
+ }
108
+ function passesOf(l, span) {
109
+ const isComposition = l.type === "composition";
110
+ if (isAdvancedBlend(l.blendMode)) return isComposition ? Math.max(1, drawnLeaves(l.sequences)) : 1;
111
+ return isComposition && Array.isArray(l.sequences) ? maxConcurrentAdvanced(l.sequences, l.duration ?? span) : 0;
112
+ }
113
+ function maxConcurrentAdvanced(layers, span) {
114
+ const events = [];
115
+ for (const l of layers) {
116
+ const w = passesOf(l, span);
117
+ if (w === 0) continue;
118
+ const at = l.at ?? 0;
119
+ const end = l.duration === void 0 ? span : at + l.duration;
120
+ const start = Math.max(0, at);
121
+ if (end > start) events.push([start, w], [end, -w]);
122
+ }
123
+ events.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
124
+ let now = 0, most = 0;
125
+ for (const [, d] of events) {
126
+ now += d;
127
+ most = Math.max(most, now);
128
+ }
129
+ return most;
130
+ }
131
+
132
+ exports.MANY_ADVANCED = MANY_ADVANCED;
133
+ exports.applyBlendMode = applyBlendMode;
134
+ exports.blendFilterFor = blendFilterFor;
135
+ exports.blendProblem = blendProblem;
136
+ exports.blendUnavailableMessage = blendUnavailableMessage;
137
+ exports.enableAdvancedBlend = enableAdvancedBlend;
138
+ exports.isAdvancedBlend = isAdvancedBlend;
139
+ exports.maxConcurrentAdvanced = maxConcurrentAdvanced;
140
+ exports.setBlendFilterFactory = setBlendFilterFactory;
141
+ exports.usesAdvancedBlend = usesAdvancedBlend;
142
+ //# sourceMappingURL=chunk-K4JVI5HK.cjs.map
143
+ //# sourceMappingURL=chunk-K4JVI5HK.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/blend.ts"],"names":["suggestName","describeLayer"],"mappings":"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","file":"chunk-K4JVI5HK.cjs","sourcesContent":["import { describeLayer } from './lint';\nimport { suggestName } from './options';\n\n/** The modes Pixi draws itself (`add`, `screen`, `multiply`) and `normal`. */\nexport const BASIC_BLEND_MODES = ['normal', 'add', 'screen', 'multiply'] as const;\n/** The modes that need the backdrop: our own `BlendModeFilter`s (`src/filters/blendModes.ts`), loaded only when a movie uses one. */\nexport const ADVANCED_BLEND_MODES = [\n 'overlay', 'soft-light', 'hard-light', 'color-dodge', 'color-burn', 'darken', 'lighten', 'difference', 'exclusion',\n 'hue', 'saturation', 'color', 'luminosity', 'linear-burn',\n] as const;\n/** Every `blendMode` there is (the one table the warnings, the types and the docs check against). */\nexport const BLEND_MODES: readonly string[] = [...BASIC_BLEND_MODES, ...ADVANCED_BLEND_MODES];\n\nexport function isAdvancedBlend(mode: unknown): boolean {\n return typeof mode === 'string' && (ADVANCED_BLEND_MODES as readonly string[]).includes(mode);\n}\n\n/** Why `mode` is not a blend mode, with the likely name and the choices; null when it is one. */\nexport function blendProblem(mode: unknown): string | null {\n if (typeof mode === 'string' && BLEND_MODES.includes(mode)) return null;\n const guess = typeof mode === 'string' ? suggestName(mode, BLEND_MODES) : null;\n const shown = typeof mode === 'string' ? `\"${mode}\"` : String(mode);\n return `blendMode ${shown} is not supported${guess ? `; did you mean \"${guess}\"?` : ''} (use ${BLEND_MODES.join(', ')})`;\n}\n\n/** Does any layer of this composition (or one nested in it, or a mask layer) use an advanced blend? */\nexport function usesAdvancedBlend(spec: unknown): boolean {\n const visit = (n: unknown): boolean => {\n if (!n || typeof n !== 'object') return false;\n if (Array.isArray(n)) return n.some(visit);\n const o = n as Record<string, unknown>;\n return isAdvancedBlend(o.blendMode) || visit(o.sequences) || visit(o.mask);\n };\n return visit(spec);\n}\n\n/** What to say about a layer's blend mode: `Composition` collects these per build, so the same mistake in 300 particle layers is said once. */\nexport type BlendReport = (message: string, spec: { name?: string; type: string }) => void;\nconst sayNow: BlendReport = (message, spec) => console.warn(`pixi-effects: ${describeLayer(spec)}: ${message}`);\n\n/** The blend filters of an advanced mode were not registered (a movie registers them in `Movie.init`, or loading them failed): the layer is drawn normal. */\nexport function blendUnavailableMessage(mode: string): string {\n return `blendMode \"${mode}\" could not be set up (the blend filters are not registered); the layer is drawn normal`;\n}\n\n/**\n * Apply a layer's `blendMode` to its display object; an unknown mode, or an advanced mode while the blend filters are not registered, says so\n * and the layer is drawn normal. Returns the blend filter it added to the layer's filter chain (the caller destroys it with the layer), if any.\n */\nexport function applyBlendMode(\n spec: { blendMode?: string; name?: string; type: string },\n display: { blendMode?: unknown; filters?: unknown },\n report: BlendReport = sayNow,\n): BlendFilterLike | null {\n const mode = spec.blendMode;\n if (mode === undefined) return null;\n const problem = blendProblem(mode);\n if (problem) { report(problem, spec); return null; }\n if (isAdvancedBlend(mode) && !blendRegistered()) { report(blendUnavailableMessage(mode), spec); return null; }\n // A container's blend mode applies INSIDE a filter's offscreen pass (against transparent black: multiply gave\n // solid black) and not to the filtered result. With filters, the pass that draws onto the backdrop is the last\n // filter's, so the mode goes there; the container stays normal.\n const filters = display.filters;\n if (Array.isArray(filters) && filters.length > 0) {\n if (isAdvancedBlend(mode)) {\n // an advanced mode is a filter of its own (it reads the backdrop): it joins the chain as the last pass\n const blend = blendFilterFor(mode);\n if (!blend) { report(blendUnavailableMessage(mode), spec); return null; }\n display.filters = [...filters, blend];\n return blend;\n }\n (filters[filters.length - 1] as { blendMode?: unknown }).blendMode = mode;\n return null;\n }\n display.blendMode = mode;\n return null;\n}\n\n/** What blend.ts needs of a blend filter (the real ones are Pixi filters; tests use plain objects). */\nexport type BlendFilterLike = { blendMode?: unknown; destroy(): void };\nlet factory: ((mode: string) => BlendFilterLike | null) | null = null;\n\n/** `filters/blendModes.ts` hands its filter maker here when it registers, so this file never imports Pixi. */\nexport function setBlendFilterFactory(f: ((mode: string) => BlendFilterLike | null) | null): void {\n factory = f;\n}\n\n/** Are the blend filters registered (a movie that uses an advanced mode registers them in `Movie.init`)? */\nexport function blendRegistered(): boolean {\n return factory !== null;\n}\n\n/** A fresh blend filter for an advanced mode, or null when the blends are not registered (or the mode is not an advanced one). */\nexport function blendFilterFor(mode: string): BlendFilterLike | null {\n return isAdvancedBlend(mode) && factory ? factory(mode) : null;\n}\n\n/**\n * Called by `Movie.init` when a layer uses an advanced mode, and only then: loads our blend filters (a separate chunk), registers them on\n * the pixi the movie runs on, and on WebGL turns the back buffer on (an advanced blend reads what is already drawn; WebGPU copies the\n * backdrop by itself, and has no such switch). A movie that uses none never reaches this, so nothing about it changes.\n */\nexport async function enableAdvancedBlend(renderer: unknown): Promise<void> {\n try {\n const { registerBlendModes } = await import('../filters/blendModes');\n registerBlendModes();\n } catch (e) {\n // a page that serves dist/index.js without its chunk, a CDN hiccup: the movie still plays, its advanced blends drawn normal\n const why = e instanceof Error ? e.message : String(e);\n console.warn(`pixi-effects: the blend filters could not be loaded (${why}); layers with an advanced blendMode are drawn normal. Serve the whole dist/ folder (the filters are the blendModes-*.js file next to index.js)`);\n return;\n }\n const bb = (renderer as { backBuffer?: { useBackBuffer: boolean } }).backBuffer;\n if (bb) bb.useBackBuffer = true;\n}\n\n/** This many layers with an advanced blend on screen at once is slow: each is a full-frame pass (measured on WebGL: about 1.5–2 ms each at 1080p). */\nexport const MANY_ADVANCED = 10;\n\ntype Counted = { at?: number; duration?: number; blendMode?: unknown; type?: string; sequences?: unknown };\n\n/** The layers a composition draws (its children each blend one by one when it has a mode): null, camera and audio layers draw nothing; nested compositions are walked. */\nfunction drawnLeaves(sequences: unknown): number {\n if (!Array.isArray(sequences)) return 0;\n let n = 0;\n for (const s of sequences as Counted[]) {\n if (!s || s.type === 'null' || s.type === 'camera' || s.type === 'audio') continue;\n n += s.type === 'composition' ? drawnLeaves(s.sequences) : 1;\n }\n return n;\n}\n\n/**\n * The full-frame passes one layer costs while it is on screen: 1 for a layer with an advanced mode; for a composition with one, one for each\n * drawn layer inside it (its children inherit the mode and blend one by one); for a composition without, the most that its own layers add\n * at one instant (a card with three blends in it, on screen with four other cards, is twelve).\n */\nfunction passesOf(l: Counted, span: number): number {\n const isComposition = l.type === 'composition';\n if (isAdvancedBlend(l.blendMode)) return isComposition ? Math.max(1, drawnLeaves(l.sequences)) : 1;\n return isComposition && Array.isArray(l.sequences) ? maxConcurrentAdvanced(l.sequences as Counted[], l.duration ?? span) : 0;\n}\n\n/** The most full-frame advanced-blend passes on screen at one instant, from the layers' `at` and `duration` (a layer with no duration lasts to the end). */\nexport function maxConcurrentAdvanced(layers: ReadonlyArray<Counted>, span: number): number {\n const events: Array<[number, number]> = [];\n for (const l of layers) {\n const w = passesOf(l, span);\n if (w === 0) continue;\n const at = l.at ?? 0;\n const end = l.duration === undefined ? span : at + l.duration;\n const start = Math.max(0, at); // a negative `at` starts before the composition: only what is after 0 is on screen\n if (end > start) events.push([start, w], [end, -w]);\n }\n events.sort((a, b) => a[0] - b[0] || a[1] - b[1]); // at one instant, the layers that end go before the ones that start\n let now = 0, most = 0;\n for (const [, d] of events) { now += d; most = Math.max(most, now); }\n return most;\n}\n"]}
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkBPW42X7C_cjs = require('./chunk-BPW42X7C.cjs');
4
- var chunkWTRKDIKH_cjs = require('./chunk-WTRKDIKH.cjs');
3
+ var chunkIFZOI3JQ_cjs = require('./chunk-IFZOI3JQ.cjs');
4
+ var chunkK4JVI5HK_cjs = require('./chunk-K4JVI5HK.cjs');
5
+ var chunkBPTW7L25_cjs = require('./chunk-BPTW7L25.cjs');
6
+ var chunkUZTKEYFP_cjs = require('./chunk-UZTKEYFP.cjs');
5
7
  var pixi_js = require('pixi.js');
6
8
  var gsap = require('gsap');
7
9
 
@@ -150,8 +152,8 @@ function readLayerTransform(target) {
150
152
  x: c.x,
151
153
  y: c.y,
152
154
  z: c.z ?? 0,
153
- rotationX: (c.rotationX ?? 0) * chunkBPW42X7C_cjs.DEG,
154
- rotationY: (c.rotationY ?? 0) * chunkBPW42X7C_cjs.DEG,
155
+ rotationX: (c.rotationX ?? 0) * chunkIFZOI3JQ_cjs.DEG,
156
+ rotationY: (c.rotationY ?? 0) * chunkIFZOI3JQ_cjs.DEG,
155
157
  rotationZ: c.rotation,
156
158
  scaleX: c.scale.x,
157
159
  scaleY: c.scale.y,
@@ -189,6 +191,7 @@ var Layer3D = class {
189
191
  blur = 0;
190
192
  blurFilter = null;
191
193
  blendWas = "normal";
194
+ blendFilter = null;
192
195
  update(host, basis) {
193
196
  this.flushRetired();
194
197
  const target = this.seq.target;
@@ -200,19 +203,19 @@ var Layer3D = class {
200
203
  if (!(needW >= 1 && needH >= 1) || !Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) return this.hide();
201
204
  const size = this.sizeFor(needW, needH);
202
205
  const frame = { x: bounds.x - pad, y: bounds.y - pad, width: size.w, height: size.h };
203
- const projected = chunkBPW42X7C_cjs.projectLayer(readLayerTransform(target), frame, basis);
206
+ const projected = chunkIFZOI3JQ_cjs.projectLayer(readLayerTransform(target), frame, basis);
204
207
  this.depth = projected.depth;
205
208
  if (!projected.visible) {
206
209
  if (!this.warnedBehind) {
207
210
  this.warnedBehind = true;
208
211
  if (this.seq.spec.hideBehindCamera) return this.hide();
209
- if (projected.depth > chunkBPW42X7C_cjs.NEAR) {
212
+ if (projected.depth > chunkIFZOI3JQ_cjs.NEAR) {
210
213
  console.warn(
211
- `pixi-effects: ${chunkBPW42X7C_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).`
214
+ `pixi-effects: ${chunkBPTW7L25_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).`
212
215
  );
213
216
  } else {
214
217
  console.warn(
215
- `pixi-effects: ${chunkBPW42X7C_cjs.describeLayer(this.seq.spec)} is at or behind the camera plane (z = ${(target.z ?? 0).toFixed(0)}) and is hidden. If that is unintended, lower its z or move the camera back (the default camera sits at z = (height/2)/tan(fov/2), about 989 for 720p at fov 40).`
218
+ `pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(this.seq.spec)} is at or behind the camera plane (z = ${(target.z ?? 0).toFixed(0)}) and is hidden. If that is unintended, lower its z or move the camera back (the default camera sits at z = (height/2)/tan(fov/2), about 989 for 720p at fov 40).`
216
219
  );
217
220
  }
218
221
  }
@@ -236,7 +239,7 @@ var Layer3D = class {
236
239
  */
237
240
  setBlur(radius) {
238
241
  const d = this.display;
239
- const r = radius > chunkBPW42X7C_cjs.MIN_BLUR ? Math.min(radius, chunkBPW42X7C_cjs.MAX_BLUR) : 0;
242
+ const r = radius > chunkIFZOI3JQ_cjs.MIN_BLUR ? Math.min(radius, chunkIFZOI3JQ_cjs.MAX_BLUR) : 0;
240
243
  this.blur = r;
241
244
  if (r === 0) {
242
245
  if (this.blurFilter) {
@@ -244,17 +247,26 @@ var Layer3D = class {
244
247
  d.blendMode = this.blendWas;
245
248
  this.blurFilter.destroy();
246
249
  this.blurFilter = null;
250
+ this.blendFilter?.destroy();
251
+ this.blendFilter = null;
247
252
  }
248
253
  return;
249
254
  }
250
255
  if (!this.blurFilter) {
251
256
  this.blurFilter = new DiscBlurFilter(r);
252
257
  this.blendWas = d.blendMode ?? "normal";
253
- if (this.blendWas !== "normal" && this.blendWas !== "inherit") {
258
+ const chain = [this.blurFilter];
259
+ if (chunkK4JVI5HK_cjs.isAdvancedBlend(this.blendWas)) {
260
+ this.blendFilter = chunkK4JVI5HK_cjs.blendFilterFor(this.blendWas);
261
+ if (this.blendFilter) {
262
+ chain.push(this.blendFilter);
263
+ d.blendMode = "normal";
264
+ }
265
+ } else if (this.blendWas !== "normal" && this.blendWas !== "inherit") {
254
266
  this.blurFilter.blendMode = this.blendWas;
255
267
  d.blendMode = "normal";
256
268
  }
257
- d.filters = [this.blurFilter];
269
+ d.filters = chain;
258
270
  }
259
271
  this.blurFilter.radius = r;
260
272
  }
@@ -335,10 +347,11 @@ var CAMERA_ALIASES = {
335
347
  };
336
348
  var CAMERA_PROPS = ["x", "y", "z", "fov", "focus", "aperture", "lookAtX", "lookAtY", "lookAtZ", "offsetX", "offsetY", "offsetZ", "lookOffsetX", "lookOffsetY", "lookOffsetZ"];
337
349
  var NEEDS_THREE_D = ["z", "rotationX", "rotationY"];
350
+ var CAMERA_ONLY = ["focus", "aperture"];
338
351
  var SKEW_KEYS = ["skew", "skewX", "skewY"];
339
352
  function lintSequence(spec, warn = defaultWarn) {
340
- const who = chunkBPW42X7C_cjs.describeLayer(spec);
341
- const keys = chunkBPW42X7C_cjs.collectPropKeys(spec);
353
+ const who = chunkBPTW7L25_cjs.describeLayer(spec);
354
+ const keys = chunkBPTW7L25_cjs.collectPropKeys(spec);
342
355
  const explained = /* @__PURE__ */ new Set();
343
356
  for (const k of keys) {
344
357
  const hint = LAYER_ALIASES[k] ?? (spec.type === "camera" ? CAMERA_ALIASES[k] : void 0);
@@ -363,6 +376,9 @@ function lintSequence(spec, warn = defaultWarn) {
363
376
  }
364
377
  return;
365
378
  }
379
+ for (const k of CAMERA_ONLY) {
380
+ if (keys.has(k)) warn(`pixi-effects: ${who}: "${k}" is a camera property and does nothing on this layer: write it in the initial / keyframes of a { type: 'camera' } layer`);
381
+ }
366
382
  if (spec.type === "audio") {
367
383
  if (spec.threeD) warn(`pixi-effects: ${who}: threeD has no effect on audio`);
368
384
  return;
@@ -379,43 +395,30 @@ function lintSequence(spec, warn = defaultWarn) {
379
395
  }
380
396
  function lintFocus(camera, siblings, warn = defaultWarn) {
381
397
  if (camera.type !== "camera") return;
382
- const who = chunkBPW42X7C_cjs.describeLayer(camera);
383
- for (const p of chunkBPW42X7C_cjs.focusProblems(camera, siblings)) {
398
+ const who = chunkBPTW7L25_cjs.describeLayer(camera);
399
+ for (const p of chunkIFZOI3JQ_cjs.focusProblems(camera, siblings)) {
384
400
  if (p.kind === "missing") {
385
401
  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`);
386
402
  } else if (p.kind === "not-threeD") {
387
403
  warn(`pixi-effects: ${who}: focus "${p.name}" is not a threeD layer, so it has no depth (the z = 0 plane is used). Write a threeD layer's name or a z number`);
404
+ } else if (p.kind === "duplicate") {
405
+ warn(`pixi-effects: ${who}: focus "${p.name}": ${p.count} layers are named "${p.name}"; the first threeD one is used. Give the layers different names`);
388
406
  } else {
389
407
  warn(`pixi-effects: ${who}: focus "${p.name}" reads only the first z of that layer; its z moves later and the focus does not follow. Animate focus itself with numbers to follow it`);
390
408
  }
391
409
  }
392
410
  }
393
411
 
394
- // src/core/blend.ts
395
- var MODES = ["normal", "add", "screen", "multiply"];
396
- function applyBlendMode(spec, display) {
397
- const mode = spec.blendMode;
398
- if (mode === void 0) return;
399
- if (!MODES.includes(mode)) {
400
- console.warn(`pixi-effects: ${chunkBPW42X7C_cjs.describeLayer(spec)}: blendMode "${mode}" is not supported (use ${MODES.join(", ")})`);
401
- return;
402
- }
403
- const filters = display.filters;
404
- if (Array.isArray(filters) && filters.length > 0) {
405
- filters[filters.length - 1].blendMode = mode;
406
- return;
407
- }
408
- display.blendMode = mode;
409
- }
410
-
411
412
  // src/sequences/Composition.ts
412
- var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
413
+ var CompositionSequence = class extends chunkIFZOI3JQ_cjs.Sequence {
413
414
  _innerContainer = null;
414
415
  _compositionShape = null;
415
416
  _children = [];
416
417
  _cameras = [];
417
418
  _layers3d = [];
418
419
  _dofSaid = { behind: false, many: false };
420
+ /** What this composition made for blend modes (filters added to layers' chains, groups and their carrier filters): destroyed with it. */
421
+ _blendOwned = [];
419
422
  /** Drawn children in stack order (cameras and target-less sequences excluded). */
420
423
  _visual = [];
421
424
  /** Layers drawn inside a null layer (`parent`): they are not in the composition's own stack. */
@@ -468,21 +471,25 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
468
471
  this.intrinsicWidth = width;
469
472
  this.intrinsicHeight = height;
470
473
  this._innerContainer = inner;
471
- const base = chunkBPW42X7C_cjs.timeRemapOf(this.spec);
472
- const span = base ? chunkBPW42X7C_cjs.contentLength(base, this.duration) : this.duration;
473
- this._remap = base ? chunkBPW42X7C_cjs.remapOf(this.spec, "time", span) : null;
474
+ const base = chunkIFZOI3JQ_cjs.timeRemapOf(this.spec);
475
+ const span = base ? chunkIFZOI3JQ_cjs.contentLength(base, this.duration) : this.duration;
476
+ this._remap = base ? chunkIFZOI3JQ_cjs.remapOf(this.spec, "time", span) : null;
474
477
  this._contentSpan = span;
475
478
  this._compositionShape = { width, height, duration: span };
476
479
  const lateKeyframes = [];
477
480
  for (const s of this.spec.sequences ?? []) {
478
481
  lintSequence(s);
479
482
  lintFocus(s, this.spec.sequences ?? []);
480
- chunkBPW42X7C_cjs.lintTiming(s, span, (message, kind) => kind === "late-keyframe" ? lateKeyframes.push(message) : console.warn(message));
481
- chunkBPW42X7C_cjs.lintText(s);
482
- chunkBPW42X7C_cjs.lintKeys(s);
483
+ chunkBPTW7L25_cjs.lintTiming(s, span, (message, kind) => kind === "late-keyframe" ? lateKeyframes.push(message) : console.warn(message));
484
+ chunkBPTW7L25_cjs.lintText(s);
485
+ chunkBPTW7L25_cjs.lintKeys(s);
486
+ }
487
+ for (const message of chunkBPTW7L25_cjs.summarizeWarnings(lateKeyframes)) console.warn(message);
488
+ const crowd = chunkK4JVI5HK_cjs.maxConcurrentAdvanced(this.spec.sequences ?? [], span);
489
+ if (crowd >= chunkK4JVI5HK_cjs.MANY_ADVANCED) {
490
+ console.warn(`pixi-effects: ${chunkBPTW7L25_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`);
483
491
  }
484
- for (const message of chunkBPW42X7C_cjs.summarizeWarnings(lateKeyframes)) console.warn(message);
485
- this._children = await chunkBPW42X7C_cjs.buildSequenceTree(
492
+ this._children = await chunkIFZOI3JQ_cjs.buildSequenceTree(
486
493
  this.spec.sequences ?? [],
487
494
  this._compositionShape,
488
495
  this.root
@@ -490,14 +497,20 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
490
497
  this._resolveParents();
491
498
  const layerNames = new Set(this._children.map((c) => c.spec.name).filter((n) => !!n));
492
499
  for (const cam of this._children) {
493
- if (!(cam instanceof chunkBPW42X7C_cjs.CameraSequence)) continue;
500
+ if (!(cam instanceof chunkIFZOI3JQ_cjs.CameraSequence)) continue;
494
501
  cam.resolveFocusNames((name) => {
495
502
  const hit = this._children.find((c) => c.spec.name === name && c.spec.threeD);
496
- return hit ? chunkBPW42X7C_cjs.layerInitialZ(hit.spec, hit.scope()) : void 0;
503
+ return hit ? chunkIFZOI3JQ_cjs.layerInitialZ(hit.spec, hit.scope()) : void 0;
497
504
  }, layerNames);
498
505
  }
506
+ const blendSaid = /* @__PURE__ */ new Map();
507
+ const report = (message, spec) => {
508
+ const seen = blendSaid.get(message);
509
+ if (seen) seen.n++;
510
+ else blendSaid.set(message, { spec, n: 1 });
511
+ };
499
512
  for (const child of this._children) {
500
- if (child instanceof chunkBPW42X7C_cjs.CameraSequence) {
513
+ if (child instanceof chunkIFZOI3JQ_cjs.CameraSequence) {
501
514
  this._cameras.push(child);
502
515
  continue;
503
516
  }
@@ -510,25 +523,57 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
510
523
  inner.addChild(layer.display);
511
524
  this._layers3d.push(layer);
512
525
  this._visual.push({ seq: child, layer });
513
- applyBlendMode(child.spec, layer.display);
526
+ const added3d = chunkK4JVI5HK_cjs.applyBlendMode(child.spec, layer.display, report);
527
+ if (added3d) this._blendOwned.push(added3d);
514
528
  if (maskSpec) {
515
- console.warn(`pixi-effects: ${chunkBPW42X7C_cjs.describeLayer(child.spec)}: mask is not supported on threeD layers yet; ignored`);
529
+ console.warn(`pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(child.spec)}: mask is not supported on threeD layers yet; ignored`);
516
530
  }
517
531
  continue;
518
532
  }
519
- into.addChild(child.target);
533
+ const mode = child.spec.blendMode;
534
+ const eraseMask = !!maskSpec && child.spec.maskInverted === true && mode !== void 0 && mode !== "normal" && chunkK4JVI5HK_cjs.blendProblem(mode) === null;
535
+ const alphaMaskLosesBlend = !!maskSpec && (maskSpec.type === "text" || maskSpec.type === "image" || maskSpec.type === "video") && !eraseMask && mode !== void 0 && mode !== "normal" && chunkK4JVI5HK_cjs.blendProblem(mode) === null;
536
+ if (alphaMaskLosesBlend) {
537
+ report(`blendMode "${mode}" cannot be used together with ${maskSpec.type === "image" ? "an" : "a"} ${maskSpec.type} layer as the mask (the blend is lost); the layer is drawn normal. Put the ${maskSpec.type} on a layer of its own with the blendMode instead of masking with it, or use maskInverted`, child.spec);
538
+ }
539
+ let wrap;
540
+ if (eraseMask) {
541
+ wrap = new pixi_js.Container();
542
+ wrap.addChild(child.target);
543
+ let carrier = null;
544
+ if (chunkK4JVI5HK_cjs.isAdvancedBlend(mode)) carrier = chunkK4JVI5HK_cjs.blendFilterFor(mode);
545
+ else {
546
+ const f = new pixi_js.AlphaFilter({ alpha: 1 });
547
+ f.blendMode = mode;
548
+ carrier = f;
549
+ }
550
+ if (carrier) {
551
+ wrap.filters = [carrier];
552
+ this._blendOwned.push(carrier);
553
+ } else report(chunkK4JVI5HK_cjs.blendUnavailableMessage(mode), child.spec);
554
+ this._blendOwned.push(wrap);
555
+ into.addChild(wrap);
556
+ } else into.addChild(child.target);
520
557
  if (holder) this._nested.push(child);
521
- else this._visual.push({ seq: child, layer: null });
522
- applyBlendMode(child.spec, child.target);
558
+ else this._visual.push({ seq: child, layer: null, wrap });
559
+ if (!wrap && !alphaMaskLosesBlend) {
560
+ const added = chunkK4JVI5HK_cjs.applyBlendMode(child.spec, child.target, report);
561
+ if (added) this._blendOwned.push(added);
562
+ }
523
563
  if (maskSpec) {
524
564
  const lifetime = maskSpec.at === void 0 ? { at: child.at, duration: maskSpec.duration ?? child.duration } : {};
525
- const built = await chunkBPW42X7C_cjs.buildSequenceTree([{ ...maskSpec, ...lifetime }], this._compositionShape, this.root);
565
+ const built = await chunkIFZOI3JQ_cjs.buildSequenceTree([{ ...maskSpec, ...lifetime }], this._compositionShape, this.root);
526
566
  const maskSeq = built[0];
527
567
  if (maskSeq?.target) {
528
- into.addChild(maskSeq.target);
568
+ (wrap ?? into).addChild(maskSeq.target);
529
569
  const inverse = child.spec.maskInverted ?? false;
530
570
  const t = child.target;
531
- if (inverse || maskSpec.type === "text") {
571
+ if (wrap) {
572
+ const mt = maskSeq.target;
573
+ const mf = Array.isArray(mt.filters) && mt.filters.length > 0 ? mt.filters[mt.filters.length - 1] : null;
574
+ if (mf) mf.blendMode = "erase";
575
+ else mt.blendMode = "erase";
576
+ } else if (inverse || maskSpec.type === "text") {
532
577
  const effect = new pixi_js.AlphaMask({ mask: maskSeq.target });
533
578
  effect.inverse = inverse;
534
579
  t.setMask?.({ mask: void 0, inverse });
@@ -539,14 +584,17 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
539
584
  t.mask = maskSeq.target;
540
585
  }
541
586
  child.maskSequence = maskSeq;
542
- maskSeq.keepHidden = maskSpec.type === "image" || maskSpec.type === "video";
587
+ maskSeq.keepHidden = !wrap && (maskSpec.type === "image" || maskSpec.type === "video");
543
588
  }
544
589
  }
545
590
  }
591
+ for (const [message, seen] of blendSaid) {
592
+ console.warn(`pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(seen.spec)}: ${message}${seen.n > 1 ? ` (and ${seen.n - 1} more layers have the same mistake)` : ""}`);
593
+ }
546
594
  if (this._layers3d.length > 0) {
547
595
  inner.sortableChildren = true;
548
596
  this._visual.forEach((v, i) => {
549
- (v.layer?.display ?? v.seq.target).zIndex = i;
597
+ (v.layer?.display ?? v.wrap ?? v.seq.target).zIndex = i;
550
598
  });
551
599
  } else if (this._cameras.length > 0) {
552
600
  console.warn("pixi-effects: camera has no effect: this composition has no threeD layers");
@@ -594,11 +642,11 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
594
642
  this._clock = clock;
595
643
  const scope = this.scope();
596
644
  if (remap.start !== void 0 && remap.timeKfs.length === 0) clock.time = remap.start;
597
- chunkBPW42X7C_cjs.bindClock(timeline, clock, "time", remap, this.duration, offset + this.at, scope);
645
+ chunkIFZOI3JQ_cjs.bindClock(timeline, clock, "time", remap, this.duration, offset + this.at, scope);
598
646
  inner.time(inner.duration());
599
647
  inner.time(0);
600
648
  last = NaN;
601
- this._warnUnreachable(chunkBPW42X7C_cjs.clockTable(remap, "time", this.duration, offset + this.at, scope, offset + this.at + this.duration), offset + this.at, offset + this.at + this.duration);
649
+ this._warnUnreachable(chunkIFZOI3JQ_cjs.clockTable(remap, "time", this.duration, offset + this.at, scope, offset + this.at + this.duration), offset + this.at, offset + this.at + this.duration);
602
650
  }
603
651
  /**
604
652
  * 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
@@ -622,7 +670,7 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
622
670
  }
623
671
  if (dwell >= 2) continue;
624
672
  console.warn(
625
- `pixi-effects: ${chunkBPW42X7C_cjs.describeLayer(child.spec)} starts at ${at}s of ${chunkBPW42X7C_cjs.describeLayer(this.spec)}'s own time, but its clock only reaches ${Number(table.min.toFixed(3))}\u2013${Number(table.max.toFixed(3))}s (${how}), so it is never visible. Layers inside a remapped composition are placed in that composition's local time.`
673
+ `pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(child.spec)} starts at ${at}s of ${chunkBPTW7L25_cjs.describeLayer(this.spec)}'s own time, but its clock only reaches ${Number(table.min.toFixed(3))}\u2013${Number(table.max.toFixed(3))}s (${how}), so it is never visible. Layers inside a remapped composition are placed in that composition's local time.`
626
674
  );
627
675
  }
628
676
  }
@@ -636,7 +684,7 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
636
684
  for (let p = this._parentOf.get(seq); p; p = this._parentOf.get(p)) out.push(p);
637
685
  return out;
638
686
  };
639
- return [...this._visual.map((v) => v.seq), ...this._nested].filter((seq) => !(seq instanceof chunkBPW42X7C_cjs.NullSequence)).map((seq) => {
687
+ return [...this._visual.map((v) => v.seq), ...this._nested].filter((seq) => !(seq instanceof chunkIFZOI3JQ_cjs.NullSequence)).map((seq) => {
640
688
  const layer = this._visual.find((v) => v.seq === seq)?.layer ?? null;
641
689
  return {
642
690
  seq,
@@ -649,14 +697,14 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
649
697
  }
650
698
  /** Match every `parent: 'name'` to a null layer; anything that cannot work is said out loud and drawn unparented. */
651
699
  _resolveParents() {
652
- const nulls = this._children.filter((c) => c instanceof chunkBPW42X7C_cjs.NullSequence);
700
+ const nulls = this._children.filter((c) => c instanceof chunkIFZOI3JQ_cjs.NullSequence);
653
701
  const nullNames = nulls.map((n) => n.spec.name).filter((n) => !!n);
654
702
  const warned = /* @__PURE__ */ new Set();
655
703
  for (const child of this._children) {
656
704
  const want = child.spec.parent;
657
705
  if (want === void 0) continue;
658
- const who = chunkBPW42X7C_cjs.describeLayer(child.spec);
659
- if (child instanceof chunkBPW42X7C_cjs.CameraSequence) {
706
+ const who = chunkBPTW7L25_cjs.describeLayer(child.spec);
707
+ if (child instanceof chunkIFZOI3JQ_cjs.CameraSequence) {
660
708
  console.warn(`pixi-effects: ${who}: a camera cannot have a parent; ignored`);
661
709
  continue;
662
710
  }
@@ -666,11 +714,11 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
666
714
  }
667
715
  const same = this._children.filter((c) => c.spec.name === want);
668
716
  if (same.length === 0) {
669
- const hint = chunkWTRKDIKH_cjs.suggestName(want, nullNames);
717
+ const hint = chunkUZTKEYFP_cjs.suggestName(want, nullNames);
670
718
  console.warn(`pixi-effects: ${who}: parent "${want}": no layer with that name${hint ? `; did you mean "${hint}"?` : ""} (the layer is drawn without a parent)`);
671
719
  continue;
672
720
  }
673
- const holder = same.find((c) => c instanceof chunkBPW42X7C_cjs.NullSequence);
721
+ const holder = same.find((c) => c instanceof chunkIFZOI3JQ_cjs.NullSequence);
674
722
  if (!holder) {
675
723
  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)`);
676
724
  continue;
@@ -714,8 +762,8 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
714
762
  childT,
715
763
  compEnd
716
764
  );
717
- const cam = active ? active.cam.state() : chunkBPW42X7C_cjs.homeCamera(width, height);
718
- const basis = chunkBPW42X7C_cjs.cameraBasis(cam, width, height);
765
+ const cam = active ? active.cam.state() : chunkIFZOI3JQ_cjs.homeCamera(width, height);
766
+ const basis = chunkIFZOI3JQ_cjs.cameraBasis(cam, width, height);
719
767
  for (const layer of this._layers3d) layer.update(host, basis);
720
768
  this._applyDepthOfField(cam, basis);
721
769
  const order = assignDepthOrder(
@@ -732,23 +780,23 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
732
780
  for (const l of this._layers3d) l.setBlur(0);
733
781
  return;
734
782
  }
735
- const focusDepth = chunkBPW42X7C_cjs.projectPoint(basis, { x: cam.lookAtX, y: cam.lookAtY, z: cam.focus ?? 0 }).depth;
736
- if (!(focusDepth > chunkBPW42X7C_cjs.NEAR)) {
783
+ const focusDepth = chunkIFZOI3JQ_cjs.projectPoint(basis, { x: cam.lookAtX, y: cam.lookAtY, z: cam.focus ?? 0 }).depth;
784
+ if (!(focusDepth > chunkIFZOI3JQ_cjs.NEAR)) {
737
785
  if (!this._dofSaid.behind) {
738
786
  this._dofSaid.behind = true;
739
- console.warn(`pixi-effects: ${chunkBPW42X7C_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)`);
787
+ console.warn(`pixi-effects: ${chunkBPTW7L25_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)`);
740
788
  }
741
789
  for (const l of this._layers3d) l.setBlur(0);
742
790
  return;
743
791
  }
744
792
  let blurred = 0;
745
793
  for (const l of this._layers3d) {
746
- l.setBlur(l.display.visible ? chunkBPW42X7C_cjs.blurRadius(aperture, basis.focal, l.depth, focusDepth) : 0);
794
+ l.setBlur(l.display.visible ? chunkIFZOI3JQ_cjs.blurRadius(aperture, basis.focal, l.depth, focusDepth) : 0);
747
795
  if (l.blur > 0) blurred++;
748
796
  }
749
- if (blurred >= chunkBPW42X7C_cjs.MANY_BLURRED && !this._dofSaid.many) {
797
+ if (blurred >= chunkIFZOI3JQ_cjs.MANY_BLURRED && !this._dofSaid.many) {
750
798
  this._dofSaid.many = true;
751
- console.warn(`pixi-effects: ${chunkBPW42X7C_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`);
799
+ console.warn(`pixi-effects: ${chunkBPTW7L25_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`);
752
800
  }
753
801
  }
754
802
  collectAudio(out, baseTime) {
@@ -762,7 +810,7 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
762
810
  const inner = [];
763
811
  for (const child of this._children) child.collectAudio(inner, 0);
764
812
  const lo = baseTime + this.at, hi = lo + this.duration;
765
- const table = chunkBPW42X7C_cjs.clockTable(remap, "time", this.duration, lo, this.scope(), hi);
813
+ const table = chunkIFZOI3JQ_cjs.clockTable(remap, "time", this.duration, lo, this.scope(), hi);
766
814
  for (const d of inner) {
767
815
  const prev = d.warp;
768
816
  out.push({ ...d, warp: (t) => t < lo || t > hi ? NaN : prev ? prev(table.at(t)) : table.at(t) });
@@ -775,6 +823,8 @@ var CompositionSequence = class extends chunkBPW42X7C_cjs.Sequence {
775
823
  for (const l of this._layers3d) l.destroy();
776
824
  this._layers3d = [];
777
825
  for (const c of this._children) c.destroy();
826
+ for (const o of this._blendOwned) o.destroy();
827
+ this._blendOwned = [];
778
828
  super.destroy();
779
829
  }
780
830
  };
@@ -786,5 +836,5 @@ function frameOf(child) {
786
836
  }
787
837
 
788
838
  exports.CompositionSequence = CompositionSequence;
789
- //# sourceMappingURL=chunk-6JJC37ZD.cjs.map
790
- //# sourceMappingURL=chunk-6JJC37ZD.cjs.map
839
+ //# sourceMappingURL=chunk-MHOO2CVU.cjs.map
840
+ //# sourceMappingURL=chunk-MHOO2CVU.cjs.map