pixi-effects 0.28.1 → 0.29.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 (91) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +11 -11
  3. package/ai/chat-template.html +5 -5
  4. package/ai/tools/check.mjs +18 -3
  5. package/ai/tools/pixi-effects.mjs +1 -1
  6. package/ai/tools/render.mjs +14 -9
  7. package/ai/tools/view.mjs +108 -16
  8. package/dist/Base-CB1_FPZD.d.cts +60 -0
  9. package/dist/Base-Ne74ztNl.d.ts +60 -0
  10. package/dist/Composition-MUKR3FYD.cjs +16 -0
  11. package/dist/{Composition-NI74UJT3.cjs.map → Composition-MUKR3FYD.cjs.map} +1 -1
  12. package/dist/Composition-RJGA7KDU.js +7 -0
  13. package/dist/{Composition-HFEVIYHN.js.map → Composition-RJGA7KDU.js.map} +1 -1
  14. package/dist/Controller.cjs +73 -45
  15. package/dist/Controller.cjs.map +1 -1
  16. package/dist/Controller.d.cts +16 -22
  17. package/dist/Controller.d.ts +16 -22
  18. package/dist/Controller.js +74 -40
  19. package/dist/Controller.js.map +1 -1
  20. package/dist/{Movie-CHcM8HNB.d.ts → Movie-C2rZFkrO.d.ts} +227 -119
  21. package/dist/{Movie-Cx5ozUGb.d.cts → Movie-DdnpLpw1.d.cts} +227 -119
  22. package/dist/{blendModes-HDOP6R7T.cjs → blendModes-ETMYWATF.cjs} +5 -5
  23. package/dist/{blendModes-HDOP6R7T.cjs.map → blendModes-ETMYWATF.cjs.map} +1 -1
  24. package/dist/{blendModes-PAVTW3BO.js → blendModes-RIVZXL5A.js} +4 -4
  25. package/dist/{blendModes-PAVTW3BO.js.map → blendModes-RIVZXL5A.js.map} +1 -1
  26. package/dist/{chunk-P4GY3Z4G.cjs → chunk-2DXPTKQZ.cjs} +6 -6
  27. package/dist/chunk-2DXPTKQZ.cjs.map +1 -0
  28. package/dist/{chunk-TYWFKCPY.js → chunk-4KB3GUEK.js} +5 -5
  29. package/dist/chunk-4KB3GUEK.js.map +1 -0
  30. package/dist/{chunk-WEJAQAFX.js → chunk-A3Q3SDSH.js} +35 -28
  31. package/dist/chunk-A3Q3SDSH.js.map +1 -0
  32. package/dist/chunk-CRQFDY7E.js +4182 -0
  33. package/dist/chunk-CRQFDY7E.js.map +1 -0
  34. package/dist/chunk-HREBQAY4.cjs +4206 -0
  35. package/dist/chunk-HREBQAY4.cjs.map +1 -0
  36. package/dist/{chunk-ZMAD3KJU.cjs → chunk-LYOKH7KE.cjs} +22 -3
  37. package/dist/chunk-LYOKH7KE.cjs.map +1 -0
  38. package/dist/{chunk-45QKLD6M.js → chunk-RCVZX2JP.js} +22 -3
  39. package/dist/chunk-RCVZX2JP.js.map +1 -0
  40. package/dist/{chunk-SBOVUZZY.cjs → chunk-WHNADXXG.cjs} +121 -114
  41. package/dist/chunk-WHNADXXG.cjs.map +1 -0
  42. package/dist/{chunk-AK54FIWM.js → chunk-ZAXYPXKW.js} +17 -6
  43. package/dist/chunk-ZAXYPXKW.js.map +1 -0
  44. package/dist/{chunk-MZCDBRTY.cjs → chunk-ZVUO325O.cjs} +34 -23
  45. package/dist/chunk-ZVUO325O.cjs.map +1 -0
  46. package/dist/index.cjs +106 -4480
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +15 -60
  49. package/dist/index.d.ts +15 -60
  50. package/dist/index.js +6 -4455
  51. package/dist/index.js.map +1 -1
  52. package/dist/loader.css +1 -1
  53. package/dist/{Presenter.cjs → present.cjs} +370 -31
  54. package/dist/present.cjs.map +1 -0
  55. package/dist/present.d.cts +278 -0
  56. package/dist/present.d.ts +278 -0
  57. package/dist/{Presenter.js → present.js} +358 -32
  58. package/dist/present.js.map +1 -0
  59. package/dist/three.cjs +6 -6
  60. package/dist/three.d.cts +2 -2
  61. package/dist/three.d.ts +2 -2
  62. package/dist/three.js +2 -2
  63. package/dist/{types-DpK1vwcl.d.ts → types-BzIB65Vk.d.cts} +11 -265
  64. package/dist/{types-DpK1vwcl.d.cts → types-BzIB65Vk.d.ts} +11 -265
  65. package/docs/api.md +44 -77
  66. package/docs/dsl.md +16 -14
  67. package/llms-full.txt +90 -118
  68. package/llms.txt +1 -1
  69. package/package.json +5 -5
  70. package/skills/pixi-effects/SKILL.md +6 -6
  71. package/skills/pixi-effects/reference/cheatsheet.md +9 -9
  72. package/skills/pixi-effects/reference/direction.md +4 -2
  73. package/skills/pixi-effects/reference/pitfalls.md +7 -6
  74. package/skills/pixi-effects/reference/recipes.md +4 -4
  75. package/skills/pixi-effects/template.html +7 -7
  76. package/dist/Base-C6f0fE8j.d.ts +0 -109
  77. package/dist/Base-DI1FCGcH.d.cts +0 -109
  78. package/dist/Composition-HFEVIYHN.js +0 -7
  79. package/dist/Composition-NI74UJT3.cjs +0 -16
  80. package/dist/Presenter.cjs.map +0 -1
  81. package/dist/Presenter.d.cts +0 -122
  82. package/dist/Presenter.d.ts +0 -122
  83. package/dist/Presenter.js.map +0 -1
  84. package/dist/chunk-45QKLD6M.js.map +0 -1
  85. package/dist/chunk-AK54FIWM.js.map +0 -1
  86. package/dist/chunk-MZCDBRTY.cjs.map +0 -1
  87. package/dist/chunk-P4GY3Z4G.cjs.map +0 -1
  88. package/dist/chunk-SBOVUZZY.cjs.map +0 -1
  89. package/dist/chunk-TYWFKCPY.js.map +0 -1
  90. package/dist/chunk-WEJAQAFX.js.map +0 -1
  91. package/dist/chunk-ZMAD3KJU.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/blend.ts"],"names":["suggestName","describeLayer"],"mappings":"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","file":"chunk-2DXPTKQZ.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) || visit(o.layer); // (`layer`: a mask written as { layer: <spec>, invert })\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,4 +1,4 @@
