pixi-effects 0.22.0 → 0.25.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 (85) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +9 -7
  3. package/ai/SKILL.md +5 -3
  4. package/ai/chat-template.html +3 -3
  5. package/ai/reference/cheatsheet.md +8 -5
  6. package/ai/reference/pitfalls.md +13 -1
  7. package/ai/reference/recipes.md +131 -0
  8. package/ai/template.html +5 -5
  9. package/ai/tools/check.mjs +7 -0
  10. package/dist/{Base-gu-5X0Cv.d.ts → Base-BgnRXbtJ.d.ts} +1 -1
  11. package/dist/{Base-BzlPgd-D.d.cts → Base-DHVKqA46.d.cts} +1 -1
  12. package/dist/Composition-2GJSCHPP.cjs +16 -0
  13. package/dist/{Composition-BK5SH6J7.cjs.map → Composition-2GJSCHPP.cjs.map} +1 -1
  14. package/dist/Composition-C4FSWJZF.js +7 -0
  15. package/dist/{Composition-Q5TVG3HM.js.map → Composition-C4FSWJZF.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-DMxOoTdW.d.cts → Movie-CTpN1wYL.d.cts} +3 -1
  21. package/dist/{Movie--_TJvdJa.d.ts → Movie-FM5m67V0.d.ts} +3 -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-HCP5XTNP.js → blendModes-G3NOAU3T.js} +5 -5
  27. package/dist/{blendModes-HCP5XTNP.js.map → blendModes-G3NOAU3T.js.map} +1 -1
  28. package/dist/{blendModes-5E4G2ZZQ.cjs → blendModes-YV43K6E7.cjs} +6 -6
  29. package/dist/{blendModes-5E4G2ZZQ.cjs.map → blendModes-YV43K6E7.cjs.map} +1 -1
  30. package/dist/{chunk-K4JVI5HK.cjs → chunk-3DLYAPK7.cjs} +7 -9
  31. package/dist/{chunk-K4JVI5HK.cjs.map → chunk-3DLYAPK7.cjs.map} +1 -1
  32. package/dist/{chunk-YEPDQ7I3.js → chunk-AXZUKNXF.js} +6 -6
  33. package/dist/{chunk-YEPDQ7I3.js.map → chunk-AXZUKNXF.js.map} +1 -1
  34. package/dist/{chunk-NHICCDTC.js → chunk-BXOCEZ4U.js} +12 -3
  35. package/dist/chunk-BXOCEZ4U.js.map +1 -0
  36. package/dist/{chunk-IFZOI3JQ.cjs → chunk-DP37TTMO.cjs} +842 -40
  37. package/dist/chunk-DP37TTMO.cjs.map +1 -0
  38. package/dist/{chunk-BPTW7L25.cjs → chunk-ECA2WNRX.cjs} +23 -9
  39. package/dist/chunk-ECA2WNRX.cjs.map +1 -0
  40. package/dist/{chunk-DC4JPY6A.js → chunk-PRZ4U6JN.js} +814 -22
  41. package/dist/chunk-PRZ4U6JN.js.map +1 -0
  42. package/dist/chunk-SY27HZC5.cjs +1727 -0
  43. package/dist/chunk-SY27HZC5.cjs.map +1 -0
  44. package/dist/{chunk-E7RONUZ7.js → chunk-TLYTYBWX.js} +20 -6
  45. package/dist/chunk-TLYTYBWX.js.map +1 -0
  46. package/dist/{chunk-UZTKEYFP.cjs → chunk-TWZNOUM7.cjs} +12 -3
  47. package/dist/chunk-TWZNOUM7.cjs.map +1 -0
  48. package/dist/chunk-XS6GSJCN.js +1724 -0
  49. package/dist/chunk-XS6GSJCN.js.map +1 -0
  50. package/dist/index.cjs +227 -77
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +5 -5
  53. package/dist/index.d.ts +5 -5
  54. package/dist/index.js +166 -16
  55. package/dist/index.js.map +1 -1
  56. package/dist/loader.css +1 -1
  57. package/dist/{music-FUN7N225.js → music-AF4VTFAF.js} +3 -3
  58. package/dist/{music-FUN7N225.js.map → music-AF4VTFAF.js.map} +1 -1
  59. package/dist/{music-GEAH2XCT.cjs → music-KB7YZLHP.cjs} +7 -7
  60. package/dist/{music-GEAH2XCT.cjs.map → music-KB7YZLHP.cjs.map} +1 -1
  61. package/dist/{sfx-2DYTYNYW.cjs → sfx-2O6UQEUP.cjs} +8 -8
  62. package/dist/{sfx-2DYTYNYW.cjs.map → sfx-2O6UQEUP.cjs.map} +1 -1
  63. package/dist/{sfx-3IDAJ3UZ.js → sfx-VUKARHDX.js} +3 -3
  64. package/dist/{sfx-3IDAJ3UZ.js.map → sfx-VUKARHDX.js.map} +1 -1
  65. package/dist/three.cjs +7 -7
  66. package/dist/three.d.cts +2 -2
  67. package/dist/three.d.ts +2 -2
  68. package/dist/three.js +3 -3
  69. package/dist/{types-DBbZVKGS.d.cts → types-CoT0ypcx.d.cts} +60 -4
  70. package/dist/{types-DBbZVKGS.d.ts → types-CoT0ypcx.d.ts} +60 -4
  71. package/docs/dsl.md +138 -5
  72. package/llms-full.txt +295 -14
  73. package/package.json +1 -1
  74. package/dist/Composition-BK5SH6J7.cjs +0 -16
  75. package/dist/Composition-Q5TVG3HM.js +0 -7
  76. package/dist/chunk-BPTW7L25.cjs.map +0 -1
  77. package/dist/chunk-DC4JPY6A.js.map +0 -1
  78. package/dist/chunk-E7RONUZ7.js.map +0 -1
  79. package/dist/chunk-IFZOI3JQ.cjs.map +0 -1
  80. package/dist/chunk-MHOO2CVU.cjs +0 -840
  81. package/dist/chunk-MHOO2CVU.cjs.map +0 -1
  82. package/dist/chunk-NHICCDTC.js.map +0 -1
  83. package/dist/chunk-UQDEDYVM.js +0 -838
  84. package/dist/chunk-UQDEDYVM.js.map +0 -1
  85. package/dist/chunk-UZTKEYFP.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkMHOO2CVU_cjs = require('./chunk-MHOO2CVU.cjs');
4
- var chunkIFZOI3JQ_cjs = require('./chunk-IFZOI3JQ.cjs');
5
- var chunkK4JVI5HK_cjs = require('./chunk-K4JVI5HK.cjs');
6
- var chunkBPTW7L25_cjs = require('./chunk-BPTW7L25.cjs');
7
- var chunkUZTKEYFP_cjs = require('./chunk-UZTKEYFP.cjs');
3
+ var chunkSY27HZC5_cjs = require('./chunk-SY27HZC5.cjs');
4
+ var chunkDP37TTMO_cjs = require('./chunk-DP37TTMO.cjs');
5
+ var chunk3DLYAPK7_cjs = require('./chunk-3DLYAPK7.cjs');
6
+ var chunkECA2WNRX_cjs = require('./chunk-ECA2WNRX.cjs');
7
+ var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
8
8
  var PIXI = require('pixi.js');
9
9
  var gsap = require('gsap');
10
10
  var PixiPlugin = require('gsap/PixiPlugin');
