pixi-effects 0.48.2 → 0.50.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 (88) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +53 -8
  3. package/ai/chat-template.html +8 -4
  4. package/ai/tools/check.mjs +6 -6
  5. package/dist/3d.cjs +967 -0
  6. package/dist/3d.cjs.map +1 -0
  7. package/dist/3d.d.cts +305 -0
  8. package/dist/3d.d.ts +305 -0
  9. package/dist/3d.js +960 -0
  10. package/dist/3d.js.map +1 -0
  11. package/dist/Canvas-BfZkAFJm.d.cts +12 -0
  12. package/dist/Canvas-BfZkAFJm.d.ts +12 -0
  13. package/dist/Composition-47U5U637.cjs +16 -0
  14. package/dist/{Composition-TJ5D7Z63.cjs.map → Composition-47U5U637.cjs.map} +1 -1
  15. package/dist/Composition-GVWWLFDL.js +7 -0
  16. package/dist/{Composition-5FKV2IBP.js.map → Composition-GVWWLFDL.js.map} +1 -1
  17. package/dist/Controller.d.cts +2 -2
  18. package/dist/Controller.d.ts +2 -2
  19. package/dist/{Movie-svZQF-9Z.d.cts → Movie-DogzDBuW.d.cts} +36 -5
  20. package/dist/{Movie--qSYKgAQ.d.ts → Movie-Y7iHg2V8.d.ts} +36 -5
  21. package/dist/{Spans-6A3VLHRH.js → Spans-3SEZSTQV.js} +6 -6
  22. package/dist/{Spans-6A3VLHRH.js.map → Spans-3SEZSTQV.js.map} +1 -1
  23. package/dist/{Spans-5ENZ3XGS.cjs → Spans-R426NVY3.cjs} +11 -11
  24. package/dist/{Spans-5ENZ3XGS.cjs.map → Spans-R426NVY3.cjs.map} +1 -1
  25. package/dist/{blendModes-V5XHC7U4.cjs → blendModes-2IDILRN6.cjs} +5 -5
  26. package/dist/{blendModes-V5XHC7U4.cjs.map → blendModes-2IDILRN6.cjs.map} +1 -1
  27. package/dist/{blendModes-535EMYGK.js → blendModes-4QH44GOL.js} +4 -4
  28. package/dist/{blendModes-535EMYGK.js.map → blendModes-4QH44GOL.js.map} +1 -1
  29. package/dist/{chunk-NGJXVJB7.cjs → chunk-3FCDRLW3.cjs} +5 -3
  30. package/dist/chunk-3FCDRLW3.cjs.map +1 -0
  31. package/dist/{chunk-JBDBICS2.js → chunk-C2HL5236.js} +4 -4
  32. package/dist/{chunk-JBDBICS2.js.map → chunk-C2HL5236.js.map} +1 -1
  33. package/dist/{chunk-WYR2AU4W.cjs → chunk-GXGIISFS.cjs} +5 -5
  34. package/dist/{chunk-WYR2AU4W.cjs.map → chunk-GXGIISFS.cjs.map} +1 -1
  35. package/dist/{chunk-BFRWSV3R.js → chunk-J4ZP76IL.js} +5 -4
  36. package/dist/chunk-J4ZP76IL.js.map +1 -0
  37. package/dist/{chunk-CCPJD76D.cjs → chunk-O2MD3L4J.cjs} +93 -93
  38. package/dist/chunk-O2MD3L4J.cjs.map +1 -0
  39. package/dist/{chunk-IVKI6CPH.js → chunk-SSVHAF3Q.js} +483 -20
  40. package/dist/chunk-SSVHAF3Q.js.map +1 -0
  41. package/dist/{chunk-6D4W2KZQ.js → chunk-TXNQLMRT.js} +6 -6
  42. package/dist/chunk-TXNQLMRT.js.map +1 -0
  43. package/dist/{chunk-RCKLUCB7.js → chunk-UTUUOQ47.js} +46 -20
  44. package/dist/chunk-UTUUOQ47.js.map +1 -0
  45. package/dist/{chunk-Z3DM4ETD.cjs → chunk-VVUSZVP7.cjs} +507 -42
  46. package/dist/chunk-VVUSZVP7.cjs.map +1 -0
  47. package/dist/{chunk-45ALIMAF.cjs → chunk-YOKRPAKA.cjs} +89 -63
  48. package/dist/chunk-YOKRPAKA.cjs.map +1 -0
  49. package/dist/index.cjs +35 -35
  50. package/dist/index.d.cts +3 -3
  51. package/dist/index.d.ts +3 -3
  52. package/dist/index.js +5 -5
  53. package/dist/loader.css +1 -1
  54. package/dist/{music-P4JRT73P.js → music-ATX22VAT.js} +3 -3
  55. package/dist/{music-P4JRT73P.js.map → music-ATX22VAT.js.map} +1 -1
  56. package/dist/{music-XQEPBIDT.cjs → music-OFVM3PYH.cjs} +3 -3
  57. package/dist/{music-XQEPBIDT.cjs.map → music-OFVM3PYH.cjs.map} +1 -1
  58. package/dist/present.cjs +5 -5
  59. package/dist/present.d.cts +2 -2
  60. package/dist/present.d.ts +2 -2
  61. package/dist/present.js +5 -5
  62. package/dist/three.cjs +13 -10
  63. package/dist/three.cjs.map +1 -1
  64. package/dist/three.d.cts +4 -12
  65. package/dist/three.d.ts +4 -12
  66. package/dist/three.js +8 -5
  67. package/dist/three.js.map +1 -1
  68. package/dist/{types-CTSrPvY3.d.cts → types-BZngm4nT.d.cts} +48 -5
  69. package/dist/{types-CTSrPvY3.d.ts → types-BZngm4nT.d.ts} +48 -5
  70. package/docs/api.md +45 -2
  71. package/docs/dsl.md +115 -1
  72. package/llms-full.txt +307 -6
  73. package/package.json +19 -3
  74. package/skills/pixi-effects/SKILL.md +4 -2
  75. package/skills/pixi-effects/reference/cheatsheet.md +4 -0
  76. package/skills/pixi-effects/reference/pitfalls.md +20 -0
  77. package/skills/pixi-effects/reference/recipes.md +119 -1
  78. package/skills/pixi-effects/template.html +14 -8
  79. package/dist/Composition-5FKV2IBP.js +0 -7
  80. package/dist/Composition-TJ5D7Z63.cjs +0 -16
  81. package/dist/chunk-45ALIMAF.cjs.map +0 -1
  82. package/dist/chunk-6D4W2KZQ.js.map +0 -1
  83. package/dist/chunk-BFRWSV3R.js.map +0 -1
  84. package/dist/chunk-CCPJD76D.cjs.map +0 -1
  85. package/dist/chunk-IVKI6CPH.js.map +0 -1
  86. package/dist/chunk-NGJXVJB7.cjs.map +0 -1
  87. package/dist/chunk-RCKLUCB7.js.map +0 -1
  88. package/dist/chunk-Z3DM4ETD.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkNGJXVJB7_cjs = require('./chunk-NGJXVJB7.cjs');