1
- import { describeLayer } from './chunk-45QKLD6M.js';
1
+ import { describeLayer } from './chunk-RCVZX2JP.js';
2
2
  import { suggestName } from './chunk-BXOCEZ4U.js';
3
3
 
4
4
  // src/core/blend.ts
@@ -34,7 +34,7 @@ function usesAdvancedBlend(spec) {
34
34
  if (!n || typeof n !== "object") return false;
35
35
  if (Array.isArray(n)) return n.some(visit);
36
36
  const o = n;
37
- return isAdvancedBlend(o.blendMode) || visit(o.sequences) || visit(o.mask);
37
+ return isAdvancedBlend(o.blendMode) || visit(o.sequences) || visit(o.mask) || visit(o.layer);
38
38
  };
39
39
  return visit(spec);
40
40
  }
@@ -83,7 +83,7 @@ function blendFilterFor(mode) {
83
83
  }
84
84
  async function enableAdvancedBlend(renderer) {
85
85
  try {
86
- const { registerBlendModes } = await import('./blendModes-PAVTW3BO.js');
86
+ const { registerBlendModes } = await import('./blendModes-RIVZXL5A.js');
87
87
  registerBlendModes();
88
88
  } catch (e) {
89
89
  const why = e instanceof Error ? e.message : String(e);
@@ -128,5 +128,5 @@ function maxConcurrentAdvanced(layers, span) {
128
128
  }
129
129
 
130
130
  export { MANY_ADVANCED, applyBlendMode, blendFilterFor, enableAdvancedBlend, isAdvancedBlend, maxConcurrentAdvanced, setBlendFilterFactory, usesAdvancedBlend };
131
- //# sourceMappingURL=chunk-TYWFKCPY.js.map
132
- //# sourceMappingURL=chunk-TYWFKCPY.js.map
131
+ //# sourceMappingURL=chunk-4KB3GUEK.js.map
132
+ //# sourceMappingURL=chunk-4KB3GUEK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/blend.ts"],"names":[],"mappings":"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","file":"chunk-4KB3GUEK.js","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) || visit(o.layer); // (`layer`: a mask written as { layer: <spec>, invert })\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,6 +1,6 @@
1
- import { MAX_CASTERS, Sequence, timeRemapOf, contentLength, remapOf, buildSequenceTree, CameraSequence, LightSequence, layerInitialZ, createTimeline, bindClock, clockTable, NullSequence, lightLevel, homeCamera, cameraBasis, packLights, projectPoint, NEAR, blurRadius, MANY_BLURRED, focusProblems, MAX_LIGHTS, projectLayer, layerToWorld, FALLOFFS, LIGHT_PROPS, LIGHT_KINDS, MIN_BLUR, MAX_BLUR, DEG, SHADOW_TAPS } from './chunk-AK54FIWM.js';
2
- import { maxConcurrentAdvanced, MANY_ADVANCED, applyBlendMode, isAdvancedBlend, blendFilterFor } from './chunk-TYWFKCPY.js';
3
- import { describeLayer, lintTiming, lintText, lintKeys, summarizeWarnings, collectPropKeys } from './chunk-45QKLD6M.js';
1
+ import { MAX_CASTERS, Sequence, timeRemapOf, contentLength, remapOf, buildSequenceTree, CameraSequence, LightSequence, layerInitialZ, createTimeline, bindClock, clockTable, NullSequence, lightLevel, homeCamera, cameraBasis, packLights, projectPoint, NEAR, blurRadius, MANY_BLURRED, focusProblems, MAX_LIGHTS, projectLayer, layerToWorld, FALLOFFS, LIGHT_PROPS, LIGHT_KINDS, MIN_BLUR, MAX_BLUR, DEG, SHADOW_TAPS } from './chunk-ZAXYPXKW.js';
2
+ import { maxConcurrentAdvanced, MANY_ADVANCED, applyBlendMode, isAdvancedBlend, blendFilterFor } from './chunk-4KB3GUEK.js';
3
+ import { describeLayer, lintTiming, lintText, lintKeys, summarizeWarnings, collectPropKeys } from './chunk-RCVZX2JP.js';
4
4
  import { suggestName } from './chunk-BXOCEZ4U.js';
5
5
  import { Container, Rectangle, RenderTexture, Sprite, Matrix, PerspectiveMesh, Texture, Filter, UniformGroup, GpuProgram, GlProgram, Shader, compileHighShaderGpuProgram } from 'pixi.js';
6
6
 
@@ -972,8 +972,30 @@ function lintFocus(camera, siblings, warn = defaultWarn) {
972
972
  // src/core/matte.ts
973
973
  var MATTE_CHANNELS = ["alpha", "luma"];
974
974
  var isObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
975
+ var isLayerSpec = (v) => isObject(v) && typeof v.type === "string";
976
+ function matteOptions(r, label) {
977
+ const problems = [];
978
+ let channel = "alpha";
979
+ if (r.channel !== void 0) {
980
+ if (r.channel === "alpha" || r.channel === "luma") channel = r.channel;
981
+ else {
982
+ const guess = typeof r.channel === "string" ? suggestName(r.channel, MATTE_CHANNELS) : null;
983
+ const alias = typeof r.channel === "string" && ["luminance", "brightness", "grayscale", "greyscale", "gray", "grey", "value"].includes(r.channel.toLowerCase()) ? "luma" : null;
984
+ const meant = guess ?? alias;
985
+ problems.push(`${label}: channel ${JSON.stringify(r.channel)} is not a matte channel${meant ? `; did you mean "${meant}"?` : ""} (use alpha or luma); alpha is used`);
986
+ }
987
+ }
988
+ let invert = false;
989
+ if (r.invert !== void 0) {
990
+ if (typeof r.invert === "boolean") invert = r.invert;
991
+ else problems.push(`${label}: invert must be true or false (got ${JSON.stringify(r.invert)}); false is used`);
992
+ }
993
+ return { channel, invert, problems };
994
+ }
975
995
  function maskSourceOf(mask) {
976
- if (isObject(mask) && typeof mask.type === "string") return { kind: "inline", spec: mask };
996
+ if (isLayerSpec(mask)) return { kind: "inline", spec: mask, channel: "alpha", invert: false, problems: [] };
997
+ if (isObject(mask) && isLayerSpec(mask.layer)) return { kind: "inline", spec: mask.layer, ...matteOptions(mask, "mask (written in place)") };
998
+ if (isObject(mask) && isObject(mask.layer)) return { kind: "refs", refs: [], problems: ["mask: `layer` is an object with no `type`, so it is neither a layer written in place (it needs a `type`, such as 'shape') nor the name of another layer (a string); the layer is drawn without a mask"] };
977
999
  const problems = [];
978
1000
  const refs = [];
979
1001
  const one = (r, inList) => {
@@ -981,27 +1003,14 @@ function maskSourceOf(mask) {
981
1003
  refs.push({ layer: r, channel: "alpha", invert: false });
982
1004
  return;
983
1005
  }
984
- if (isObject(r) && typeof r.type === "string") {
1006
+ if (isLayerSpec(r) || isObject(r) && isLayerSpec(r.layer)) {
985
1007
  if (inList) problems.push("a layer written inside a list of masks is ignored: give that layer a name and write the name");
986
1008
  return;
987
1009
  }
988
1010
  if (isObject(r) && typeof r.layer === "string") {
989
- let channel = "alpha";
990
- if (r.channel !== void 0) {
991
- if (r.channel === "alpha" || r.channel === "luma") channel = r.channel;
992
- else {
993
- const guess = typeof r.channel === "string" ? suggestName(r.channel, MATTE_CHANNELS) : null;
994
- const alias = typeof r.channel === "string" && ["luminance", "brightness", "grayscale", "greyscale", "gray", "grey", "value"].includes(r.channel.toLowerCase()) ? "luma" : null;
995
- const meant = guess ?? alias;
996
- problems.push(`mask "${r.layer}": channel ${JSON.stringify(r.channel)} is not a matte channel${meant ? `; did you mean "${meant}"?` : ""} (use alpha or luma); alpha is used`);
997
- }
998
- }
999
- let invert = false;
1000
- if (r.invert !== void 0) {
1001
- if (typeof r.invert === "boolean") invert = r.invert;
1002
- else problems.push(`mask "${r.layer}": invert must be true or false (got ${JSON.stringify(r.invert)}); false is used`);
1003
- }
1004
- refs.push({ layer: r.layer, channel, invert });
1011
+ const o = matteOptions(r, `mask "${r.layer}"`);
1012
+ problems.push(...o.problems);
1013
+ refs.push({ layer: r.layer, channel: o.channel, invert: o.invert });
1005
1014
  }
1006
1015
  };
1007
1016
  if (Array.isArray(mask)) for (const r of mask) one(r, true);
@@ -1016,7 +1025,7 @@ function usesMatteRoute(spec) {
1016
1025
  const s = maskSourceOf(spec.mask);
1017
1026
  if (s.kind !== "inline") return false;
1018
1027
  const t = s.spec.type;
1019
- return spec.maskInverted === true || t === "text" || t === "image" || t === "video" || t === "shader";
1028
+ return s.invert || s.channel === "luma" || t === "text" || t === "image" || t === "video" || t === "shader";
1020
1029
  }
1021
1030
  var MANY_MATTES = 8;
1022
1031
  var startOf = (s) => Math.max(0, s.at ?? 0);
@@ -1027,12 +1036,10 @@ function canBeMatte(spec) {
1027
1036
  }
1028
1037
  function matteProblems(layer, siblings, span) {
1029
1038
  const src = maskSourceOf(layer.mask);
1039
+ if (src.kind === "inline") return [...src.problems];
1030
1040
  if (src.kind !== "refs") return [];
1031
1041
  const out = [...src.problems];
1032
1042
  const names = siblings.filter((s) => s.name && s.type !== "camera").map((s) => s.name);
1033
- if (layer.maskInverted && src.refs.length) {
1034
- out.push('maskInverted is for a mask written in place: with a reference write { layer: "name", invert: true } (and use a list to subtract one matte from another)');
1035
- }
1036
1043
  if (layer.parent && src.refs.length) {
1037
1044
  out.push(`it has a parent, so it is drawn in the null layer's space and the matte is in the composition's: mask the null layer ("${layer.parent}") instead`);
1038
1045
  }
@@ -1409,7 +1416,7 @@ var CompositionSequence = class extends Sequence {
1409
1416
  const chain = [];
1410
1417
  for (let p = this._parentOf.get(child); p; p = this._parentOf.get(p)) chain.push(p);
1411
1418
  this._mattes.add(key, maskSeq, chain);
1412
- const f = this._mattes.filterFor(key, { channel: "alpha", invert: child.spec.maskInverted === true });
1419
+ const f = this._mattes.filterFor(key, { channel: maskSrc.channel, invert: maskSrc.invert });
1413
1420
  if (f) matteFilters.push(f);
1414
1421
  } else {
1415
1422
  into.addChild(maskSeq.target);
@@ -1716,5 +1723,5 @@ function frameOf(child) {
1716
1723
  }
1717
1724
 
1718
1725
  export { CompositionSequence, maskSourceOf };
1719
- //# sourceMappingURL=chunk-WEJAQAFX.js.map
1720
- //# sourceMappingURL=chunk-WEJAQAFX.js.map
1726
+ //# sourceMappingURL=chunk-A3Q3SDSH.js.map
1727
+ //# sourceMappingURL=chunk-A3Q3SDSH.js.map