@@ -717,7 +717,7 @@ var DEFAULTS = { samples: 8, shutter: 0.5 };
717
717
  function resolveMotionBlur(spec, where) {
718
718
  if (spec === void 0 || spec === null || spec === false) return null;
719
719
  const o = spec === true ? {} : typeof spec === "number" ? { samples: spec } : spec;
720
- if (typeof spec === "object") chunkUZTKEYFP_cjs.warnUnknownOptions(`${where} motionBlur`, o, ["samples", "shutter"]);
720
+ if (typeof spec === "object") chunkTWZNOUM7_cjs.warnUnknownOptions(`${where} motionBlur`, o, ["samples", "shutter"]);
721
721
  const samples = o.samples ?? DEFAULTS.samples, shutter = o.shutter ?? DEFAULTS.shutter;
722
722
  if (!(Number.isInteger(samples) && samples >= 2 && samples <= 64)) throw new Error(`pixi-effects: ${where}: motionBlur samples must be a whole number from 2 to 64, got ${samples}`);
723
723
  if (!(Number.isFinite(shutter) && shutter > 0 && shutter <= 1)) throw new Error(`pixi-effects: ${where}: motionBlur shutter must be a fraction of the frame time above 0 and up to 1 (0.5 is a 180\xB0 shutter), got ${shutter}`);
@@ -919,10 +919,10 @@ var MODE_CODES = {
919
919
  var GL_FRAGMENT = `
920
920
  in vec2 vTextureCoord;
921
921
  uniform sampler2D uTexture;
922
- uniform vec4 uInputSize; // PIXI-bound: xy = sprite render texture size (with padding)
923
- uniform vec4 uInputClamp; // PIXI-bound: xy = min uv of unpadded content, zw = max uv
924
- uniform vec4 uOutputFrame; // PIXI-bound: xy = sprite top-left on output, zw = bbox size in px
925
- uniform vec4 uGlobalFrame; // PIXI-bound: xy = global frame offset, zw = canvas size in px
922
+ uniform highp vec4 uInputSize; // PIXI-bound: xy = sprite render texture size (with padding)
923
+ uniform highp vec4 uInputClamp; // PIXI-bound: xy = min uv of unpadded content, zw = max uv
924
+ uniform highp vec4 uOutputFrame; // PIXI-bound: xy = sprite top-left on output, zw = bbox size in px
925
+ uniform highp vec4 uGlobalFrame; // PIXI-bound: xy = global frame offset, zw = canvas size in px
926
926
  uniform float uProgress;
927
927
  uniform float uSmoothing;
928
928
  uniform float uMode;
@@ -1240,6 +1240,133 @@ var TransitionMaskFilter = class extends PIXI.Filter {
1240
1240
  this.resources.transitionUniforms.uniforms.uSeed = v;
1241
1241
  }
1242
1242
  };
1243
+ var LUMA_MAPS = ["linear", "diagonal", "radial"];
1244
+ var GL = `in vec2 vTextureCoord;
1245
+ uniform sampler2D uTexture;
1246
+ uniform sampler2D uMap;
1247
+ uniform highp vec4 uInputClamp;
1248
+ uniform highp vec4 uOutputFrame;
1249
+ uniform highp vec4 uGlobalFrame;
1250
+ uniform float uProgress;
1251
+ uniform float uSoftness;
1252
+ uniform float uInvert;
1253
+ uniform float uFlip;
1254
+ uniform float uMode;
1255
+ out vec4 finalColor;
1256
+ float lumaOf(vec2 cuv, float aspect) {
1257
+ if (uMode > 2.5) { vec2 p = (cuv - 0.5) * vec2(aspect, 1.0); return clamp(length(p) / (0.5 * length(vec2(aspect, 1.0))), 0.0, 1.0); }
1258
+ if (uMode > 1.5) return clamp((cuv.x + cuv.y) * 0.5, 0.0, 1.0);
1259
+ if (uMode > 0.5) return clamp(cuv.x, 0.0, 1.0);
1260
+ return dot(texture(uMap, cuv).rgb, vec3(0.2126, 0.7152, 0.0722));
1261
+ }
1262
+ void main(void) {
1263
+ vec4 raw = texture(uTexture, vTextureCoord);
1264
+ vec2 bboxUV = (vTextureCoord - uInputClamp.xy) / (uInputClamp.zw - uInputClamp.xy);
1265
+ vec2 cuv = (uOutputFrame.xy + bboxUV * uOutputFrame.zw) / uGlobalFrame.zw;
1266
+ float l = lumaOf(cuv, uGlobalFrame.z / uGlobalFrame.w);
1267
+ if (uFlip > 0.5) l = 1.0 - l;
1268
+ float s = max(uSoftness, 0.0001);
1269
+ float ep = uProgress * (1.0 + 2.0 * s) - s;
1270
+ float reveal = 1.0 - smoothstep(ep - s, ep + s, l);
1271
+ if (uInvert > 0.5) reveal = 1.0 - step(0.99, reveal);
1272
+ finalColor = raw * reveal;
1273
+ }`;
1274
+ var WGSL = `
1275
+ struct GlobalFilterUniforms {
1276
+ uInputSize:vec4<f32>, uInputPixel:vec4<f32>, uInputClamp:vec4<f32>, uOutputFrame:vec4<f32>, uGlobalFrame:vec4<f32>, uOutputTexture:vec4<f32>,
1277
+ };
1278
+ struct LumaUniforms { uProgress:f32, uSoftness:f32, uInvert:f32, uFlip:f32, uMode:f32, };
1279
+ @group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
1280
+ @group(0) @binding(1) var uTexture: texture_2d<f32>;
1281
+ @group(0) @binding(2) var uSampler : sampler;
1282
+ @group(1) @binding(0) var<uniform> lumaUniforms : LumaUniforms;
1283
+ @group(1) @binding(1) var uMap: texture_2d<f32>;
1284
+ @group(1) @binding(2) var uMapSampler : sampler;
1285
+ struct VSOutput {
1286
+ @builtin(position) position: vec4<f32>,
1287
+ @location(0) uv : vec2<f32>,
1288
+ };
1289
+ @vertex
1290
+ fn mainVertex(
1291
+ @location(0) aPosition : vec2<f32>,
1292
+ ) -> VSOutput {
1293
+ var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
1294
+ position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
1295
+ position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
1296
+ return VSOutput(vec4<f32>(position, 0.0, 1.0), aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw));
1297
+ }
1298
+ fn lumaOf(cuv: vec2<f32>, aspect: f32) -> f32 {
1299
+ let mode = lumaUniforms.uMode;
1300
+ if (mode > 2.5) {
1301
+ let p = (cuv - vec2<f32>(0.5)) * vec2<f32>(aspect, 1.0);
1302
+ return clamp(length(p) / (0.5 * length(vec2<f32>(aspect, 1.0))), 0.0, 1.0);
1303
+ }
1304
+ if (mode > 1.5) { return clamp((cuv.x + cuv.y) * 0.5, 0.0, 1.0); }
1305
+ if (mode > 0.5) { return clamp(cuv.x, 0.0, 1.0); }
1306
+ let m = textureSampleLevel(uMap, uMapSampler, cuv, 0.0).rgb;
1307
+ return dot(m, vec3<f32>(0.2126, 0.7152, 0.0722));
1308
+ }
1309
+ @fragment
1310
+ fn mainFragment(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
1311
+ let raw = textureSample(uTexture, uSampler, uv);
1312
+ let bboxUV = (uv - gfu.uInputClamp.xy) / (gfu.uInputClamp.zw - gfu.uInputClamp.xy);
1313
+ let cuv = (gfu.uOutputFrame.xy + bboxUV * gfu.uOutputFrame.zw) / gfu.uGlobalFrame.zw;
1314
+ var l = lumaOf(cuv, gfu.uGlobalFrame.z / gfu.uGlobalFrame.w);
1315
+ if (lumaUniforms.uFlip > 0.5) { l = 1.0 - l; }
1316
+ let s = max(lumaUniforms.uSoftness, 0.0001);
1317
+ let ep = lumaUniforms.uProgress * (1.0 + 2.0 * s) - s;
1318
+ var reveal = 1.0 - smoothstep(ep - s, ep + s, l);
1319
+ if (lumaUniforms.uInvert > 0.5) { reveal = 1.0 - step(0.99, reveal); }
1320
+ return raw * reveal;
1321
+ }`;
1322
+ var LumaWipeFilter = class extends PIXI.Filter {
1323
+ _mapName;
1324
+ _builtIn;
1325
+ _resolved = false;
1326
+ _warned = false;
1327
+ constructor({ map, softness = 0.1, progress = 0, invert = false, flip = false }) {
1328
+ const t = PIXI.Texture.WHITE;
1329
+ const mode = LUMA_MAPS.indexOf(map) + 1;
1330
+ super({
1331
+ glProgram: PIXI.GlProgram.from({ vertex: PIXI.defaultFilterVert, fragment: GL, name: "pe-luma-wipe" }),
1332
+ gpuProgram: PIXI.GpuProgram.from({ vertex: { source: WGSL, entryPoint: "mainVertex" }, fragment: { source: WGSL, entryPoint: "mainFragment" } }),
1333
+ resources: {
1334
+ lumaUniforms: new PIXI.UniformGroup({
1335
+ uProgress: { value: progress, type: "f32" },
1336
+ uSoftness: { value: softness, type: "f32" },
1337
+ uInvert: { value: invert ? 1 : 0, type: "f32" },
1338
+ uFlip: { value: flip ? 1 : 0, type: "f32" },
1339
+ uMode: { value: mode, type: "f32" }
1340
+ }),
1341
+ uMap: t.source,
1342
+ uMapSampler: t.source.style
1343
+ }
1344
+ });
1345
+ this._mapName = map;
1346
+ this._builtIn = mode > 0;
1347
+ }
1348
+ get uProgress() {
1349
+ return this.resources.lumaUniforms.uniforms.uProgress;
1350
+ }
1351
+ set uProgress(v) {
1352
+ this.resources.lumaUniforms.uniforms.uProgress = v;
1353
+ }
1354
+ apply(fm, input, output, clear) {
1355
+ if (!this._builtIn && !this._resolved) {
1356
+ const t = PIXI.Assets.get(this._mapName);
1357
+ if (t) {
1358
+ this.resources.uMap = t.source;
1359
+ this.resources.uMapSampler = t.source.style;
1360
+ this._resolved = true;
1361
+ } else if (!this._warned) {
1362
+ this._warned = true;
1363
+ const guess = chunkTWZNOUM7_cjs.suggestName(this._mapName, LUMA_MAPS);
1364
+ console.warn(`pixi-effects: luma transition map "${this._mapName}" is not a built-in map (${LUMA_MAPS.join(", ")}) and no image asset has that name${guess ? `; did you mean "${guess}"?` : ""}; the wipe follows a white map (everything changes at once)`);
1365
+ }
1366
+ }
1367
+ fm.applyFilter(this, input, output, clear);
1368
+ }
1369
+ };
1243
1370
 
1244
1371
  // src/core/Transitions.ts
1245
1372
  var EPS = 1e-6;
@@ -1280,8 +1407,8 @@ function expandTransitions(spec) {
1280
1407
  }
1281
1408
  const transitions = out.transitions;
1282
1409
  const sequences = out.sequences ?? [];
1283
- const remap = out.duration !== void 0 ? chunkIFZOI3JQ_cjs.timeRemapOf(out) : null;
1284
- const parentDuration = remap ? chunkIFZOI3JQ_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
1410
+ const remap = out.duration !== void 0 ? chunkDP37TTMO_cjs.timeRemapOf(out) : null;
1411
+ const parentDuration = remap ? chunkDP37TTMO_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
1285
1412
  const compW = out.width;
1286
1413
  const compH = out.height;
1287
1414
  const threeDByName = new Set(sequences.filter((s) => s.name && s.threeD).map((s) => s.name));
@@ -1294,7 +1421,7 @@ function expandTransitions(spec) {
1294
1421
  });
1295
1422
  const masksParticipants = /* @__PURE__ */ new Set();
1296
1423
  for (const t of transitions) {
1297
- if (t.kind === "wipe" || t.kind === "iris" || t.kind === "dissolve" || t.kind === "zoom") {
1424
+ if (t.kind === "wipe" || t.kind === "iris" || t.kind === "dissolve" || t.kind === "zoom" || t.kind === "luma") {
1298
1425
  masksParticipants.add(t.from);
1299
1426
  masksParticipants.add(t.to);
1300
1427
  }
@@ -1349,16 +1476,16 @@ function expandTransitions(spec) {
1349
1476
  if (toUses > 1) {
1350
1477
  throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
1351
1478
  }
1352
- const tStart = chunkIFZOI3JQ_cjs.resolveAt(t.at, parentDuration);
1479
+ const tStart = chunkDP37TTMO_cjs.resolveAt(t.at, parentDuration);
1353
1480
  const tEnd = tStart + t.duration;
1354
1481
  const fromSeq = fromEntry.seq;
1355
- const fromStart = chunkIFZOI3JQ_cjs.resolveAt(fromSeq.at, parentDuration);
1482
+ const fromStart = chunkDP37TTMO_cjs.resolveAt(fromSeq.at, parentDuration);
1356
1483
  const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
1357
1484
  if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
1358
1485
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
1359
1486
  }
1360
1487
  const toSeq = toEntry.seq;
1361
- const toStart = chunkIFZOI3JQ_cjs.resolveAt(toSeq.at, parentDuration);
1488
+ const toStart = chunkDP37TTMO_cjs.resolveAt(toSeq.at, parentDuration);
1362
1489
  const toEnd = toStart + (toSeq.duration ?? parentDuration);
1363
1490
  if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
1364
1491
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
@@ -1391,6 +1518,9 @@ function expandTransitions(spec) {
1391
1518
  case "dissolve":
1392
1519
  expandDissolve(out, abs, fromEntry.seq, toEntry.seq, i);
1393
1520
  break;
1521
+ case "luma":
1522
+ expandLuma(out, abs, fromEntry.seq, toEntry.seq, i);
1523
+ break;
1394
1524
  }
1395
1525
  rebaseNewKeyframes(fromEntry.seq, nFrom, fromStart);
1396
1526
  rebaseNewKeyframes(toEntry.seq, nTo, toStart);
@@ -1414,7 +1544,11 @@ function wrapAsFullComposition(seq, compW, compH) {
1414
1544
  delete inner.name;
1415
1545
  delete inner.at;
1416
1546
  delete inner.duration;
1547
+ const m = inner.mask;
1548
+ const carriesMatte = m !== void 0 && chunkSY27HZC5_cjs.maskSourceOf(m).kind === "refs";
1549
+ if (carriesMatte) delete inner.mask;
1417
1550
  return {
1551
+ ...carriesMatte ? { mask: m } : {},
1418
1552
  type: "composition",
1419
1553
  name: seq.name,
1420
1554
  at: seq.at,
@@ -1641,6 +1775,20 @@ function expandDissolve(comp, t, fromSeq, toSeq, transitionIndex) {
1641
1775
  });
1642
1776
  fromSeq.filterArea = fullArea;
1643
1777
  }
1778
+ function expandLuma(comp, t, fromSeq, toSeq, transitionIndex) {
1779
+ const ease = t.ease ?? "none";
1780
+ const inName = transitionFilterName(transitionIndex);
1781
+ const outName = `${transitionFilterName(transitionIndex)}-out`;
1782
+ const fullArea = { x: 0, y: 0, width: comp.width ?? 0, height: comp.height ?? 0 };
1783
+ const opts = { map: t.map ?? "linear", softness: t.softness ?? 0.1, flip: t.flip ?? false };
1784
+ for (const [seq, name, invert] of [[toSeq, inName, false], [fromSeq, outName, true]]) {
1785
+ const filters = ensureFilters(seq);
1786
+ rejectReservedNameCollision(filters, seq.name);
1787
+ filters.push({ type: "custom", name, filter: new LumaWipeFilter({ ...opts, invert }) });
1788
+ ensureKeyframes(seq).push({ at: t.at, to: { [`filters.${name}.uProgress`]: 1 }, duration: t.duration, ease });
1789
+ seq.filterArea = fullArea;
1790
+ }
1791
+ }
1644
1792
  var OWN_NAME_PATTERN = /^_pe-transition-\d+(-out)?$/;
1645
1793
  function rejectReservedNameCollision(filters, seqName) {
1646
1794
  for (const f of filters) {
@@ -1680,7 +1828,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1680
1828
  blending.add(w.to);
1681
1829
  }
1682
1830
  }
1683
- comp.layers().forEach(({ seq, display, threeD, carriers, depthBlur }, i) => {
1831
+ comp.layers().forEach(({ seq, display, threeD, carriers, depthBlur, light }, i) => {
1684
1832
  const t = seq.target;
1685
1833
  const name = seq.spec.name;
1686
1834
  const label = name ?? `${seq.spec.type}#${i}`;
@@ -1699,9 +1847,9 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1699
1847
  onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
1700
1848
  if (area === 0) onCanvas = "none";
1701
1849
  }