3
+ var chunk3FCDRLW3_cjs = require('./chunk-3FCDRLW3.cjs');
4
4
  var chunkDOLTCXCL_cjs = require('./chunk-DOLTCXCL.cjs');
5
5
  var pixi_js = require('pixi.js');
6
6
 
@@ -514,9 +514,9 @@ var PureTimeline = class _PureTimeline {
514
514
  };
515
515
  const ends = given(vars);
516
516
  const starts = fromVars ? given(fromVars) : /* @__PURE__ */ new Map();
517
- const ids = kind === "fromTo" ? [.../* @__PURE__ */ new Set([...starts.keys(), ...ends.keys()])] : [...ends.keys()];
517
+ const ids2 = kind === "fromTo" ? [.../* @__PURE__ */ new Set([...starts.keys(), ...ends.keys()])] : [...ends.keys()];
518
518
  let lastAlpha;
519
- for (const id of ids) {
519
+ for (const id of ids2) {
520
520
  const e = ends.get(id), f = starts.get(id);
521
521
  const acc = (e ?? f).acc;
522
522
  const ch = this.channel(t, acc);
@@ -1385,6 +1385,9 @@ var PIXI_SHORTHANDS = /* @__PURE__ */ new Set([
1385
1385
  "fillColor",
1386
1386
  "fillAlpha"
1387
1387
  ]);
1388
+ function routedProp(prop, value) {
1389
+ return prop === "tint" ? { pixi: { tint: value } } : { [prop]: value };
1390
+ }
1388
1391
  function pixiwrap(props) {
1389
1392
  const out = {};
1390
1393
  const pixi = {};
@@ -1407,7 +1410,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
1407
1410
  if (kf.kind === "set") {
1408
1411
  const resolved = normalizeProps(kf.set, scope, { skipKeys, relative: "allow" });
1409
1412
  const { rest, routed } = splitRouted(resolved, routers);
1410
- for (const r of routed) timeline.set(r.target, { [r.prop]: r.value }, at);
1413
+ for (const r of routed) timeline.set(r.target, routedProp(r.prop, r.value), at);
1411
1414
  const { ownProps, filterProps } = partitionProps(rest);
1412
1415
  if (Object.keys(ownProps).length > 0) timeline.set(target, pixiwrap(ownProps), at);
1413
1416
  for (const [name, props] of Object.entries(filterProps)) {
@@ -1419,7 +1422,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
1419
1422
  const resolved = normalizeProps(kf.to, scope, { skipKeys, relative: "allow" });
1420
1423
  const { rest, routed } = splitRouted(resolved, routers);
1421
1424
  for (const r of routed)
1422
- timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1425
+ timeline.to(r.target, { ...routedProp(r.prop, r.value), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1423
1426
  const { ownProps, filterProps } = partitionProps(rest);
1424
1427
  if (Object.keys(ownProps).length > 0)
1425
1428
  timeline.to(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
@@ -1432,7 +1435,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
1432
1435
  const resolved = normalizeProps(kf.from, scope, { skipKeys, relative: "allow" });
1433
1436
  const { rest, routed } = splitRouted(resolved, routers);
1434
1437
  for (const r of routed)
1435
- timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1438
+ timeline.from(r.target, { ...routedProp(r.prop, r.value), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1436
1439
  const { ownProps, filterProps } = partitionProps(rest);
1437
1440
  if (Object.keys(ownProps).length > 0)
1438
1441
  timeline.from(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
@@ -1453,16 +1456,16 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
1453
1456
  if (f) {
1454
1457
  timeline.fromTo(
1455
1458
  r.target,
1456
- { [r.prop]: f.value },
1457
- { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop },
1459
+ routedProp(r.prop, f.value),
1460
+ { ...routedProp(r.prop, r.value), duration: kf.duration, ease: kf.ease, ...kf.loop },
1458
1461
  at
1459
1462
  );
1460
1463
  } else {
1461
- timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1464
+ timeline.to(r.target, { ...routedProp(r.prop, r.value), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1462
1465
  }
1463
1466
  }
1464
1467
  for (const f of fromByKey.values())
1465
- timeline.from(f.target, { [f.prop]: f.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1468
+ timeline.from(f.target, { ...routedProp(f.prop, f.value), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
1466
1469
  const fromSplit = partitionProps(fromRouted.rest);
1467
1470
  const toSplit = partitionProps(toRouted.rest);
1468
1471
  const ownKeys = /* @__PURE__ */ new Set([...Object.keys(fromSplit.ownProps), ...Object.keys(toSplit.ownProps)]);
@@ -1495,7 +1498,7 @@ function applyInitial(target, initial, scope, skipKeys = [], routers) {
1495
1498
  if (!initial) return;
1496
1499
  const resolved = normalizeProps(initial, scope, { skipKeys, where: "initial" });
1497
1500
  const { rest, routed } = splitRouted(resolved, routers);
1498
- for (const r of routed) setNow(r.target, { [r.prop]: r.value });
1501
+ for (const r of routed) setNow(r.target, routedProp(r.prop, r.value));
1499
1502
  const { ownProps, filterProps } = partitionProps(rest);
1500
1503
  if (Object.keys(ownProps).length > 0) setNow(target, pixiwrap(ownProps));
1501
1504
  for (const [name, props] of Object.entries(filterProps)) {
@@ -2976,7 +2979,7 @@ var TextSequence = class extends Sequence {
2976
2979
  if (this.spec.resolution !== void 0) {
2977
2980
  const r = this.spec.resolution;
2978
2981
  if (typeof r === "number" && r >= 1 && r <= 8) text.resolution = r;
2979
- else console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: resolution must be a number from 1 to 8 (the text is drawn at that many times the pixels), got ${JSON.stringify(r)}: ignored`);
2982
+ else console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: resolution must be a number from 1 to 8 (the text is drawn at that many times the pixels), got ${JSON.stringify(r)}: ignored`);
2980
2983
  }
2981
2984
  this.target = text;
2982
2985
  this.intrinsicWidth = text.width;
@@ -2992,7 +2995,7 @@ var TextSequence = class extends Sequence {
2992
2995
  { skipKeys: STYLE_OPAQUE_KEYS }
2993
2996
  );
2994
2997
  const unset = Object.keys(resolved).filter((k) => resolved[k] === void 0);
2995
- if (unset.length) console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: ${unset.map((k) => `style.${k}`).join(", ")} ${unset.length > 1 ? "are" : "is"} undefined (a variable that was never set?), so ${unset.length > 1 ? "they are" : "it is"} ignored and the default is used: omit the key instead`);
2998
+ if (unset.length) console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: ${unset.map((k) => `style.${k}`).join(", ")} ${unset.length > 1 ? "are" : "is"} undefined (a variable that was never set?), so ${unset.length > 1 ? "they are" : "it is"} ignored and the default is used: omit the key instead`);
2996
2999
  const outline = resolved.stroke;
2997
3000
  if (outline && typeof outline === "object" && !("join" in outline) && !("lineJoin" in outline)) resolved.stroke = { ...outline, join: "round" };
2998
3001
  for (const k of Object.keys(resolved)) {
@@ -3004,7 +3007,7 @@ var TextSequence = class extends Sequence {
3004
3007
  }
3005
3008
  const startFill = initialProps.fill;
3006
3009
  if (typeof startFill === "string" || typeof startFill === "number") text.style.fill = startFill;
3007
- validateGradientKeyframes(this.spec, chunkNGJXVJB7_cjs.describeLayer(this.spec), void 0, "text");
3010
+ validateGradientKeyframes(this.spec, chunk3FCDRLW3_cjs.describeLayer(this.spec), void 0, "text");
3008
3011
  const gradientSpec = this.spec.fillGradient ?? initialProps.fillGradient;
3009
3012
  if (gradientSpec) {
3010
3013
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -3040,7 +3043,7 @@ var TextSequence = class extends Sequence {
3040
3043
  bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
3041
3044
  this._template = t;
3042
3045
  refresh();
3043
- }, chunkNGJXVJB7_cjs.describeLayer(this.spec));
3046
+ }, chunk3FCDRLW3_cjs.describeLayer(this.spec));
3044
3047
  }
3045
3048
  };
3046
3049
  function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
@@ -3490,7 +3493,7 @@ var CameraSequence = class extends Sequence {
3490
3493
  carrier.fogColor = "#000000";
3491
3494
  carrier.fogAmount = 1;
3492
3495
  this.target = carrier;
3493
- const keys = chunkNGJXVJB7_cjs.collectPropKeys(this.spec);
3496
+ const keys = chunk3FCDRLW3_cjs.collectPropKeys(this.spec);
3494
3497
  this.autoZ = !keys.has("z");
3495
3498
  this.dof = keys.has("focus") || keys.has("aperture");
3496
3499
  this.fog = keys.has("fogNear") || keys.has("fogFar") || keys.has("fogColor") || keys.has("fogAmount");
@@ -3811,7 +3814,7 @@ function resolveSpansStyle(style, scope, who, warn = defaultWarn) {
3811
3814
  var TEXT_ONLY = ["type", "spans", "text", "style", "format", "colorSpace", "fillGradient", "initial", "keyframes", "resolution"];
3812
3815
  var NOT_FOR_A_GROUP = ["fill", "text", "value", "fillGradient"];
3813
3816
  function expandSpans(spec, warn = defaultWarn, scope) {
3814
- const who = chunkNGJXVJB7_cjs.describeLayer(spec);
3817
+ const who = chunk3FCDRLW3_cjs.describeLayer(spec);
3815
3818
  const s = spec;
3816
3819
  if (s.text !== void 0) warn(`pixi-effects: ${who}: "text" is ignored when the layer has spans: write the text as spans`);
3817
3820
  const style = resolveSpansStyle(s.style ?? {}, scope, who, warn);
@@ -3870,7 +3873,7 @@ var ImageSequence = class extends Sequence {
3870
3873
  const source = texture.source;
3871
3874
  if (source && !ORIGINAL_SCALE_MODE.has(source)) ORIGINAL_SCALE_MODE.set(source, source.scaleMode);
3872
3875
  const mode = this.spec.scaleMode;
3873
- if (mode !== void 0 && mode !== "nearest" && mode !== "linear") console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: scaleMode "${String(mode)}" is not "nearest" or "linear": ignored`);
3876
+ if (mode !== void 0 && mode !== "nearest" && mode !== "linear") console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: scaleMode "${String(mode)}" is not "nearest" or "linear": ignored`);
3874
3877
  if (source) source.scaleMode = mode === "nearest" || mode === "linear" ? mode : ORIGINAL_SCALE_MODE.get(source);
3875
3878
  const sprite = new pixi_js.Sprite({ texture, label: this.spec.name });
3876
3879
  sprite.cullable = true;
@@ -3979,12 +3982,12 @@ var AudioSequence = class extends Sequence {
3979
3982
  const playable = this._remap && this._remap.timeKfs.length > 0 ? Infinity : (data.duration ?? Infinity) / constant;
3980
3983
  if (!spec.loop && Number.isFinite(playable) && this.duration > playable + 0.05) {
3981
3984
  console.warn(
3982
- `pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(spec)}: audio asset "${spec.asset}" plays for ${playable.toFixed(1)}s (${data.duration.toFixed(1)}s at speed ${constant}) but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${playable.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
3985
+ `pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(spec)}: audio asset "${spec.asset}" plays for ${playable.toFixed(1)}s (${data.duration.toFixed(1)}s at speed ${constant}) but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${playable.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
3983
3986
  );
3984
3987
  }
3985
3988
  }
3986
3989
  async _buildSfx(spec) {
3987
- const who = chunkNGJXVJB7_cjs.describeLayer(spec);
3990
+ const who = chunk3FCDRLW3_cjs.describeLayer(spec);
3988
3991
  const raw = spec;
3989
3992
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
3990
3993
  if (raw.loop) console.warn(`pixi-effects: ${who}: loop has no effect on an sfx \u2014 to repeat it, add one audio layer per hit (a JS loop)`);
@@ -4003,11 +4006,11 @@ var AudioSequence = class extends Sequence {
4003
4006
  });
4004
4007
  }
4005
4008
  async _buildMusic(spec) {
4006
- const who = chunkNGJXVJB7_cjs.describeLayer(spec);
4009
+ const who = chunk3FCDRLW3_cjs.describeLayer(spec);
4007
4010
  const raw = spec;
4008
4011
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
4009
4012
  if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
4010
- const { resolveMusic, renderMusic, renderMusicAsync, musicLength, musicKey, summarizeMusic } = await import('./music-XQEPBIDT.cjs');
4013
+ const { resolveMusic, renderMusic, renderMusicAsync, musicLength, musicKey, summarizeMusic } = await import('./music-OFVM3PYH.cjs');
4011
4014
  const music = resolveMusic(spec.music, who);
4012
4015
  if (!music) return;
4013
4016
  const natural = musicLength(music);
@@ -4038,7 +4041,7 @@ var AudioSequence = class extends Sequence {
4038
4041
  out.push({
4039
4042
  ...sourceMap ? { sourceMap } : {},
4040
4043
  ...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
4041
- layer: chunkNGJXVJB7_cjs.describeLayer(this.spec),
4044
+ layer: chunk3FCDRLW3_cjs.describeLayer(this.spec),
4042
4045
  source: this._source,
4043
4046
  ...this._music ? { music: this._music } : {},
4044
4047
  loop: !this._synth && !!this.spec.loop,
@@ -4580,7 +4583,7 @@ var VideoSequence = class extends Sequence {
4580
4583
  out.push({
4581
4584
  ...sourceMap ? { sourceMap } : {},
4582
4585
  buffer: this._audioBuffer,
4583
- layer: chunkNGJXVJB7_cjs.describeLayer(this.spec),
4586
+ layer: chunk3FCDRLW3_cjs.describeLayer(this.spec),
4584
4587
  source: `video "${this.spec.asset}"`,
4585
4588
  loop: !!this.spec.loop,
4586
4589
  start: baseTime + this.at,
@@ -4890,20 +4893,20 @@ var ShapeSequence = class extends Sequence {
4890
4893
  for (const k of geomKeys) this._liveKeys.add(k);
4891
4894
  seedGeometry(this._state, this.spec, scope);
4892
4895
  seedStyle(this._state, this.spec.initial ?? {}, scope);
4893
- seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunkNGJXVJB7_cjs.describeLayer(this.spec));
4896
+ seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunk3FCDRLW3_cjs.describeLayer(this.spec));
4894
4897
  if (this.spec.shape === "arc") {
4895
4898
  this._state.startAngle ??= 0;
4896
4899
  this._state.endAngle ??= 360;
4897
4900
  const top = this.spec, ini = this.spec.initial ?? {};
4898
4901
  if ("trimStart" in top || "trimEnd" in top || "trimStart" in ini || "trimEnd" in ini) {
4899
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
4902
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
4900
4903
  }
4901
4904
  } else {
4902
4905
  this._state.trimStart ??= 0;
4903
4906
  this._state.trimEnd ??= 1;
4904
4907
  }
4905
4908
  const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
4906
- validateGradientKeyframes(this.spec, chunkNGJXVJB7_cjs.describeLayer(this.spec));
4909
+ validateGradientKeyframes(this.spec, chunk3FCDRLW3_cjs.describeLayer(this.spec));
4907
4910
  if (gradientSpec) {
4908
4911
  if (hasGradientKeys(this.spec.keyframes)) {
4909
4912
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -4947,9 +4950,9 @@ var ShapeSequence = class extends Sequence {
4947
4950
  }
4948
4951
  /** The prepared morph between `d` and `morphTo`, or null (and a warning when the spec asked for one that cannot work). */
4949
4952
  _setupMorph() {
4950
- const who = chunkNGJXVJB7_cjs.describeLayer(this.spec);
4953
+ const who = chunk3FCDRLW3_cjs.describeLayer(this.spec);
4951
4954
  const top = this.spec;
4952
- const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunkNGJXVJB7_cjs.collectPropKeys(this.spec).has("morph"));
4955
+ const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunk3FCDRLW3_cjs.collectPropKeys(this.spec).has("morph"));
4953
4956
  if (this.spec.shape !== "path") {
4954
4957
  if ("morphTo" in top) console.warn(`pixi-effects: ${who}: morphTo only works on a path shape (shape: 'path'); ignored`);
4955
4958
  return null;
@@ -5585,7 +5588,7 @@ var ShaderSequence = class extends Sequence {
5585
5588
  }
5586
5589
  async build() {
5587
5590
  const spec = this.shaderSpec;
5588
- const who = chunkNGJXVJB7_cjs.describeLayer(spec);
5591
+ const who = chunk3FCDRLW3_cjs.describeLayer(spec);
5589
5592
  for (const m of shaderProblems(spec)) console.warn(`pixi-effects: ${who}: ${m}`);
5590
5593
  if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
5591
5594
  const scope = buildScope(this, this.parent, this.root);
@@ -5629,7 +5632,7 @@ var ShaderSequence = class extends Sequence {
5629
5632
  const warn = (why) => {
5630
5633
  if (this.warnedPaths.has(path)) return;
5631
5634
  this.warnedPaths.add(path);
5632
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: keyframe path uniforms.${path} ${why}; skipped`);
5635
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: keyframe path uniforms.${path} ${why}; skipped`);
5633
5636
  };
5634
5637
  if (slot === void 0) {
5635
5638
  const guess = chunkDOLTCXCL_cjs.suggestName(name, Object.keys(this.carrier));
@@ -5664,7 +5667,7 @@ var ShaderSequence = class extends Sequence {
5664
5667
  this.failed = true;
5665
5668
  if (!this.warnedNoGl) {
5666
5669
  this.warnedNoGl = true;
5667
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: this browser has no WebGL2, so the shader cannot run; the layer is drawn as a checkerboard`);
5670
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: this browser has no WebGL2, so the shader cannot run; the layer is drawn as a checkerboard`);
5668
5671
  }
5669
5672
  }
5670
5673
  compile() {
@@ -5695,7 +5698,7 @@ var ShaderSequence = class extends Sequence {
5695
5698
  gl.deleteProgram(p);
5696
5699
  this.failed = true;
5697
5700
  this.prog = null;
5698
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: the fragment shader did not compile (the line numbers are the lines of your code):
5701
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: the fragment shader did not compile (the line numbers are the lines of your code):
5699
5702
  ${glslErrors(log).join("\n")}
5700
5703
  The layer is drawn as a checkerboard until it is fixed.`);
5701
5704
  return;
@@ -5774,10 +5777,14 @@ function resolveDim(v, scope) {
5774
5777
  if (typeof v === "number") return v;
5775
5778
  return evaluateExpr(v, scope);
5776
5779
  }
5780
+
5781
+ // src/core/purity.ts
5782
+ var NOT_PURE = /\bMath\s*\.\s*random\s*\(|\bDate\s*\.\s*now\s*\(|\bperformance\s*\.\s*now\s*\(|\bnew\s+Date\s*\(/;
5783
+
5784
+ // src/sequences/Canvas.ts
5777
5785
  var MAX_SIZE = 8192;
5778
5786
  var MIN_RESOLUTION = 0.25;
5779
5787
  var MAX_RESOLUTION = 4;
5780
- var NOT_PURE = /\bMath\s*\.\s*random\s*\(|\bDate\s*\.\s*now\s*\(|\bperformance\s*\.\s*now\s*\(|\bnew\s+Date\s*\(/;
5781
5788
  function seeded(seed) {
5782
5789
  let a = seed >>> 0;
5783
5790
  return () => {
@@ -5822,7 +5829,7 @@ var CanvasSequence = class extends Sequence {
5822
5829
  }
5823
5830
  async build() {
5824
5831
  const spec = this.canvasSpec;
5825
- const who = chunkNGJXVJB7_cjs.describeLayer(spec);
5832
+ const who = chunk3FCDRLW3_cjs.describeLayer(spec);
5826
5833
  if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
5827
5834
  const scope = buildScope(this, this.parent, this.root);
5828
5835
  this.layerW = this.size("width", spec.width, scope, this.parent?.width ?? this.root.width, who);
@@ -5907,7 +5914,7 @@ var CanvasSequence = class extends Sequence {
5907
5914
  say(why) {
5908
5915
  if (this.warnedDraw) return;
5909
5916
  this.warnedDraw = true;
5910
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: ${why}`);
5917
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: ${why}`);
5911
5918
  }
5912
5919
  info(local) {
5913
5920
  const duration = this.duration ?? 0;
@@ -5934,7 +5941,7 @@ var CanvasSequence = class extends Sequence {
5934
5941
  if (!this.warnedPaths.has(path)) {
5935
5942
  this.warnedPaths.add(path);
5936
5943
  const guess = chunkDOLTCXCL_cjs.suggestName(path.split(".")[0], Object.keys(this.carrier));
5937
- console.warn(`pixi-effects: ${chunkNGJXVJB7_cjs.describeLayer(this.spec)}: keyframe path params.${path} names no param "${path}"${guess ? `; did you mean "${guess}"?` : ""} (declare it in params with a starting value); skipped`);
5944
+ console.warn(`pixi-effects: ${chunk3FCDRLW3_cjs.describeLayer(this.spec)}: keyframe path params.${path} names no param "${path}"${guess ? `; did you mean "${guess}"?` : ""} (declare it in params with a starting value); skipped`);
5938
5945
  }
5939
5946
  return null;
5940
5947
  }
@@ -6068,17 +6075,466 @@ var CanvasSequence = class extends Sequence {
6068
6075
  }
6069
6076
  };
6070
6077
 
6078
+ // src/core/setupValues.ts
6079
+ var SetupValues = class {
6080
+ values = /* @__PURE__ */ new Map();
6081
+ /** The value `target[prop]` has now, noted the first time only. */
6082
+ note(target, prop) {
6083
+ let props = this.values.get(target);
6084
+ if (!props) {
6085
+ props = /* @__PURE__ */ new Map();
6086
+ this.values.set(target, props);
6087
+ }
6088
+ if (!props.has(prop)) props.set(prop, target[prop]);
6089
+ }
6090
+ /** For a layer that borrowed: a one-property stand-in for `target[prop]`, the noted value while `borrowed()`, the object itself after. */
6091
+ view(target, prop, borrowed) {
6092
+ this.note(target, prop);
6093
+ const noted = () => this.values.get(target).get(prop);
6094
+ let held = null;
6095
+ const view = {};
6096
+ Object.defineProperty(view, prop, {
6097
+ enumerable: true,
6098
+ get: () => borrowed() ? held ? held.v : noted() : target[prop],
6099
+ set: (v) => {
6100
+ if (borrowed()) held = { v };
6101
+ else target[prop] = v;
6102
+ }
6103
+ });
6104
+ return { target: view, prop };
6105
+ }
6106
+ /** The swap: every noted property back to the value setup left. */
6107
+ restore() {
6108
+ for (const [target, props] of this.values) {
6109
+ for (const [prop, v] of props) {
6110
+ try {
6111
+ target[prop] = v;
6112
+ } catch {
6113
+ }
6114
+ }
6115
+ }
6116
+ }
6117
+ };
6118
+
6119
+ // src/sequences/Scene2D.ts
6120
+ var Scene2DBox = class extends pixi_js.Container {
6121
+ boxWidth = 1;
6122
+ boxHeight = 1;
6123
+ _ax = 0;
6124
+ _ay = 0;
6125
+ anchor = /* @__PURE__ */ (() => {
6126
+ const box = this;
6127
+ return {
6128
+ get x() {
6129
+ return box._ax;
6130
+ },
6131
+ set x(v) {
6132
+ box._ax = v;
6133
+ box.pivot.x = v * box.boxWidth;
6134
+ },
6135
+ get y() {
6136
+ return box._ay;
6137
+ },
6138
+ set y(v) {
6139
+ box._ay = v;
6140
+ box.pivot.y = v * box.boxHeight;
6141
+ },
6142
+ set(x, y = x) {
6143
+ this.x = x;
6144
+ this.y = y;
6145
+ }
6146
+ };
6147
+ })();
6148
+ };
6149
+ var isFlipbook = (n) => {
6150
+ const f = n;
6151
+ return typeof f.gotoAndStop === "function" && typeof f.totalFrames === "number" && typeof f.animationSpeed === "number" && "autoUpdate" in n;
6152
+ };
6153
+ var DEFAULT_LABELS = /* @__PURE__ */ new Set([
6154
+ "Container",
6155
+ "Graphics",
6156
+ "Sprite",
6157
+ "AnimatedSprite",
6158
+ "TilingSprite",
6159
+ "NineSliceSprite",
6160
+ "Text",
6161
+ "BitmapText",
6162
+ "HTMLText",
6163
+ "Mesh",
6164
+ "MeshSimple",
6165
+ "MeshPlane",
6166
+ "MeshRope",
6167
+ "PerspectiveMesh",
6168
+ "ParticleContainer",
6169
+ "RenderContainer",
6170
+ "DOMContainer"
6171
+ ]);
6172
+ var ids = /* @__PURE__ */ new WeakMap();
6173
+ var lastId = 0;
6174
+ function idOf(fn) {
6175
+ if (typeof fn !== "function") return 0;
6176
+ let id = ids.get(fn);
6177
+ if (id === void 0) {
6178
+ id = ++lastId;
6179
+ ids.set(fn, id);
6180
+ }
6181
+ return id;
6182
+ }
6183
+ var Scene2DSequence = class extends Sequence {
6184
+ _box = null;
6185
+ _ctx = null;
6186
+ _objects = {};
6187
+ _flipbooks = [];
6188
+ _warned = /* @__PURE__ */ new Set();
6189
+ /** What a rebuild matches this layer by; null: never kept (`reuse: false`, no `name`). */
6190
+ _key = null;
6191
+ /** The layer of the tree being replaced whose scene this one takes over at the swap (`commitReuse`): until then it is not this layer's. */
6192
+ _borrowed = null;
6193
+ /** True once another layer took this layer's scene: destroying this one must not let it go. */
6194
+ _donated = false;
6195
+ /** What setup left on the objects the keyframes reach, shared with a layer that takes the scene over (core/setupValues.ts). */
6196
+ _setupValues = new SetupValues();
6197
+ get _spec() {
6198
+ return this.spec;
6199
+ }
6200
+ _who() {
6201
+ const name = this._spec.name;
6202
+ return `pixi-effects: scene2d layer${name ? ` "${name}"` : ""}`;
6203
+ }
6204
+ _say(key, message) {
6205
+ if (this._warned.has(key)) return;
6206
+ this._warned.add(key);
6207
+ console.warn(`${this._who()}: ${message}`);
6208
+ }
6209
+ pathRouters() {
6210
+ return { scene2d: (path) => this._resolvePath(path) };
6211
+ }
6212
+ async build() {
6213
+ const spec = this._spec;
6214
+ if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
6215
+ if (typeof spec.setup !== "function") {
6216
+ throw new Error(`${this._who()}: a scene2d layer needs setup: ({ root }) => { \u2026 } (a function that adds PixiJS display objects to root)`);
6217
+ }
6218
+ if (typeof spec.update === "function" && NOT_PURE.test(spec.update.toString())) {
6219
+ this._say("pure", "update calls Math.random, Date.now, performance.now or new Date, so it is not deterministic: the same frame would draw differently in playback, in a seek and in an export. Derive the value from t (random(seed) from pixi-effects is repeatable)");
6220
+ }
6221
+ const scope = buildScope(this, this.parent, this.root);
6222
+ const width = dim(spec.width, scope) ?? this.parent?.width ?? this.root.width;
6223
+ const height = dim(spec.height, scope) ?? this.parent?.height ?? this.root.height;
6224
+ const box = new Scene2DBox({ label: spec.name ?? "scene2d" });
6225
+ box.boxWidth = width;
6226
+ box.boxHeight = height;
6227
+ this._box = box;
6228
+ this.target = box;
6229
+ this.intrinsicWidth = width;
6230
+ this.intrinsicHeight = height;
6231
+ this._key = spec.reuse === false || !spec.name ? null : JSON.stringify(["scene2d", spec.name, idOf(spec.setup), width, height]);
6232
+ const donor = this._key !== null ? this.root.reuse?.claim(this._key, this) : null;
6233
+ if (donor && donor._lendable()) {
6234
+ this._borrowed = donor;
6235
+ this._objects = donor._objects;
6236
+ this._flipbooks = donor._flipbooks;
6237
+ this._setupValues = donor._setupValues;
6238
+ this._ctx = { ...donor._ctx, width, height };
6239
+ this.buildFilters();
6240
+ return;
6241
+ }
6242
+ const root = new pixi_js.Container({ label: "root" });
6243
+ box.addChild(root);
6244
+ const renderer = this.root.pixiRenderer;
6245
+ const objects = {};
6246
+ const ctx = { root, renderer, width, height, objects, texture: (name) => textureOf(name) };
6247
+ let result;
6248
+ try {
6249
+ result = await spec.setup(ctx);
6250
+ } catch (err) {
6251
+ box.destroy({ children: true });
6252
+ this._box = null;
6253
+ this.target = null;
6254
+ throw new Error(`${this._who()}: setup failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
6255
+ }
6256
+ Object.assign(objects, result?.objects ?? {});
6257
+ if (!("root" in objects)) objects.root = root;
6258
+ this._objects = objects;
6259
+ this._ctx = ctx;
6260
+ this._stopSelfUpdating(root);
6261
+ this.buildFilters();
6262
+ }
6263
+ /** Reuse (core/reuse.ts): the key this layer is matched by, while it can still lend its scene. */
6264
+ reuseKey() {
6265
+ return this._lendable() ? this._key : null;
6266
+ }
6267
+ _lendable() {
6268
+ return !!this._box && !!this._ctx && !this._donated && !this._borrowed;
6269
+ }
6270
+ /** The new tree is on stage: the old layer's scene moves into this layer's box, for good. */
6271
+ commitReuse() {
6272
+ const d = this._borrowed, box = this._box;
6273
+ if (!d || !box || !this._ctx) return;
6274
+ this._setupValues.restore();
6275
+ box.addChild(this._ctx.root);
6276
+ d._donated = true;
6277
+ this._borrowed = null;
6278
+ }
6279
+ /**
6280
+ * Anything that would move on PixiJS's shared ticker instead of the video's time is turned off: an AnimatedSprite is posed by the layer from its time (so a sprite left
6281
+ * playing still plays, frame for frame the same in a seek and an export); anything else with `autoUpdate` is said once (drive it from update). A sprite showing a
6282
+ * `<video>` plays by the browser's clock: said once.
6283
+ */
6284
+ _stopSelfUpdating(root) {
6285
+ const stopped = [];
6286
+ const visit = (node) => {
6287
+ const n = node;
6288
+ if (isFlipbook(node)) {
6289
+ if (!this._flipbooks.includes(node)) this._flipbooks.push(node);
6290
+ if (node.autoUpdate) node.autoUpdate = false;
6291
+ } else if (n.autoUpdate === true) {
6292
+ n.autoUpdate = false;
6293
+ stopped.push(n.label || n.constructor?.name || "a node");
6294
+ }
6295
+ const resource = n.texture?.source?.resource;
6296
+ if (typeof HTMLVideoElement !== "undefined" && resource instanceof HTMLVideoElement) {
6297
+ this._say("video", `a sprite shows a <video> texture, which plays by the browser's clock, not the video's time: use a video layer (type: 'video') for footage`);
6298
+ }
6299
+ for (const c of node.children ?? []) visit(c);
6300
+ };
6301
+ visit(root);
6302
+ if (stopped.length) {
6303
+ this._say("autoUpdate", `turned off autoUpdate on ${stopped.join(", ")}: a video draws from the time, so drive them from update(t)`);
6304
+ }
6305
+ }
6306
+ /** An AnimatedSprite still playing after `update` is posed from the layer's time: frame floor(t × 60 × animationSpeed) (PixiJS counts ticks of 1/60 s), its loop and frame times kept. */
6307
+ _poseFlipbooks(t) {
6308
+ for (const f of this._flipbooks) {
6309
+ if (!f.playing || f.totalFrames <= 0) continue;
6310
+ const n = f.totalFrames;
6311
+ let frame;
6312
+ const durations = f._durations;
6313
+ if (durations && durations.length === n) {
6314
+ const total = durations.reduce((a, b) => a + b, 0);
6315
+ let ms = t * 1e3 * Math.abs(f.animationSpeed);
6316
+ ms = f.loop && total > 0 ? ms % total : Math.min(ms, total);
6317
+ frame = 0;
6318
+ for (let acc = durations[0]; frame < n - 1 && acc <= ms; acc += durations[++frame]) {
6319
+ }
6320
+ } else {
6321
+ const ticks = Math.floor(t * 60 * Math.abs(f.animationSpeed) + 1e-9);
6322
+ frame = f.loop ? ticks % n : Math.min(ticks, n - 1);
6323
+ }
6324
+ if (f.animationSpeed < 0) frame = n - 1 - frame;
6325
+ f.gotoAndStop(frame);
6326
+ f.play();
6327
+ }
6328
+ }
6329
+ /** Per-frame hook, duck-typed by the movie (as the video, canvas and 3D layers are). */
6330
+ async awaitFrameAt(local) {
6331
+ if (!this._ctx || this._borrowed) return;
6332
+ this._frame(Math.max(0, Math.min(local, this.duration ?? local)));
6333
+ }
6334
+ _frame(t) {
6335
+ const update = this._spec.update;
6336
+ if (update) {
6337
+ try {
6338
+ update(t, this._ctx);
6339
+ } catch (err) {
6340
+ this._say("update", `update threw (reported once): ${err instanceof Error ? err.message : String(err)}`);
6341
+ }
6342
+ }
6343
+ this._poseFlipbooks(t);
6344
+ }
6345
+ /**
6346
+ * `movie.pick`: the top object of the scene under a canvas point, by PixiJS's own `containsPoint` (a Graphics by its shape, a Sprite or Text by its box) or its `hitArea`.
6347
+ * `eventMode: 'none'` and `interactiveChildren: false` are honoured; hidden, unrenderable and clear nodes are not hit. null: nothing of the scene is there (the point falls through).
6348
+ */
6349
+ pick2d(global) {
6350
+ const root = this._ctx?.root;
6351
+ if (!root || this._borrowed) return null;
6352
+ const hitIn = (node2) => {
6353
+ if (!node2.visible || !node2.renderable || node2.alpha <= 0 || node2.measurable === false) return null;
6354
+ const mode = node2.eventMode;
6355
+ if (mode === "none") return null;
6356
+ const local = node2.toLocal(global);
6357
+ const area = node2 === root ? null : node2.hitArea;
6358
+ if (area && !area.contains(local.x, local.y)) return null;
6359
+ if (node2.interactiveChildren !== false) {
6360
+ for (let i = node2.children.length - 1; i >= 0; i--) {
6361
+ const h = hitIn(node2.children[i]);
6362
+ if (h) return h;
6363
+ }
6364
+ }
6365
+ if (node2 === root) return null;
6366
+ if (area) return node2;
6367
+ const contains = node2.containsPoint;
6368
+ return typeof contains === "function" && contains.call(node2, new pixi_js.Point(local.x, local.y)) ? node2 : null;
6369
+ };
6370
+ const node = hitIn(root);
6371
+ if (!node) return null;
6372
+ let name = "";
6373
+ for (let n = node; n && n !== root; n = n.parent) {
6374
+ if (n.label && !DEFAULT_LABELS.has(n.label) && n.label !== n.constructor?.name) {
6375
+ name = n.label;
6376
+ break;
6377
+ }
6378
+ }
6379
+ const p = root.toLocal(global);
6380
+ return { object: name, node, point: [p.x, p.y] };
6381
+ }
6382
+ /** `hit.scene2d.grab()`: for a canvas point, where it is in the grabbed node's parent's pixels and how far that is from where it was grabbed (`node.x += delta[0]`). */
6383
+ dragFrom(node, global) {
6384
+ const space = node.parent ?? node;
6385
+ const from = space.toLocal(global);
6386
+ return (x, y) => {
6387
+ const p = space.toLocal({ x, y });
6388
+ return { point: [p.x, p.y], delta: [p.x - from.x, p.y - from.y] };
6389
+ };
6390
+ }
6391
+ /**
6392
+ * The determinism check (`check`, `movie.review()`): the scene set by `update` and drawn at a few moments in two orders, with one draw thrown away first, as the canvas and 3D
6393
+ * layers are. It draws the root alone into a texture of the box's size with PixiJS's renderer; the next real frame sets the scene again.
6394
+ */
6395
+ checkDeterminism(times) {
6396
+ const none = { differs: [], drawMs: 0, threw: [] };
6397
+ const ctx = this._ctx;
6398
+ const renderer = this.root.pixiRenderer;
6399
+ if (!ctx || !renderer || this._borrowed) return none;
6400
+ const root = ctx.root;
6401
+ const w = Math.max(1, Math.ceil(ctx.width)), h = Math.max(1, Math.ceil(ctx.height));
6402
+ const rt = pixi_js.RenderTexture.create({ width: w, height: h });
6403
+ const wasGroup = root.isRenderGroup;
6404
+ const keep = w * h * 4 * times.length <= 96e6;
6405
+ const hash = (d) => {
6406
+ let x = 2166136261;
6407
+ for (let i = 0; i < d.length; i++) {
6408
+ x ^= d[i];
6409
+ x = Math.imul(x, 16777619);
6410
+ }
6411
+ return x >>> 0;
6412
+ };
6413
+ const ms = [];
6414
+ const threw = /* @__PURE__ */ new Set();
6415
+ const update = this._spec.update;
6416
+ const once = (t, timed) => {
6417
+ const from = performance.now();
6418
+ let pixels = new Uint8Array(0);
6419
+ try {
6420
+ update?.(t, ctx);
6421
+ this._poseFlipbooks(t);
6422
+ renderer.render({ container: root, target: rt, clear: true, transform: new pixi_js.Matrix() });
6423
+ pixels = renderer.extract.pixels(rt).pixels;
6424
+ } catch {
6425
+ threw.add(t);
6426
+ }
6427
+ if (timed) ms.push(performance.now() - from);
6428
+ return pixels;
6429
+ };
6430
+ try {
6431
+ for (const t of times) once(t, false);
6432
+ const first = times.map((t) => {
6433
+ const d = once(t, true);
6434
+ return keep ? d.slice() : hash(d);
6435
+ });
6436
+ const second = [...times].reverse().map((t) => once(t, false)).reverse();
6437
+ const differs = [];
6438
+ times.forEach((t, i) => {
6439
+ const a = first[i], b = second[i];
6440
+ if (typeof a === "number") {
6441
+ if (a !== hash(b)) differs.push({ t, pixels: -1, maxDiff: -1 });
6442
+ return;
6443
+ }
6444
+ let pixels = 0, maxDiff = 0;
6445
+ for (let k = 0; k < a.length; k++) {
6446
+ const d = Math.abs(a[k] - b[k]);
6447
+ if (d) {
6448
+ pixels++;
6449
+ if (d > maxDiff) maxDiff = d;
6450
+ }
6451
+ }
6452
+ if (pixels) differs.push({ t, pixels, maxDiff });
6453
+ });
6454
+ ms.sort((x, y) => x - y);
6455
+ return { differs: differs.filter((d) => !threw.has(d.t)), drawMs: ms.length ? ms[Math.floor(ms.length / 2)] : 0, threw: times.filter((t) => threw.has(t)) };
6456
+ } finally {
6457
+ rt.destroy(true);
6458
+ if (!wasGroup && root.isRenderGroup) root.disableRenderGroup();
6459
+ }
6460
+ }
6461
+ _resolvePath(path) {
6462
+ const segs = path.split(".");
6463
+ if (segs.length < 2) {
6464
+ this._warnPath(path, "needs at least <object>.<prop>");
6465
+ return null;
6466
+ }
6467
+ let obj = this._objects[segs[0]];
6468
+ if (obj == null) {
6469
+ this._warnPath(path, `unknown object "${segs[0]}" (known: ${Object.keys(this._objects).join(", ")}): expose it in setup's { objects }`);
6470
+ return null;
6471
+ }
6472
+ for (let i = 1; i < segs.length - 1; i++) {
6473
+ obj = obj[segs[i]];
6474
+ if (obj == null) {
6475
+ this._warnPath(path, `"${segs[i]}" is undefined along the path`);
6476
+ return null;
6477
+ }
6478
+ }
6479
+ const prop = segs[segs.length - 1];
6480
+ if (typeof obj !== "object" || !(prop in obj)) {
6481
+ this._warnPath(path, `no property "${prop}"`);
6482
+ return null;
6483
+ }
6484
+ return this._borrowed ? this._setupValues.view(obj, prop, () => this._borrowed !== null) : (this._setupValues.note(obj, prop), { target: obj, prop });
6485
+ }
6486
+ _warnPath(path, why) {
6487
+ this._say(`path:${path}`, `keyframe path scene2d.${path}: ${why}; skipped`);
6488
+ }
6489
+ destroy() {
6490
+ const kept = this._donated || this._borrowed !== null;
6491
+ if (!kept && this._ctx && this._spec.dispose) {
6492
+ try {
6493
+ this._spec.dispose(this._ctx);
6494
+ } catch (err) {
6495
+ console.warn(`${this._who()}: dispose() threw \u2014`, err);
6496
+ }
6497
+ }
6498
+ const box = this._box;
6499
+ this._box = null;
6500
+ if (this.target === box) this.target = null;
6501
+ try {
6502
+ box?.destroy({ children: true });
6503
+ } catch (err) {
6504
+ console.warn(`${this._who()}: destroying the scene threw \u2014`, err);
6505
+ }
6506
+ this._ctx = null;
6507
+ this._objects = {};
6508
+ this._flipbooks = [];
6509
+ this._borrowed = null;
6510
+ super.destroy();
6511
+ }
6512
+ };
6513
+ function textureOf(name) {
6514
+ if (pixi_js.Assets.cache.has(name)) {
6515
+ const t = pixi_js.Assets.get(name);
6516
+ if (t && typeof t.source === "object") return t;
6517
+ throw new Error(`asset "${name}" is not a picture (ctx.texture gives the texture of an image asset)`);
6518
+ }
6519
+ const known = [...pixi_js.Assets.cache._cache?.keys() ?? []].filter((k) => !/[/:.]/.test(k) && !k.startsWith("pixi-effects-"));
6520
+ throw new Error(`no asset named "${name}"${known.length ? ` (assets: ${known.join(", ")})` : ""}: list it in movie.init({ assets: [{ name, src }] })`);
6521
+ }
6522
+ function dim(v, scope) {
6523
+ if (v === void 0) return void 0;
6524
+ return typeof v === "number" ? v : evaluateExpr(v, scope);
6525
+ }
6526
+
6071
6527
  // src/core/Composition.ts
6072
6528
  var _CompositionSequence = null;
6073
6529
  async function getCompositionSequence() {
6074
6530
  if (!_CompositionSequence) {
6075
- _CompositionSequence = (await import('./Composition-TJ5D7Z63.cjs')).CompositionSequence;
6531
+ _CompositionSequence = (await import('./Composition-47U5U637.cjs')).CompositionSequence;
6076
6532
  }
6077
6533
  return _CompositionSequence;
6078
6534
  }
6079
6535
  var _SpansSequence = null;
6080
6536
  async function getSpansSequence() {
6081
- if (!_SpansSequence) _SpansSequence = (await import('./Spans-5ENZ3XGS.cjs')).SpansSequence;
6537
+ if (!_SpansSequence) _SpansSequence = (await import('./Spans-R426NVY3.cjs')).SpansSequence;
6082
6538
  return _SpansSequence;
6083
6539
  }
6084
6540
  var staticTypes = {
@@ -6091,12 +6547,17 @@ var staticTypes = {
6091
6547
  light: LightSequence,
6092
6548
  shader: ShaderSequence,
6093
6549
  canvas: CanvasSequence,
6550
+ scene2d: Scene2DSequence,
6094
6551
  null: NullSequence
6095
6552
  };
6096
6553
  var registry2 = {};
6097
6554
  function registerSequenceType(type, ctor) {
6098
6555
  registry2[type] = ctor;
6099
6556
  }
6557
+ var OPTIONAL_ENTRIES = {
6558
+ scene3d: { from: "pixi-effects/3d", call: "register3D" },
6559
+ three: { from: "pixi-effects/three", call: "registerThree" }
6560
+ };
6100
6561
  async function buildSequenceTree(specs, parent, root, out = []) {
6101
6562
  for (let spec of specs) {
6102
6563
  let Cls = staticTypes[spec.type] ?? registry2[spec.type];
@@ -6108,7 +6569,9 @@ async function buildSequenceTree(specs, parent, root, out = []) {
6108
6569
  Cls = await getCompositionSequence();
6109
6570
  }
6110
6571
  if (!Cls) {
6111
- console.warn(`pixi-effects: unknown sequence type "${spec.type}"`);
6572
+ const type = spec.type;
6573
+ const entry = OPTIONAL_ENTRIES[type];
6574
+ console.warn(`pixi-effects: unknown sequence type "${type}"${entry ? `: import { ${entry.call} } from '${entry.from}' and call ${entry.call}() before movie.init` : ""}`);
6112
6575
  await root.onLayerBuilt?.();
6113
6576
  continue;
6114
6577
  }
@@ -6137,9 +6600,11 @@ exports.MAX_CASTERS = MAX_CASTERS;
6137
6600
  exports.MAX_LIGHTS = MAX_LIGHTS;
6138
6601
  exports.MIN_BLUR = MIN_BLUR;
6139
6602
  exports.NEAR = NEAR;
6603
+ exports.NOT_PURE = NOT_PURE;
6140
6604
  exports.NullSequence = NullSequence;
6141
6605
  exports.SHADOW_TAPS = SHADOW_TAPS;
6142
6606
  exports.Sequence = Sequence;
6607
+ exports.SetupValues = SetupValues;
6143
6608
  exports.TextSequence = TextSequence;
6144
6609
  exports.bindClock = bindClock;
6145
6610
  exports.bindCounterKeyframes = bindCounterKeyframes;
@@ -6178,5 +6643,5 @@ exports.spansMeta = spansMeta;
6178
6643
  exports.springDuration = springDuration;
6179
6644
  exports.timeRemapOf = timeRemapOf;
6180
6645
  exports.trimPolylines = trimPolylines;
6181
- //# sourceMappingURL=chunk-Z3DM4ETD.cjs.map
6182
- //# sourceMappingURL=chunk-Z3DM4ETD.cjs.map
6646
+ //# sourceMappingURL=chunk-VVUSZVP7.cjs.map
6647
+ //# sourceMappingURL=chunk-VVUSZVP7.cjs.map