1702
- const keys = chunkBPTW7L25_cjs.collectPropKeys(seq.spec);
1850
+ const keys = chunkECA2WNRX_cjs.collectPropKeys(seq.spec);
1703
1851
  const carried = carriers.some((c) => {
1704
- const k = chunkBPTW7L25_cjs.collectPropKeys(c.spec);
1852
+ const k = chunkECA2WNRX_cjs.collectPropKeys(c.spec);
1705
1853
  return (c.spec.keyframes ?? []).length > 0 && (k.has("x") || k.has("y") || k.has("rotation") || k.has("scale"));
1706
1854
  });
1707
1855
  const moving = parentMoving || carried || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
@@ -1712,6 +1860,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1712
1860
  const zero = parentZero || zeroScale(t) || carriers.some((c) => zeroScale(c.target));
1713
1861
  const info = { path: prefix + label, name, type: seq.spec.type, threeD, visible, alpha, moving, bounds, onCanvas };
1714
1862
  if (threeD) info.depthBlur = Number(depthBlur.toFixed(2));
1863
+ if (threeD && light !== void 0) info.light = Number(light.toFixed(2));
1715
1864
  layers.push(info);
1716
1865
  let shown = bounds ? clip(bounds, view) : null;
1717
1866
  const maskTarget = seq.maskSequence?.target;
@@ -1723,7 +1872,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1723
1872
  const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
1724
1873
  if (group) scene.set(info, group);
1725
1874
  if (zero || seq.showsNothingYet) scaledToNothing.add(info);
1726
- if (seq instanceof chunkMHOO2CVU_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1875
+ if (seq instanceof chunkSY27HZC5_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1727
1876
  });
1728
1877
  };
1729
1878
  walk2(root, "", false, true);
@@ -1784,10 +1933,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions, lo
1784
1933
  const start = parentStart + (seq.at ?? 0);
1785
1934
  const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
1786
1935
  const span = end - start;
1787
- const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkIFZOI3JQ_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1936
+ const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkDP37TTMO_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1788
1937
  const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq), ...local ? { local } : {} };
1789
1938
  const inner = [];
1790
- const isComp = seq instanceof chunkMHOO2CVU_cjs.CompositionSequence;
1939
+ const isComp = seq instanceof chunkSY27HZC5_cjs.CompositionSequence;
1791
1940
  if (isComp) {
1792
1941
  const label = seq.remapLabel();
1793
1942
  walk(seq, label ? 0 : start, label ? seq.contentSpan : end, depth + 1, prefix + name + "/", inner, transitions, label ? `${name} ${label}` : local);
@@ -1850,6 +1999,7 @@ var COLORS = {
1850
1999
  composition: "#8ea4c8",
1851
2000
  three: "#ff9f68",
1852
2001
  camera: "#b0b0b0",
2002
+ light: "#b0b0b0",
1853
2003
  null: "#b0b0b0"
1854
2004
  };
1855
2005
  var esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -2070,7 +2220,7 @@ function normalizeStops(raw, duration, frameRate) {
2070
2220
  console.warn(`pixi-effects: stops[${i}] ${JSON.stringify(r)} is not a time in seconds (or { at, page?, notes?, advance?, pdf? }); ignored`);
2071
2221
  return;
2072
2222
  }
2073
- if (typeof r === "object") chunkUZTKEYFP_cjs.warnUnknownOptions(`stops[${i}]`, r, KEYS);
2223
+ if (typeof r === "object") chunkTWZNOUM7_cjs.warnUnknownOptions(`stops[${i}]`, r, KEYS);
2074
2224
  const at = spec.at < 0 ? duration + spec.at : spec.at;
2075
2225
  if (at < -1e-9 || at > duration + 1e-9) {
2076
2226
  console.warn(`pixi-effects: stops[${i}] at ${spec.at} s is outside the movie (0 to ${duration} s); ignored`);
@@ -2300,7 +2450,7 @@ var Movie = class {
2300
2450
  return this._audioContext;
2301
2451
  }
2302
2452
  async init(options = {}) {
2303
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition", "poster", "motionBlur", "loader"]);
2453
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition", "poster", "motionBlur", "loader"]);
2304
2454
  this._initState = "pending";
2305
2455
  try {
2306
2456
  this.width = options.width ?? 1920;
@@ -2334,7 +2484,7 @@ var Movie = class {
2334
2484
  this.app = new PIXI.Application();
2335
2485
  await this.app.init({ ...baseAppOptions, preference: "webgl" });
2336
2486
  }
2337
- if (chunkK4JVI5HK_cjs.usesAdvancedBlend(options.composition)) await chunkK4JVI5HK_cjs.enableAdvancedBlend(this.app.renderer);
2487
+ if (chunk3DLYAPK7_cjs.usesAdvancedBlend(options.composition)) await chunk3DLYAPK7_cjs.enableAdvancedBlend(this.app.renderer);
2338
2488
  const root = new PIXI.Container();
2339
2489
  root.cullable = true;
2340
2490
  root.cullableChildren = true;
@@ -2343,14 +2493,14 @@ var Movie = class {
2343
2493
  this._rootContainer = root;
2344
2494
  const audioContext = this._ensureAudioContext();
2345
2495
  await loadAssetBundle(options.assets ?? [], audioContext);
2346
- const rootShape = { width: this.width, height: this.height, duration: this.duration };
2496
+ const rootShape = { width: this.width, height: this.height, duration: this.duration, frameRate: this.frameRate };
2347
2497
  const seededComposition = options.composition ? {
2348
2498
  ...options.composition,
2349
2499
  width: options.composition.width ?? this.width,
2350
2500
  height: options.composition.height ?? this.height,
2351
2501
  duration: options.composition.duration ?? this.duration
2352
2502
  } : void 0;
2353
- await chunkIFZOI3JQ_cjs.ensureFilterLibrary(seededComposition);
2503
+ await chunkDP37TTMO_cjs.ensureFilterLibrary(seededComposition);
2354
2504
  const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
2355
2505
  const rootSeqSpec = {
2356
2506
  type: "composition",
@@ -2360,7 +2510,7 @@ var Movie = class {
2360
2510
  ...userComposition
2361
2511
  };
2362
2512
  if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
2363
- const composition = new chunkMHOO2CVU_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2513
+ const composition = new chunkSY27HZC5_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2364
2514
  await composition.build();
2365
2515
  this._rootSequence = composition;
2366
2516
  if (composition.target) root.addChild(composition.target);
@@ -2444,7 +2594,7 @@ var Movie = class {
2444
2594
  }));
2445
2595
  }
2446
2596
  async snapshot(frame = this.currentFrame, opts = {}) {
2447
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as", "motionBlur"]);
2597
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as", "motionBlur"]);
2448
2598
  this._requireReady("snapshot");
2449
2599
  return this._captureFrame(clampFrame(frame, this.totalFrames), { scale: opts.scale ?? 1, type: opts.type ?? "image/png", as: opts.as ?? "blob", motionBlur: opts.motionBlur });
2450
2600
  }
@@ -2473,7 +2623,7 @@ var Movie = class {
2473
2623
  return encodeCanvas(out, o.type, o.as, o.quality);
2474
2624
  }
2475
2625
  async stopImages(opts = {}) {
2476
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.stopImages()", opts, ["which", "pick", "scale", "type", "quality", "as", "motionBlur", "pdf", "onImage"]);
2626
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.stopImages()", opts, ["which", "pick", "scale", "type", "quality", "as", "motionBlur", "pdf", "onImage"]);
2477
2627
  this._requireReady("stopImages");
2478
2628
  if (this.stops.length === 0) return [];
2479
2629
  const picks = pictureStops(this.stops, { which: opts.which, pick: opts.pick, pdf: opts.pdf });
@@ -2505,7 +2655,7 @@ var Movie = class {
2505
2655
  * animation. `issues` says which stop, which page and what to do; leaves the playhead where it was.
2506
2656
  */
2507
2657
  async inspectStops(opts = {}) {
2508
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.inspectStops()", opts, ["lookback", "tolerance"]);
2658
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.inspectStops()", opts, ["lookback", "tolerance"]);
2509
2659
  this._requireReady("inspectStops");
2510
2660
  const out = { stops: [], issues: [] };
2511
2661
  if (this.stops.length === 0) return out;
@@ -2539,7 +2689,7 @@ var Movie = class {
2539
2689
  * JPEG at the canvas size. Needs `composition.stops`. A transparent background comes out black: give the movie a `background`.
2540
2690
  */
2541
2691
  async exportPDF(opts = {}) {
2542
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.exportPDF()", opts, ["which", "pick", "scale", "quality", "title", "motionBlur", "onImage"]);
2692
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.exportPDF()", opts, ["which", "pick", "scale", "quality", "title", "motionBlur", "onImage"]);
2543
2693
  this._requireReady("exportPDF");
2544
2694
  if (this.stops.length === 0) throw new Error("pixi-effects: movie.exportPDF(): this movie has no stops, so there are no pages; add `stops` to the composition (or build it with deck())");
2545
2695
  const scale = opts.scale ?? 1;
@@ -2562,7 +2712,7 @@ var Movie = class {
2562
2712
  return new Blob([buildPdf(pages, { title: opts.title })], { type: "application/pdf" });
2563
2713
  }
2564
2714
  async onionSkin(opts = {}) {
2565
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.onionSkin()", opts, ["from", "to", "count", "scale", "as", "motionBlur"]);
2715
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.onionSkin()", opts, ["from", "to", "count", "scale", "as", "motionBlur"]);
2566
2716
  this._requireReady("onionSkin");
2567
2717
  const from = opts.from ?? 0, to = opts.to ?? this.duration, count = opts.count ?? 8, scale = opts.scale ?? 1;
2568
2718
  if (!(Number.isInteger(count) && count >= 1 && count <= 64)) throw new Error(`pixi-effects: movie.onionSkin(): count must be a whole number from 1 to 64, got ${count}`);
@@ -2593,7 +2743,7 @@ var Movie = class {
2593
2743
  return encodeCanvas(out, "image/png", opts.as ?? "blob");
2594
2744
  }
2595
2745
  async contactSheet(opts = {}) {
2596
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.contactSheet()", opts, ["frames", "times", "count", "columns", "cellWidth", "as", "motionBlur"]);
2746
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.contactSheet()", opts, ["frames", "times", "count", "columns", "cellWidth", "as", "motionBlur"]);
2597
2747
  this._requireReady("contactSheet");
2598
2748
  const mb = this._blurFor(opts.motionBlur, "movie.contactSheet()");
2599
2749
  const blurred = mb ? this._blurCanvas() : null;
@@ -2630,7 +2780,7 @@ var Movie = class {
2630
2780
  * the canvas, cut by an edge, empty, or overlapping other text. Seeks there and stays there.
2631
2781
  */
2632
2782
  async inspect(frame = this.currentFrame, opts = { layers: "visible" }) {
2633
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.inspect()", opts, ["layers"]);
2783
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.inspect()", opts, ["layers"]);
2634
2784
  this._requireReady("inspect");
2635
2785
  const f = clampFrame(frame, this.totalFrames);
2636
2786
  await this.gotoFrame(f, true);
@@ -2646,12 +2796,12 @@ var Movie = class {
2646
2796
  }
2647
2797
  /** The timeline as one self-contained HTML page (an inline SVG, no scripts): layers as bars on a time axis, ◆ keyframes, transition bands. Open it in a browser. */
2648
2798
  timelineChart(opts = {}) {
2649
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.timelineChart()", opts, ["title"]);
2799
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.timelineChart()", opts, ["title"]);
2650
2800
  return timelineHtml(this.timelineData(), opts);
2651
2801
  }
2652
2802
  /** Just the chart: one `<svg>` whose geometry is in `data-*` attributes (a viewer puts a playhead on it: `pixi-effects-view`). */
2653
2803
  timelineSvg(opts = {}) {
2654
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.timelineSvg()", opts, ["chartWidth", "labels"]);
2804
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.timelineSvg()", opts, ["chartWidth", "labels"]);
2655
2805
  return timelineSvg(this.timelineData(), opts);
2656
2806
  }
2657
2807
  /**
@@ -2668,7 +2818,7 @@ var Movie = class {
2668
2818
  * scene's first and last frame and a frame every 0.25 s), fonts and the sound. See `ReviewReport`. Page warnings are in `window.__logs`. The movie is left as it was.
2669
2819
  */
2670
2820
  async review(opts = {}) {
2671
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.review()", opts, ["at", "strict"]);
2821
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.review()", opts, ["at", "strict"]);
2672
2822
  this._requireReady("review");
2673
2823
  const back = this.currentFrame, wasAtPoster = this._atPoster;
2674
2824
  try {
@@ -2688,7 +2838,7 @@ var Movie = class {
2688
2838
  return inspectFonts(this._rootSequence);
2689
2839
  }
2690
2840
  inspectAudio(opts = {}) {
2691
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.inspectAudio()", opts, ["window", "scenes"]);
2841
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.inspectAudio()", opts, ["window", "scenes"]);
2692
2842
  this._requireReady("inspectAudio");
2693
2843
  const scenes = opts.scenes ?? namedScenes(this.timelineData().rows);
2694
2844
  return analyzeAudio(this.audioBuffer, this._audioSources, this._mixStats, this.duration, { ...opts, scenes });
@@ -2966,7 +3116,7 @@ var Movie = class {
2966
3116
  return this.muted;
2967
3117
  }
2968
3118
  async render(options) {
2969
- chunkUZTKEYFP_cjs.warnUnknownOptions("movie.render()", options, ["format", "video", "audio", "motionBlur", "range", "scale", "draft"]);
3119
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.render()", options, ["format", "video", "audio", "motionBlur", "range", "scale", "draft"]);
2970
3120
  try {
2971
3121
  return await this._quietly(() => exportFrames(this, options));
2972
3122
  } catch (err) {
@@ -3024,16 +3174,16 @@ function measureText(text, style = {}) {
3024
3174
  return { width: m.width, height: m.height, lines: text.split("\n").length };
3025
3175
  }
3026
3176
  function splitText(text, style = {}, opts = {}) {
3027
- chunkUZTKEYFP_cjs.warnUnknownOptions("splitText()", opts, ["by", "x", "y", "align"]);
3177
+ chunkTWZNOUM7_cjs.warnUnknownOptions("splitText()", opts, ["by", "x", "y", "align"]);
3028
3178
  let by = opts.by ?? "chars";
3029
3179
  if (!BY.includes(by)) {
3030
- const g = chunkUZTKEYFP_cjs.suggestName(String(by), BY);
3180
+ const g = chunkTWZNOUM7_cjs.suggestName(String(by), BY);
3031
3181
  console.warn(`pixi-effects: splitText(): by "${by}" is not one of ${BY.map((b) => `"${b}"`).join(", ")}${g ? ` \u2014 did you mean "${g}"?` : ""}; using "chars"`);
3032
3182
  by = "chars";
3033
3183
  }
3034
3184
  let align = opts.align ?? "left";
3035
3185
  if (!ALIGN.includes(align)) {
3036
- const g = chunkUZTKEYFP_cjs.suggestName(String(align), ALIGN);
3186
+ const g = chunkTWZNOUM7_cjs.suggestName(String(align), ALIGN);
3037
3187
  console.warn(`pixi-effects: splitText(): align "${align}" is not one of ${ALIGN.join(", ")}${g ? ` \u2014 did you mean "${g}"?` : ""}; using "left"`);
3038
3188
  align = "left";
3039
3189
  }
@@ -3070,7 +3220,7 @@ function splitText(text, style = {}, opts = {}) {
3070
3220
  // src/presets/kenBurns.ts
3071
3221
  var KEN_BURNS_KEYS = ["asset", "name", "at", "duration", "fit", "ease", "motion", "origin", "zoom", "direction", "angle", "from", "to"];
3072
3222
  function kenBurns(opts) {
3073
- chunkUZTKEYFP_cjs.warnUnknownOptions("kenBurns()", opts, KEN_BURNS_KEYS);
3223
+ chunkTWZNOUM7_cjs.warnUnknownOptions("kenBurns()", opts, KEN_BURNS_KEYS);
3074
3224
  const {
3075
3225
  asset,
3076
3226
  name,
@@ -3180,14 +3330,14 @@ function clamp(v, lo, hi) {
3180
3330
  return Math.max(lo, Math.min(hi, v));
3181
3331
  }
3182
3332
  function parseEase(name) {
3183
- chunkIFZOI3JQ_cjs.checkEase(name, "a preset");
3333
+ chunkDP37TTMO_cjs.checkEase(name, "a preset");
3184
3334
  return gsap.gsap.parseEase(name);
3185
3335
  }
3186
3336
 
3187
3337
  // src/presets/orbit.ts
3188
3338
  var ORBIT_KEYS = ["duration", "degrees", "start", "radius", "center", "width", "height", "fov", "ease", "dollyZoom", "at", "name", "stepsPerSecond"];
3189
3339
  function orbit(opts) {
3190
- chunkUZTKEYFP_cjs.warnUnknownOptions("orbit()", opts, ORBIT_KEYS);
3340
+ chunkTWZNOUM7_cjs.warnUnknownOptions("orbit()", opts, ORBIT_KEYS);
3191
3341
  const {
3192
3342
  duration,
3193
3343
  degrees,
@@ -3203,17 +3353,17 @@ function orbit(opts) {
3203
3353
  throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
3204
3354
  }
3205
3355
  const [cx, cy] = opts.center ?? [width / 2, height / 2];
3206
- const fixedR = opts.radius ?? chunkIFZOI3JQ_cjs.homeDistance(height, fov ?? chunkIFZOI3JQ_cjs.DEFAULT_FOV);
3356
+ const fixedR = opts.radius ?? chunkDP37TTMO_cjs.homeDistance(height, fov ?? chunkDP37TTMO_cjs.DEFAULT_FOV);
3207
3357
  const start = opts.start ?? -degrees / 2;
3208
3358
  const steps = Math.max(1, Math.round(duration * stepsPerSecond));
3209
3359
  const easeFn = parseEase(ease);
3210
3360
  const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
3211
3361
  const pos = (i) => {
3212
3362
  const p = i / steps;
3213
- const a = (start + degrees * easeFn(p)) * chunkIFZOI3JQ_cjs.DEG;
3363
+ const a = (start + degrees * easeFn(p)) * chunkDP37TTMO_cjs.DEG;
3214
3364
  if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
3215
3365
  const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
3216
- const R = chunkIFZOI3JQ_cjs.homeDistance(height, f);
3366
+ const R = chunkDP37TTMO_cjs.homeDistance(height, f);
3217
3367
  return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
3218
3368
  };
3219
3369
  const keyframes = [];
@@ -3245,7 +3395,7 @@ var KEYS2 = ["count", "at", "emit", "life", "area", "angle", "speed", "gravity",
3245
3395
  var SHAPES = ["circle", "rect", "star"];
3246
3396
  var MAX_KEYFRAMES = 3e4;
3247
3397
  function particles(opts) {
3248
- chunkUZTKEYFP_cjs.warnUnknownOptions("particles()", opts, KEYS2);
3398
+ chunkTWZNOUM7_cjs.warnUnknownOptions("particles()", opts, KEYS2);
3249
3399
  const { count, at = 0, emit = 0, gravity = 0, wind = 0, drag = 0, sway, fade, colors = ["#ffffff"], shape = "circle", seed = 0, name = "particle", template, sampleRate = 20 } = opts;
3250
3400
  if (!(Number.isInteger(count) && count > 0)) throw new Error(`particles(): count must be a whole number of particles (at least 1), got ${count}`);
3251
3401
  const life = range("life", opts.life, 1e-6);
@@ -3253,7 +3403,7 @@ function particles(opts) {
3253
3403
  if (!(Number.isFinite(emit) && emit >= 0)) throw new Error(`particles(): emit must be a number of seconds >= 0, got ${emit}`);
3254
3404
  if (!(Number.isFinite(sampleRate) && sampleRate > 0)) throw new Error(`particles(): sampleRate must be a positive number (samples per second), got ${sampleRate}`);
3255
3405
  if (!SHAPES.includes(shape)) {
3256
- const g = chunkUZTKEYFP_cjs.suggestName(String(shape), SHAPES);
3406
+ const g = chunkTWZNOUM7_cjs.suggestName(String(shape), SHAPES);
3257
3407
  throw new Error(`particles(): shape "${shape}" is not one of ${SHAPES.map((s) => `"${s}"`).join(", ")}${g ? `; did you mean "${g}"?` : ""}`);
3258
3408
  }
3259
3409
  const angle = range("angle", opts.angle ?? [0, 360], -Infinity);
@@ -3268,7 +3418,7 @@ function particles(opts) {
3268
3418
  const round3 = (v) => Math.round(v * 1e6) / 1e6;
3269
3419
  const out = [];
3270
3420
  for (let i = 0; i < count; i++) {
3271
- const r = chunkIFZOI3JQ_cjs.random(seed * 1000003 + i * 7919 + 17);
3421
+ const r = chunkDP37TTMO_cjs.random(seed * 1000003 + i * 7919 + 17);
3272
3422
  const pick = ([a2, b]) => a2 + r() * (b - a2);
3273
3423
  const born = at + r() * emit;
3274
3424
  const lifetime = pick(life);
@@ -3281,7 +3431,7 @@ function particles(opts) {
3281
3431
  const turn = spin ? pick(spin) : 0;
3282
3432
  const startAngle = spin ? r() * 360 : 0;
3283
3433
  const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
3284
- const n0 = sway ? chunkIFZOI3JQ_cjs.noise(0, seed * 1000003 + i) : 0;
3434
+ const n0 = sway ? chunkDP37TTMO_cjs.noise(0, seed * 1000003 + i) : 0;
3285
3435
  const at_ = (t) => {
3286
3436
  const axis = (p0, v0, acc) => {
3287
3437
  if (drag > 0) {
@@ -3290,7 +3440,7 @@ function particles(opts) {
3290
3440
  }
3291
3441
  return p0 + v0 * t + 0.5 * acc * t * t;
3292
3442
  };
3293
- const sw = sway ? swayAmp * (chunkIFZOI3JQ_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3443
+ const sw = sway ? swayAmp * (chunkDP37TTMO_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3294
3444
  return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
3295
3445
  };
3296
3446
  const kfs = [];
@@ -3340,7 +3490,7 @@ function range(name, v, min) {
3340
3490
  var KEYS3 = ["d", "at", "duration", "ease", "from", "to", "orient", "rotate", "frameRate"];
3341
3491
  var MAX_STEPS = 2e3;
3342
3492
  function followPath(opts) {
3343
- chunkUZTKEYFP_cjs.warnUnknownOptions("followPath()", opts, KEYS3);
3493
+ chunkTWZNOUM7_cjs.warnUnknownOptions("followPath()", opts, KEYS3);
3344
3494
  const { d, at = 0, duration, ease = "none", from = 0, to = 1, orient = false, rotate = 0, frameRate = 30 } = opts;
3345
3495
  if (typeof d !== "string" || d.trim() === "") throw new Error('followPath(): d must be SVG path data, e.g. "M 100 600 C 300 100 900 100 1180 600"');
3346
3496
  if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`followPath(): duration must be a positive number of seconds, got ${duration}`);
@@ -3352,7 +3502,7 @@ function followPath(opts) {
3352
3502
  if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
3353
3503
  const segments = [];
3354
3504
  let total = 0;
3355
- for (const line of chunkIFZOI3JQ_cjs.flattenSvgPath(d)) {
3505
+ for (const line of chunkDP37TTMO_cjs.flattenSvgPath(d)) {
3356
3506
  const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
3357
3507
  for (let i = 2; i < p.length; i += 2) {
3358
3508
  const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
@@ -3407,7 +3557,7 @@ var KEYS4 = ["points", "at", "duration", "ease", "look", "lookAhead", "smooth",
3407
3557
  var MAX_STEPS2 = 4e3;
3408
3558
  var PER_SPAN = 48;
3409
3559
  function cameraPath(opts) {
3410
- chunkUZTKEYFP_cjs.warnUnknownOptions("cameraPath()", opts, KEYS4);
3560
+ chunkTWZNOUM7_cjs.warnUnknownOptions("cameraPath()", opts, KEYS4);
3411
3561
  const { points, at = 0, duration, ease = "none", look = "ahead", lookAhead = 0.08, smooth = true, from = 0, to = 1, frameRate = 30 } = opts;
3412
3562
  if (!Array.isArray(points) || points.length < 2) throw new Error("cameraPath(): points needs at least two points: [[x, y, z], [x, y, z], \u2026]");
3413
3563
  points.forEach((p, i) => {
@@ -3481,7 +3631,7 @@ function stagger(items, options = {}) {
3481
3631
  const isCount = typeof items === "number";
3482
3632
  const n = isCount ? items : items.length;
3483
3633
  if (!Number.isInteger(n) || n < 0) throw new Error(`stagger(): count must be a whole number of items, got ${n}`);
3484
- chunkUZTKEYFP_cjs.warnUnknownOptions("stagger()", options, STAGGER_KEYS);
3634
+ chunkTWZNOUM7_cjs.warnUnknownOptions("stagger()", options, STAGGER_KEYS);
3485
3635
  const { each, amount, from = "start", grid, ease = "none", seed = 0 } = options;
3486
3636
  if (each !== void 0 && amount !== void 0) throw new Error("stagger(): give `each` (seconds between neighbours) or `amount` (seconds in total), not both");
3487
3637
  if (each !== void 0 && !(Number.isFinite(each) && each >= 0)) throw new Error(`stagger(): each must be a number of seconds >= 0, got ${each}`);
@@ -3506,7 +3656,7 @@ function distances(n, from, grid, seed) {
3506
3656
  if (n === 0) return [];
3507
3657
  if (from === "random") {
3508
3658
  const order = Array.from({ length: n }, (_, i) => i);
3509
- const r = chunkIFZOI3JQ_cjs.random(seed);
3659
+ const r = chunkDP37TTMO_cjs.random(seed);
3510
3660
  for (let i = n - 1; i > 0; i--) {
3511
3661
  const j = Math.floor(r() * (i + 1));
3512
3662
  [order[i], order[j]] = [order[j], order[i]];
@@ -3543,7 +3693,7 @@ function distances(n, from, grid, seed) {
3543
3693
  var WIGGLE_KEYS = ["at", "duration", "freq", "seed", "ease", "props"];
3544
3694
  var MAX_STEPS3 = 2e3;
3545
3695
  function wiggle(opts) {
3546
- chunkUZTKEYFP_cjs.warnUnknownOptions("wiggle()", opts, WIGGLE_KEYS);
3696
+ chunkTWZNOUM7_cjs.warnUnknownOptions("wiggle()", opts, WIGGLE_KEYS);
3547
3697
  const { at = 0, duration, freq = 3, seed = 0, ease = "sine.inOut", props } = opts;
3548
3698
  if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`wiggle(): duration must be a positive number of seconds, got ${duration}`);
3549
3699
  if (!(Number.isFinite(freq) && freq > 0)) throw new Error(`wiggle(): freq must be a positive number (steps per second), got ${freq}`);
@@ -3568,7 +3718,7 @@ function wiggle(opts) {
3568
3718
  to[n] = p.around;
3569
3719
  return;
3570
3720
  }
3571
- const off = (chunkIFZOI3JQ_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3721
+ const off = (chunkDP37TTMO_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3572
3722
  to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
3573
3723
  });
3574
3724
  out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
@@ -3591,7 +3741,7 @@ var PRESETS = {
3591
3741
  };
3592
3742
  var PRESET_NAMES = Object.keys(PRESETS);
3593
3743
  function animateText(text, style, options) {
3594
- chunkUZTKEYFP_cjs.warnUnknownOptions("animateText()", options, KEYS5);
3744
+ chunkTWZNOUM7_cjs.warnUnknownOptions("animateText()", options, KEYS5);
3595
3745
  const { by = "chars", x = 0, y = 0, align = "left", name = "text", at = 0, duration, idle, styleFor } = options;
3596
3746
  for (const [n, v] of [["x", x], ["y", y]]) {
3597
3747
  if (typeof v !== "number" || !Number.isFinite(v)) {
@@ -3667,11 +3817,11 @@ function resolveTween(spec, which) {
3667
3817
  if (TWEEN_KEYS.includes(key)) continue;
3668
3818
  if (TIME_KEYS.includes(key)) {
3669
3819
  console.warn(`pixi-effects: animateText(): ${which}.${key} ("${key}") is ignored: ${which === "out" ? "an out leaves from the END of the layer (at + duration), so to make the text gone at a time T set duration to T \u2212 at" : "the entrance starts when the piece starts (the options' at, plus the stagger)"}`);
3670
- } else chunkUZTKEYFP_cjs.warnUnknownOptions(`animateText() ${which}`, { [key]: 1 }, TWEEN_KEYS);
3820
+ } else chunkTWZNOUM7_cjs.warnUnknownOptions(`animateText() ${which}`, { [key]: 1 }, TWEEN_KEYS);
3671
3821
  }
3672
3822
  }
3673
3823
  if (t.preset !== void 0 && !(t.preset in PRESETS)) {
3674
- const guess = chunkUZTKEYFP_cjs.suggestName(String(t.preset), PRESET_NAMES);
3824
+ const guess = chunkTWZNOUM7_cjs.suggestName(String(t.preset), PRESET_NAMES);
3675
3825
  throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")})`);
3676
3826
  }
3677
3827
  const base = t.preset ? PRESETS[t.preset] : void 0;
@@ -3692,7 +3842,7 @@ var KEYS6 = ["at", "duration", "props", "audioOffset", "loop", "frameRate"];
3692
3842
  var PROP_KEYS = ["base", "amount", "band", "beats", "decay", "attack", "release", "invert", "curve"];
3693
3843
  var MAX_STEPS4 = 4e3;
3694
3844
  function react(env, options) {
3695
- chunkUZTKEYFP_cjs.warnUnknownOptions("react()", options, KEYS6);
3845
+ chunkTWZNOUM7_cjs.warnUnknownOptions("react()", options, KEYS6);
3696
3846
  const { at = 0, duration, props, audioOffset = 0, loop = false } = options;
3697
3847
  const frameRate = options.frameRate ?? env.frameRate;
3698
3848
  if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`react(): duration must be a positive number of seconds, got ${duration}`);
@@ -3701,7 +3851,7 @@ function react(env, options) {
3701
3851
  if (names.length === 0) throw new Error("react(): props is empty; name at least one property, e.g. props: { scale: { base: 1, amount: 0.3 } }");
3702
3852
  for (const n of names) {
3703
3853
  const p = props[n];
3704
- chunkUZTKEYFP_cjs.warnUnknownOptions(`react() props.${n}`, p, PROP_KEYS);
3854
+ chunkTWZNOUM7_cjs.warnUnknownOptions(`react() props.${n}`, p, PROP_KEYS);
3705
3855
  if (!Number.isFinite(p.amount)) throw new Error(`react(): props.${n}.amount must be a number, got ${p.amount}`);
3706
3856
  if (!p.beats && p.band !== void 0 && !env.series[p.band]) throw new Error(`react(): props.${n}: band "${p.band}" is not in this envelope (it has: ${Object.keys(env.series).join(", ")})`);
3707
3857
  if (p.beats && !(p.decay === void 0 || Number.isFinite(p.decay) && p.decay > 0)) throw new Error(`react(): props.${n}.decay must be a positive number of seconds, got ${p.decay}`);
@@ -3808,7 +3958,7 @@ function tempo(beats) {
3808
3958
  return Math.round(60 / median * 10) / 10;
3809
3959
  }
3810
3960
  function computeEnvelope(audio, options = {}) {
3811
- chunkUZTKEYFP_cjs.warnUnknownOptions("audioEnvelope()", options, OPTION_KEYS);
3961
+ chunkTWZNOUM7_cjs.warnUnknownOptions("audioEnvelope()", options, OPTION_KEYS);
3812
3962
  const frameRate = options.frameRate ?? 30;
3813
3963
  if (!(Number.isFinite(frameRate) && frameRate > 0)) throw new Error(`pixi-effects: audioEnvelope(): frameRate must be a positive number, got ${frameRate}`);
3814
3964
  const bands = options.bands ?? DEFAULT_BANDS;
@@ -3932,7 +4082,7 @@ async function audioEnvelope(source, options = {}) {
3932
4082
 
3933
4083
  // src/audio/musicEnvelope.ts
3934
4084
  async function musicEnvelope(music, options = {}) {
3935
- const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-GEAH2XCT.cjs');
4085
+ const { resolveMusic, renderMusic, musicLength, musicBeatTimes, TempoMap } = await import('./music-KB7YZLHP.cjs');
3936
4086
  const messages = [];
3937
4087
  const m = resolveMusic(music, "musicEnvelope()", (msg) => messages.push(msg));
3938
4088
  if (!m) throw new Error(`pixi-effects: musicEnvelope(): ${messages.join(" ") || "the music has nothing to play"}`);
@@ -3945,7 +4095,7 @@ async function musicEnvelope(music, options = {}) {
3945
4095
 
3946
4096
  // src/audio/musicBuffer.ts
3947
4097
  async function musicBuffer(music, options = {}) {
3948
- const { resolveMusic, renderMusic, musicLength } = await import('./music-GEAH2XCT.cjs');
4098
+ const { resolveMusic, renderMusic, musicLength } = await import('./music-KB7YZLHP.cjs');
3949
4099
  const messages = [];
3950
4100
  const m = resolveMusic(music, "musicBuffer()", (msg) => messages.push(msg));
3951
4101
  if (!m) throw new Error(`pixi-effects: musicBuffer(): ${messages.join(" ") || "the music has nothing to play"}`);
@@ -3965,11 +4115,11 @@ var PAGE_KEYS = ["name", "duration", "sequences", "stops", "notes", "advance", "
3965
4115
  var DECK_KEYS = ["pages", "transition", "width", "height", "frameRate", "background", "canvas", "assets", "poster", "motionBlur", "loader"];
3966
4116
  function deck(options) {
3967
4117
  if (!options || !Array.isArray(options.pages) || options.pages.length === 0) throw new Error("deck(): pages must be a list with at least one page: { pages: [{ name, duration, stops, sequences }] }");
3968
- chunkUZTKEYFP_cjs.warnUnknownOptions("deck()", options, DECK_KEYS);
4118
+ chunkTWZNOUM7_cjs.warnUnknownOptions("deck()", options, DECK_KEYS);
3969
4119
  const { pages, transition, ...movieOptions } = options;
3970
4120
  pages.forEach((p, i) => {
3971
4121
  if (!p || typeof p !== "object") throw new Error(`deck(): pages[${i}] must be an object`);
3972
- chunkUZTKEYFP_cjs.warnUnknownOptions(`deck() pages[${i}]`, p, PAGE_KEYS);
4122
+ chunkTWZNOUM7_cjs.warnUnknownOptions(`deck() pages[${i}]`, p, PAGE_KEYS);
3973
4123
  if (!(typeof p.duration === "number" && Number.isFinite(p.duration) && p.duration > 0)) throw new Error(`deck(): pages[${i}].duration must be a positive number of seconds, got ${String(p.duration)}`);
3974
4124
  if (!Array.isArray(p.sequences)) throw new Error(`deck(): pages[${i}].sequences must be a list of layers (it may be empty), got ${typeof p.sequences}`);
3975
4125
  });
@@ -3989,7 +4139,7 @@ function deck(options) {
3989
4139
  const label = page.name ? `"${page.name}"` : `pages[${i}]`;
3990
4140
  const isLast = i === pages.length - 1;
3991
4141
  const entries = (page.stops ?? [isLast ? page.duration : page.duration - overlap]).map((e, k) => {
3992
- if (e && typeof e === "object") chunkUZTKEYFP_cjs.warnUnknownOptions(`deck() page ${label} stops[${k}]`, e, ["at", "pdf"]);
4142
+ if (e && typeof e === "object") chunkTWZNOUM7_cjs.warnUnknownOptions(`deck() page ${label} stops[${k}]`, e, ["at", "pdf"]);
3993
4143
  return typeof e === "object" && e !== null ? e : { at: e };
3994
4144
  });
3995
4145
  const local = entries.map((e) => e.at);
@@ -4023,7 +4173,7 @@ var round2 = (v) => Math.round(v * 1e6) / 1e6;
4023
4173
 
4024
4174
  // src/transforms/withFade.ts
4025
4175
  function withFade(spec, opts) {
4026
- chunkUZTKEYFP_cjs.warnUnknownOptions("withFade()", opts, ["in", "out"]);
4176
+ chunkTWZNOUM7_cjs.warnUnknownOptions("withFade()", opts, ["in", "out"]);
4027
4177
  if (opts.in != null && opts.in > 0) {
4028
4178
  spec.initial = { ...spec.initial ?? {}, alpha: 0 };
4029
4179
  const kf = { at: 0, to: { alpha: 1 }, duration: opts.in };
@@ -4043,19 +4193,19 @@ function withFade(spec, opts) {
4043
4193
 
4044
4194
  Object.defineProperty(exports, "noise", {
4045
4195
  enumerable: true,
4046
- get: function () { return chunkIFZOI3JQ_cjs.noise; }
4196
+ get: function () { return chunkDP37TTMO_cjs.noise; }
4047
4197
  });
4048
4198
  Object.defineProperty(exports, "rand", {
4049
4199
  enumerable: true,
4050
- get: function () { return chunkIFZOI3JQ_cjs.rand; }
4200
+ get: function () { return chunkDP37TTMO_cjs.rand; }
4051
4201
  });
4052
4202
  Object.defineProperty(exports, "random", {
4053
4203
  enumerable: true,
4054
- get: function () { return chunkIFZOI3JQ_cjs.random; }
4204
+ get: function () { return chunkDP37TTMO_cjs.random; }
4055
4205
  });
4056
4206
  Object.defineProperty(exports, "registerSequenceType", {
4057
4207
  enumerable: true,
4058
- get: function () { return chunkIFZOI3JQ_cjs.registerSequenceType; }
4208
+ get: function () { return chunkDP37TTMO_cjs.registerSequenceType; }
4059
4209
  });
4060
4210
  exports.Movie = Movie;
4061
4211
  exports.animateText = animateText;