pixi-effects 0.36.0 → 0.37.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 (76) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +5 -5
  3. package/ai/chat-template.html +3 -3
  4. package/ai/tools/check.mjs +12 -2
  5. package/ai/tools/lookup.mjs +2 -1
  6. package/dist/{Base-CmiFiwQM.d.cts → Base-BlA6SeqJ.d.cts} +1 -1
  7. package/dist/{Base-CdF7AJop.d.ts → Base-YqM0Ljvp.d.ts} +1 -1
  8. package/dist/Composition-5KZETM4J.js +7 -0
  9. package/dist/{Composition-BMRCE5FH.js.map → Composition-5KZETM4J.js.map} +1 -1
  10. package/dist/Composition-MHDI7UNZ.cjs +16 -0
  11. package/dist/{Composition-XRLYR6GL.cjs.map → Composition-MHDI7UNZ.cjs.map} +1 -1
  12. package/dist/Controller.d.cts +2 -2
  13. package/dist/Controller.d.ts +2 -2
  14. package/dist/{Movie-D5WFfZdZ.d.ts → Movie-CJN_gvLB.d.cts} +21 -2
  15. package/dist/{Movie-Bh1HPdKw.d.cts → Movie-CfHaGmUP.d.ts} +21 -2
  16. package/dist/{Spans-MWP2FX3T.js → Spans-FSSO2HGX.js} +6 -6
  17. package/dist/{Spans-MWP2FX3T.js.map → Spans-FSSO2HGX.js.map} +1 -1
  18. package/dist/{Spans-4IRBSOLI.cjs → Spans-WVJH77BW.cjs} +11 -11
  19. package/dist/{Spans-4IRBSOLI.cjs.map → Spans-WVJH77BW.cjs.map} +1 -1
  20. package/dist/{blendModes-KU7XLV7U.cjs → blendModes-FD3THLNC.cjs} +5 -5
  21. package/dist/{blendModes-KU7XLV7U.cjs.map → blendModes-FD3THLNC.cjs.map} +1 -1
  22. package/dist/{blendModes-OOI3T6BE.js → blendModes-FMYO6SQN.js} +4 -4
  23. package/dist/{blendModes-OOI3T6BE.js.map → blendModes-FMYO6SQN.js.map} +1 -1
  24. package/dist/{chunk-2JFFKHXO.js → chunk-32MMNDDN.js} +4 -3
  25. package/dist/chunk-32MMNDDN.js.map +1 -0
  26. package/dist/{chunk-42ML5AKN.cjs → chunk-3SAS3ZE5.cjs} +4 -3
  27. package/dist/chunk-3SAS3ZE5.cjs.map +1 -0
  28. package/dist/{chunk-CC7SUR7Q.cjs → chunk-E26M4NTL.cjs} +122 -41
  29. package/dist/chunk-E26M4NTL.cjs.map +1 -0
  30. package/dist/{chunk-AZ6AINSW.js → chunk-IPQNT65V.js} +6 -6
  31. package/dist/chunk-IPQNT65V.js.map +1 -0
  32. package/dist/{chunk-NEUPEENI.cjs → chunk-JN7JHNZR.cjs} +5 -5
  33. package/dist/{chunk-NEUPEENI.cjs.map → chunk-JN7JHNZR.cjs.map} +1 -1
  34. package/dist/{chunk-VF56PRAA.js → chunk-KNDEKWQO.js} +89 -9
  35. package/dist/chunk-KNDEKWQO.js.map +1 -0
  36. package/dist/{chunk-Y5UWFH6Y.cjs → chunk-MJMOPWMK.cjs} +92 -92
  37. package/dist/chunk-MJMOPWMK.cjs.map +1 -0
  38. package/dist/{chunk-KJSEQVBV.cjs → chunk-QHIOOK5S.cjs} +333 -26
  39. package/dist/chunk-QHIOOK5S.cjs.map +1 -0
  40. package/dist/{chunk-G3DX65HO.js → chunk-SBR75G73.js} +311 -6
  41. package/dist/chunk-SBR75G73.js.map +1 -0
  42. package/dist/{chunk-WIIU42FH.js → chunk-VNP7QCJE.js} +4 -4
  43. package/dist/{chunk-WIIU42FH.js.map → chunk-VNP7QCJE.js.map} +1 -1
  44. package/dist/index.cjs +41 -33
  45. package/dist/index.d.cts +32 -6
  46. package/dist/index.d.ts +32 -6
  47. package/dist/index.js +5 -5
  48. package/dist/loader.css +1 -1
  49. package/dist/present.cjs +5 -5
  50. package/dist/present.d.cts +2 -2
  51. package/dist/present.d.ts +2 -2
  52. package/dist/present.js +5 -5
  53. package/dist/three.cjs +6 -6
  54. package/dist/three.d.cts +2 -2
  55. package/dist/three.d.ts +2 -2
  56. package/dist/three.js +2 -2
  57. package/dist/{types-B6zDTU2V.d.ts → types-DvnXXm33.d.cts} +53 -2
  58. package/dist/{types-B6zDTU2V.d.cts → types-DvnXXm33.d.ts} +53 -2
  59. package/docs/dsl.md +35 -0
  60. package/llms-full.txt +221 -5
  61. package/package.json +1 -1
  62. package/skills/pixi-effects/SKILL.md +3 -2
  63. package/skills/pixi-effects/reference/cheatsheet.md +2 -0
  64. package/skills/pixi-effects/reference/pitfalls.md +4 -0
  65. package/skills/pixi-effects/reference/recipes.md +177 -3
  66. package/skills/pixi-effects/template.html +6 -6
  67. package/dist/Composition-BMRCE5FH.js +0 -7
  68. package/dist/Composition-XRLYR6GL.cjs +0 -16
  69. package/dist/chunk-2JFFKHXO.js.map +0 -1
  70. package/dist/chunk-42ML5AKN.cjs.map +0 -1
  71. package/dist/chunk-AZ6AINSW.js.map +0 -1
  72. package/dist/chunk-CC7SUR7Q.cjs.map +0 -1
  73. package/dist/chunk-G3DX65HO.js.map +0 -1
  74. package/dist/chunk-KJSEQVBV.cjs.map +0 -1
  75. package/dist/chunk-VF56PRAA.js.map +0 -1
  76. package/dist/chunk-Y5UWFH6Y.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunk42ML5AKN_cjs = require('./chunk-42ML5AKN.cjs');
3
+ var chunk3SAS3ZE5_cjs = require('./chunk-3SAS3ZE5.cjs');
4
4
  var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
5
5
  var PIXI = require('pixi.js');
6
6
 
@@ -992,6 +992,17 @@ function noise(x, seed = 0) {
992
992
  const u = f * f * f * (f * (f * 6 - 15) + 10);
993
993
  return a + (b - a) * u;
994
994
  }
995
+ function noise2(x, y, seed = 0) {
996
+ if (!Number.isFinite(x) || !Number.isFinite(y)) return 0;
997
+ const i = Math.floor(x), j = Math.floor(y);
998
+ const fx = x - i, fy = y - j;
999
+ const s = fold(seed) * 668265261;
1000
+ const corner = (a, b) => mix2(Math.imul((a | 0) + s, 2654435761) ^ Math.imul((b | 0) + 2135587861, 2246822507)) / 2147483648 - 1;
1001
+ const ux = fx * fx * fx * (fx * (fx * 6 - 15) + 10), uy = fy * fy * fy * (fy * (fy * 6 - 15) + 10);
1002
+ const top = corner(i, j) + (corner(i + 1, j) - corner(i, j)) * ux;
1003
+ const bottom = corner(i, j + 1) + (corner(i + 1, j + 1) - corner(i, j + 1)) * ux;
1004
+ return top + (bottom - top) * uy;
1005
+ }
995
1006
 
996
1007
  // src/expr/Parser.ts
997
1008
  var FUNCS = {
@@ -2963,7 +2974,7 @@ var TextSequence = class extends Sequence {
2963
2974
  if (this.spec.resolution !== void 0) {
2964
2975
  const r = this.spec.resolution;
2965
2976
  if (typeof r === "number" && r >= 1 && r <= 8) text.resolution = r;
2966
- else console.warn(`pixi-effects: ${chunk42ML5AKN_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`);
2977
+ else console.warn(`pixi-effects: ${chunk3SAS3ZE5_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`);
2967
2978
  }
2968
2979
  this.target = text;
2969
2980
  this.intrinsicWidth = text.width;
@@ -2979,7 +2990,7 @@ var TextSequence = class extends Sequence {
2979
2990
  { skipKeys: STYLE_OPAQUE_KEYS }
2980
2991
  );
2981
2992
  const unset = Object.keys(resolved).filter((k) => resolved[k] === void 0);
2982
- if (unset.length) console.warn(`pixi-effects: ${chunk42ML5AKN_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`);
2993
+ if (unset.length) console.warn(`pixi-effects: ${chunk3SAS3ZE5_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`);
2983
2994
  const outline = resolved.stroke;
2984
2995
  if (outline && typeof outline === "object" && !("join" in outline) && !("lineJoin" in outline)) resolved.stroke = { ...outline, join: "round" };
2985
2996
  for (const k of Object.keys(resolved)) {
@@ -2991,7 +3002,7 @@ var TextSequence = class extends Sequence {
2991
3002
  }
2992
3003
  const startFill = initialProps.fill;
2993
3004
  if (typeof startFill === "string" || typeof startFill === "number") text.style.fill = startFill;
2994
- validateGradientKeyframes(this.spec, chunk42ML5AKN_cjs.describeLayer(this.spec), void 0, "text");
3005
+ validateGradientKeyframes(this.spec, chunk3SAS3ZE5_cjs.describeLayer(this.spec), void 0, "text");
2995
3006
  const gradientSpec = this.spec.fillGradient ?? initialProps.fillGradient;
2996
3007
  if (gradientSpec) {
2997
3008
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -3027,7 +3038,7 @@ var TextSequence = class extends Sequence {
3027
3038
  bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
3028
3039
  this._template = t;
3029
3040
  refresh();
3030
- }, chunk42ML5AKN_cjs.describeLayer(this.spec));
3041
+ }, chunk3SAS3ZE5_cjs.describeLayer(this.spec));
3031
3042
  }
3032
3043
  };
3033
3044
  function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
@@ -3477,7 +3488,7 @@ var CameraSequence = class extends Sequence {
3477
3488
  carrier.fogColor = "#000000";
3478
3489
  carrier.fogAmount = 1;
3479
3490
  this.target = carrier;
3480
- const keys = chunk42ML5AKN_cjs.collectPropKeys(this.spec);
3491
+ const keys = chunk3SAS3ZE5_cjs.collectPropKeys(this.spec);
3481
3492
  this.autoZ = !keys.has("z");
3482
3493
  this.dof = keys.has("focus") || keys.has("aperture");
3483
3494
  this.fog = keys.has("fogNear") || keys.has("fogFar") || keys.has("fogColor") || keys.has("fogAmount");
@@ -3798,7 +3809,7 @@ function resolveSpansStyle(style, scope, who, warn = defaultWarn) {
3798
3809
  var TEXT_ONLY = ["type", "spans", "text", "style", "format", "colorSpace", "fillGradient", "initial", "keyframes", "resolution"];
3799
3810
  var NOT_FOR_A_GROUP = ["fill", "text", "value", "fillGradient"];
3800
3811
  function expandSpans(spec, warn = defaultWarn, scope) {
3801
- const who = chunk42ML5AKN_cjs.describeLayer(spec);
3812
+ const who = chunk3SAS3ZE5_cjs.describeLayer(spec);
3802
3813
  const s = spec;
3803
3814
  if (s.text !== void 0) warn(`pixi-effects: ${who}: "text" is ignored when the layer has spans: write the text as spans`);
3804
3815
  const style = resolveSpansStyle(s.style ?? {}, scope, who, warn);
@@ -3857,7 +3868,7 @@ var ImageSequence = class extends Sequence {
3857
3868
  const source = texture.source;
3858
3869
  if (source && !ORIGINAL_SCALE_MODE.has(source)) ORIGINAL_SCALE_MODE.set(source, source.scaleMode);
3859
3870
  const mode = this.spec.scaleMode;
3860
- if (mode !== void 0 && mode !== "nearest" && mode !== "linear") console.warn(`pixi-effects: ${chunk42ML5AKN_cjs.describeLayer(this.spec)}: scaleMode "${String(mode)}" is not "nearest" or "linear": ignored`);
3871
+ if (mode !== void 0 && mode !== "nearest" && mode !== "linear") console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: scaleMode "${String(mode)}" is not "nearest" or "linear": ignored`);
3861
3872
  if (source) source.scaleMode = mode === "nearest" || mode === "linear" ? mode : ORIGINAL_SCALE_MODE.get(source);
3862
3873
  const sprite = new PIXI.Sprite({ texture, label: this.spec.name });
3863
3874
  sprite.cullable = true;
@@ -3966,12 +3977,12 @@ var AudioSequence = class extends Sequence {
3966
3977
  const playable = this._remap && this._remap.timeKfs.length > 0 ? Infinity : (data.duration ?? Infinity) / constant;
3967
3978
  if (!spec.loop && Number.isFinite(playable) && this.duration > playable + 0.05) {
3968
3979
  console.warn(
3969
- `pixi-effects: ${chunk42ML5AKN_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.`
3980
+ `pixi-effects: ${chunk3SAS3ZE5_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.`
3970
3981
  );
3971
3982
  }
3972
3983
  }
3973
3984
  async _buildSfx(spec) {
3974
- const who = chunk42ML5AKN_cjs.describeLayer(spec);
3985
+ const who = chunk3SAS3ZE5_cjs.describeLayer(spec);
3975
3986
  const raw = spec;
3976
3987
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
3977
3988
  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)`);
@@ -3990,7 +4001,7 @@ var AudioSequence = class extends Sequence {
3990
4001
  });
3991
4002
  }
3992
4003
  async _buildMusic(spec) {
3993
- const who = chunk42ML5AKN_cjs.describeLayer(spec);
4004
+ const who = chunk3SAS3ZE5_cjs.describeLayer(spec);
3994
4005
  const raw = spec;
3995
4006
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
3996
4007
  if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
@@ -4025,7 +4036,7 @@ var AudioSequence = class extends Sequence {
4025
4036
  out.push({
4026
4037
  ...sourceMap ? { sourceMap } : {},
4027
4038
  ...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
4028
- layer: chunk42ML5AKN_cjs.describeLayer(this.spec),
4039
+ layer: chunk3SAS3ZE5_cjs.describeLayer(this.spec),
4029
4040
  source: this._source,
4030
4041
  ...this._music ? { music: this._music } : {},
4031
4042
  loop: !this._synth && !!this.spec.loop,
@@ -4567,7 +4578,7 @@ var VideoSequence = class extends Sequence {
4567
4578
  out.push({
4568
4579
  ...sourceMap ? { sourceMap } : {},
4569
4580
  buffer: this._audioBuffer,
4570
- layer: chunk42ML5AKN_cjs.describeLayer(this.spec),
4581
+ layer: chunk3SAS3ZE5_cjs.describeLayer(this.spec),
4571
4582
  source: `video "${this.spec.asset}"`,
4572
4583
  loop: !!this.spec.loop,
4573
4584
  start: baseTime + this.at,
@@ -4855,20 +4866,20 @@ var ShapeSequence = class extends Sequence {
4855
4866
  for (const k of geomKeys) this._liveKeys.add(k);
4856
4867
  seedGeometry(this._state, this.spec, scope);
4857
4868
  seedStyle(this._state, this.spec.initial ?? {}, scope);
4858
- seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunk42ML5AKN_cjs.describeLayer(this.spec));
4869
+ seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunk3SAS3ZE5_cjs.describeLayer(this.spec));
4859
4870
  if (this.spec.shape === "arc") {
4860
4871
  this._state.startAngle ??= 0;
4861
4872
  this._state.endAngle ??= 360;
4862
4873
  const top = this.spec, ini = this.spec.initial ?? {};
4863
4874
  if ("trimStart" in top || "trimEnd" in top || "trimStart" in ini || "trimEnd" in ini) {
4864
- console.warn(`pixi-effects: ${chunk42ML5AKN_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
4875
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
4865
4876
  }
4866
4877
  } else {
4867
4878
  this._state.trimStart ??= 0;
4868
4879
  this._state.trimEnd ??= 1;
4869
4880
  }
4870
4881
  const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
4871
- validateGradientKeyframes(this.spec, chunk42ML5AKN_cjs.describeLayer(this.spec));
4882
+ validateGradientKeyframes(this.spec, chunk3SAS3ZE5_cjs.describeLayer(this.spec));
4872
4883
  if (gradientSpec) {
4873
4884
  if (hasGradientKeys(this.spec.keyframes)) {
4874
4885
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -4912,9 +4923,9 @@ var ShapeSequence = class extends Sequence {
4912
4923
  }
4913
4924
  /** The prepared morph between `d` and `morphTo`, or null (and a warning when the spec asked for one that cannot work). */
4914
4925
  _setupMorph() {
4915
- const who = chunk42ML5AKN_cjs.describeLayer(this.spec);
4926
+ const who = chunk3SAS3ZE5_cjs.describeLayer(this.spec);
4916
4927
  const top = this.spec;
4917
- const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunk42ML5AKN_cjs.collectPropKeys(this.spec).has("morph"));
4928
+ const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunk3SAS3ZE5_cjs.collectPropKeys(this.spec).has("morph"));
4918
4929
  if (this.spec.shape !== "path") {
4919
4930
  if ("morphTo" in top) console.warn(`pixi-effects: ${who}: morphTo only works on a path shape (shape: 'path'); ignored`);
4920
4931
  return null;
@@ -5550,7 +5561,7 @@ var ShaderSequence = class extends Sequence {
5550
5561
  }
5551
5562
  async build() {
5552
5563
  const spec = this.shaderSpec;
5553
- const who = chunk42ML5AKN_cjs.describeLayer(spec);
5564
+ const who = chunk3SAS3ZE5_cjs.describeLayer(spec);
5554
5565
  for (const m of shaderProblems(spec)) console.warn(`pixi-effects: ${who}: ${m}`);
5555
5566
  if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
5556
5567
  const scope = buildScope(this, this.parent, this.root);
@@ -5594,7 +5605,7 @@ var ShaderSequence = class extends Sequence {
5594
5605
  const warn = (why) => {
5595
5606
  if (this.warnedPaths.has(path)) return;
5596
5607
  this.warnedPaths.add(path);
5597
- console.warn(`pixi-effects: ${chunk42ML5AKN_cjs.describeLayer(this.spec)}: keyframe path uniforms.${path} ${why}; skipped`);
5608
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: keyframe path uniforms.${path} ${why}; skipped`);
5598
5609
  };
5599
5610
  if (slot === void 0) {
5600
5611
  const guess = chunkTWZNOUM7_cjs.suggestName(name, Object.keys(this.carrier));
@@ -5629,7 +5640,7 @@ var ShaderSequence = class extends Sequence {
5629
5640
  this.failed = true;
5630
5641
  if (!this.warnedNoGl) {
5631
5642
  this.warnedNoGl = true;
5632
- console.warn(`pixi-effects: ${chunk42ML5AKN_cjs.describeLayer(this.spec)}: this browser has no WebGL2, so the shader cannot run; the layer is drawn as a checkerboard`);
5643
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: this browser has no WebGL2, so the shader cannot run; the layer is drawn as a checkerboard`);
5633
5644
  }
5634
5645
  }
5635
5646
  compile() {
@@ -5660,7 +5671,7 @@ var ShaderSequence = class extends Sequence {
5660
5671
  gl.deleteProgram(p);
5661
5672
  this.failed = true;
5662
5673
  this.prog = null;
5663
- console.warn(`pixi-effects: ${chunk42ML5AKN_cjs.describeLayer(this.spec)}: the fragment shader did not compile (the line numbers are the lines of your code):
5674
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: the fragment shader did not compile (the line numbers are the lines of your code):
5664
5675
  ${glslErrors(log).join("\n")}
5665
5676
  The layer is drawn as a checkerboard until it is fixed.`);
5666
5677
  return;
@@ -5739,18 +5750,311 @@ function resolveDim(v, scope) {
5739
5750
  if (typeof v === "number") return v;
5740
5751
  return evaluateExpr(v, scope);
5741
5752
  }
5753
+ var MAX_SIZE = 8192;
5754
+ var MIN_RESOLUTION = 0.25;
5755
+ var MAX_RESOLUTION = 4;
5756
+ var NOT_PURE = /\bMath\s*\.\s*random\s*\(|\bDate\s*\.\s*now\s*\(|\bperformance\s*\.\s*now\s*\(|\bnew\s+Date\s*\(/;
5757
+ function seeded(seed) {
5758
+ let a = seed >>> 0;
5759
+ return () => {
5760
+ a = a + 1831565813 >>> 0;
5761
+ let t = a;
5762
+ t = Math.imul(t ^ t >>> 15, t | 1);
5763
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
5764
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
5765
+ };
5766
+ }
5767
+ function offscreen(width, height) {
5768
+ const c = document.createElement("canvas");
5769
+ c.width = Math.max(1, Math.round(width));
5770
+ c.height = Math.max(1, Math.round(height));
5771
+ c.getContext("2d", { willReadFrequently: true });
5772
+ return c;
5773
+ }
5774
+ var CanvasSequence = class extends Sequence {
5775
+ canvas = null;
5776
+ w = 1;
5777
+ h = 1;
5778
+ res = 1;
5779
+ fps = 30;
5780
+ layerW = 1;
5781
+ layerH = 1;
5782
+ seed = 0;
5783
+ smoothing = true;
5784
+ drawFn = null;
5785
+ state;
5786
+ /** The current value of every param: what keyframes move (`params.amount`). */
5787
+ carrier = {};
5788
+ failed = false;
5789
+ warnedDraw = false;
5790
+ warnedPaths = /* @__PURE__ */ new Set();
5791
+ lastKey = "";
5792
+ lastLocal = 0;
5793
+ get canvasSpec() {
5794
+ return this.spec;
5795
+ }
5796
+ pathRouters() {
5797
+ return { params: (path) => this.resolveParam(path) };
5798
+ }
5799
+ async build() {
5800
+ const spec = this.canvasSpec;
5801
+ const who = chunk3SAS3ZE5_cjs.describeLayer(spec);
5802
+ if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
5803
+ const scope = buildScope(this, this.parent, this.root);
5804
+ this.layerW = this.size("width", spec.width, scope, this.parent?.width ?? this.root.width, who);
5805
+ this.layerH = this.size("height", spec.height, scope, this.parent?.height ?? this.root.height, who);
5806
+ const r = spec.resolution;
5807
+ if (r === void 0) this.res = 1;
5808
+ else if (typeof r === "number" && Number.isFinite(r) && r >= MIN_RESOLUTION && r <= MAX_RESOLUTION) this.res = r;
5809
+ else {
5810
+ this.res = typeof r === "number" && Number.isFinite(r) ? Math.min(MAX_RESOLUTION, Math.max(MIN_RESOLUTION, r)) : 1;
5811
+ console.warn(`pixi-effects: ${who}: resolution must be a number from ${MIN_RESOLUTION} to ${MAX_RESOLUTION} (canvas pixels per layer pixel), got ${JSON.stringify(r)}: ${this.res} is used`);
5812
+ }
5813
+ const longest = Math.max(this.layerW, this.layerH);
5814
+ if (longest * this.res > MAX_SIZE) {
5815
+ const fitted = MAX_SIZE / longest;
5816
+ console.warn(`pixi-effects: ${who}: ${this.layerW}\xD7${this.layerH} at resolution ${this.res} would be a canvas of ${Math.round(longest * this.res)} pixels, more than ${MAX_SIZE}: resolution ${Math.round(fitted * 1e3) / 1e3} is used (lower the size or the resolution)`);
5817
+ this.res = fitted;
5818
+ }
5819
+ this.w = Math.max(1, Math.round(this.layerW * this.res));
5820
+ this.h = Math.max(1, Math.round(this.layerH * this.res));
5821
+ this.fps = this.root.frameRate ?? 30;
5822
+ this.seed = typeof spec.seed === "number" && Number.isFinite(spec.seed) ? Math.floor(spec.seed) : 0;
5823
+ this.smoothing = spec.smoothing !== false;
5824
+ const params = spec.params;
5825
+ if (params !== void 0) {
5826
+ if (params === null || typeof params !== "object" || Array.isArray(params)) {
5827
+ console.warn(`pixi-effects: ${who}: params must be an object of numbers, got ${JSON.stringify(params)}: ignored`);
5828
+ } else {
5829
+ const bad = [];
5830
+ for (const [k, v] of Object.entries(params)) {
5831
+ if (typeof v === "number" && Number.isFinite(v)) this.carrier[k] = v;
5832
+ else bad.push(`"${k}"`);
5833
+ }
5834
+ if (bad.length) console.warn(`pixi-effects: ${who}: params ${bad.join(", ")} ${bad.length > 1 ? "are" : "is"} not a number, so ${bad.length > 1 ? "they are" : "it is"} ignored (params holds numbers that keyframes can animate as 'params.<name>')`);
5835
+ }
5836
+ }
5837
+ if (typeof spec.draw === "function") {
5838
+ this.drawFn = spec.draw;
5839
+ if (NOT_PURE.test(spec.draw.toString())) {
5840
+ console.warn(`pixi-effects: ${who}: draw 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. Use info.random() (seeded), or derive the value from t`);
5841
+ }
5842
+ } else {
5843
+ this.failed = true;
5844
+ console.warn(`pixi-effects: ${who}: a canvas layer needs draw: (ctx, t, info) => { \u2026 } (a function that draws the picture at time t); the layer is drawn as a checkerboard`);
5845
+ }
5846
+ this.canvas = document.createElement("canvas");
5847
+ this.canvas.width = this.w;
5848
+ this.canvas.height = this.h;
5849
+ const sprite = new PIXI.Sprite({ texture: PIXI.Texture.from(this.canvas), label: spec.name });
5850
+ if (!this.smoothing) sprite.texture.source.scaleMode = "nearest";
5851
+ sprite.width = this.layerW;
5852
+ sprite.height = this.layerH;
5853
+ this.target = sprite;
5854
+ this.intrinsicWidth = this.layerW;
5855
+ this.intrinsicHeight = this.layerH;
5856
+ this.buildFilters();
5857
+ if (typeof spec.setup === "function" && !this.failed) {
5858
+ try {
5859
+ this.state = await spec.setup(this.info(0));
5860
+ } catch (e) {
5861
+ this.failed = true;
5862
+ this.say(`setup failed: ${e instanceof Error ? e.message : String(e)}; the layer is drawn as a checkerboard`);
5863
+ }
5864
+ }
5865
+ this.drawAt(0);
5866
+ }
5867
+ async awaitFrameAt(local) {
5868
+ this.drawAt(Math.max(0, Math.min(local, this.duration ?? local)));
5869
+ }
5870
+ size(name, v, scope, fallback, who) {
5871
+ if (v === void 0) return fallback;
5872
+ const n = typeof v === "number" ? v : evaluateExpr(v, scope);
5873
+ if (!Number.isFinite(n) || n < 1) {
5874
+ console.warn(`pixi-effects: ${who}: ${name} must be a number of pixels of at least 1 (or an expression), got ${JSON.stringify(v)}: ${fallback} is used`);
5875
+ return fallback;
5876
+ }
5877
+ if (n > MAX_SIZE) {
5878
+ console.warn(`pixi-effects: ${who}: ${name} ${n} is more than ${MAX_SIZE}: ${MAX_SIZE} is used`);
5879
+ return MAX_SIZE;
5880
+ }
5881
+ return n;
5882
+ }
5883
+ say(why) {
5884
+ if (this.warnedDraw) return;
5885
+ this.warnedDraw = true;
5886
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_cjs.describeLayer(this.spec)}: ${why}`);
5887
+ }
5888
+ info(local) {
5889
+ const duration = this.duration ?? 0;
5890
+ const start = this.absoluteStart ?? this.at;
5891
+ return {
5892
+ frame: Math.round(local * this.fps),
5893
+ duration,
5894
+ progress: duration > 0 ? local / duration : 0,
5895
+ width: this.layerW,
5896
+ height: this.layerH,
5897
+ resolution: this.res,
5898
+ frameRate: this.fps,
5899
+ params: { ...this.carrier },
5900
+ state: this.state,
5901
+ random: seeded(this.seed),
5902
+ start,
5903
+ time: start + local,
5904
+ canvas: offscreen
5905
+ };
5906
+ }
5907
+ /** Resolve `params.amount` for the keyframe pipeline; a name nobody declared is said once and dropped. */
5908
+ resolveParam(path) {
5909
+ if (path in this.carrier && !path.includes(".")) return { target: this.carrier, prop: path };
5910
+ if (!this.warnedPaths.has(path)) {
5911
+ this.warnedPaths.add(path);
5912
+ const guess = chunkTWZNOUM7_cjs.suggestName(path.split(".")[0], Object.keys(this.carrier));
5913
+ console.warn(`pixi-effects: ${chunk3SAS3ZE5_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`);
5914
+ }
5915
+ return null;
5916
+ }
5917
+ drawAt(local) {
5918
+ const c = this.canvas;
5919
+ if (!c) return;
5920
+ const ctx = c.getContext("2d");
5921
+ if (!ctx) {
5922
+ this.say("this browser gave no 2D context for the layer's canvas, so nothing can be drawn");
5923
+ return;
5924
+ }
5925
+ const key = `${local}|${this.absoluteStart ?? this.at}|${JSON.stringify(this.carrier)}`;
5926
+ if (key === this.lastKey) return;
5927
+ this.lastKey = key;
5928
+ this.lastLocal = local;
5929
+ if (!this.paint(ctx, c, local)) this.lastKey = "";
5930
+ this.target?.texture.source.update();
5931
+ }
5932
+ /** Draws one frame of the layer into `ctx` (the layer's own canvas, or the scratch one of the determinism check). false: `draw` threw. */
5933
+ paint(ctx, c, local) {
5934
+ const hasReset = "reset" in ctx && typeof ctx.reset === "function";
5935
+ const fresh = () => {
5936
+ if (hasReset) ctx.reset();
5937
+ else {
5938
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
5939
+ ctx.clearRect(0, 0, c.width, c.height);
5940
+ }
5941
+ };
5942
+ fresh();
5943
+ if (this.failed || !this.drawFn) {
5944
+ this.checkerboard(ctx, c);
5945
+ return true;
5946
+ }
5947
+ if (!hasReset) ctx.save();
5948
+ let ok = true;
5949
+ try {
5950
+ ctx.scale(this.res, this.res);
5951
+ ctx.imageSmoothingEnabled = this.smoothing;
5952
+ this.drawFn(ctx, local, this.info(local));
5953
+ } catch (e) {
5954
+ if (!hasReset) {
5955
+ ctx.restore();
5956
+ ctx.save();
5957
+ }
5958
+ fresh();
5959
+ this.say(`draw threw at ${local.toFixed(2)} s: ${e instanceof Error ? e.message : String(e)}; that frame is drawn as a checkerboard (the other frames are tried again)`);
5960
+ this.checkerboard(ctx, c);
5961
+ ok = false;
5962
+ }
5963
+ if (!hasReset) ctx.restore();
5964
+ return ok;
5965
+ }
5966
+ /**
5967
+ * Draws each of `times` in two orders and returns the moments where the pictures differ (a draw that uses Math.random, the clock or state that outlives the call), with how much
5968
+ * (channel values that differ, the largest difference out of 255), and how long a draw took. One draw of every moment comes first and is thrown away: a browser can draw a canvas
5969
+ * made in `setup` differently the first time it is used as a source, and a cache a draw fills on its first call is fine. The layer's own canvas is not touched (everything is drawn in a scratch canvas).
5970
+ * A layer that failed, or a draw that throws, is reported in `threw`.
5971
+ */
5972
+ checkDeterminism(times) {
5973
+ const none = { differs: [], drawMs: 0, threw: [] };
5974
+ if (!this.canvas) return none;
5975
+ if (this.failed || !this.drawFn) return { ...none, threw: [...times] };
5976
+ const scratch = document.createElement("canvas");
5977
+ scratch.width = this.w;
5978
+ scratch.height = this.h;
5979
+ const ctx = scratch.getContext("2d", { willReadFrequently: true });
5980
+ if (!ctx) return none;
5981
+ const keep = this.w * this.h * 4 * times.length <= 96e6;
5982
+ const read2 = () => ctx.getImageData(0, 0, scratch.width, scratch.height).data;
5983
+ const hash = (d) => {
5984
+ let h = 2166136261;
5985
+ for (let i = 0; i < d.length; i++) {
5986
+ h ^= d[i];
5987
+ h = Math.imul(h, 16777619);
5988
+ }
5989
+ return h >>> 0;
5990
+ };
5991
+ const ms = [];
5992
+ const threw = /* @__PURE__ */ new Set();
5993
+ const once = (t, timed) => {
5994
+ const from = performance.now();
5995
+ if (!this.paint(ctx, scratch, t)) threw.add(t);
5996
+ if (timed) {
5997
+ ctx.getImageData(0, 0, 1, 1);
5998
+ ms.push(performance.now() - from);
5999
+ }
6000
+ return read2();
6001
+ };
6002
+ for (const t of times) once(t, false);
6003
+ const first = times.map((t) => {
6004
+ const d = once(t, true);
6005
+ return keep ? d.slice() : hash(d);
6006
+ });
6007
+ const second = [...times].reverse().map((t) => once(t, false)).reverse();
6008
+ scratch.width = scratch.height = 1;
6009
+ const differs = [];
6010
+ times.forEach((t, i) => {
6011
+ const a = first[i], b = second[i];
6012
+ if (typeof a === "number") {
6013
+ if (a !== hash(b)) differs.push({ t, pixels: -1, maxDiff: -1 });
6014
+ return;
6015
+ }
6016
+ let pixels = 0, maxDiff = 0;
6017
+ for (let k = 0; k < a.length; k++) {
6018
+ const d = Math.abs(a[k] - b[k]);
6019
+ if (d) {
6020
+ pixels++;
6021
+ if (d > maxDiff) maxDiff = d;
6022
+ }
6023
+ }
6024
+ if (pixels) differs.push({ t, pixels, maxDiff });
6025
+ });
6026
+ ms.sort((x, y) => x - y);
6027
+ 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)) };
6028
+ }
6029
+ checkerboard(ctx, c) {
6030
+ const s = 32;
6031
+ for (let y = 0; y < c.height; y += s) for (let x = 0; x < c.width; x += s) {
6032
+ ctx.fillStyle = x / s + y / s & 1 ? "#ff00ff" : "#220022";
6033
+ ctx.fillRect(x, y, s, s);
6034
+ }
6035
+ }
6036
+ destroy() {
6037
+ const texture = this.target?.texture;
6038
+ if (this.canvas) {
6039
+ this.canvas.width = this.canvas.height = 1;
6040
+ this.canvas = null;
6041
+ }
6042
+ super.destroy();
6043
+ texture?.destroy(true);
6044
+ }
6045
+ };
5742
6046
 
5743
6047
  // src/core/Composition.ts
5744
6048
  var _CompositionSequence = null;
5745
6049
  async function getCompositionSequence() {
5746
6050
  if (!_CompositionSequence) {
5747
- _CompositionSequence = (await import('./Composition-XRLYR6GL.cjs')).CompositionSequence;
6051
+ _CompositionSequence = (await import('./Composition-MHDI7UNZ.cjs')).CompositionSequence;
5748
6052
  }
5749
6053
  return _CompositionSequence;
5750
6054
  }
5751
6055
  var _SpansSequence = null;
5752
6056
  async function getSpansSequence() {
5753
- if (!_SpansSequence) _SpansSequence = (await import('./Spans-4IRBSOLI.cjs')).SpansSequence;
6057
+ if (!_SpansSequence) _SpansSequence = (await import('./Spans-WVJH77BW.cjs')).SpansSequence;
5754
6058
  return _SpansSequence;
5755
6059
  }
5756
6060
  var staticTypes = {
@@ -5762,6 +6066,7 @@ var staticTypes = {
5762
6066
  camera: CameraSequence,
5763
6067
  light: LightSequence,
5764
6068
  shader: ShaderSequence,
6069
+ canvas: CanvasSequence,
5765
6070
  null: NullSequence
5766
6071
  };
5767
6072
  var registry2 = {};
@@ -5834,6 +6139,7 @@ exports.layerToWorld = layerToWorld;
5834
6139
  exports.lengthen = lengthen;
5835
6140
  exports.lightLevel = lightLevel;
5836
6141
  exports.noise = noise;
6142
+ exports.noise2 = noise2;
5837
6143
  exports.packLights = packLights;
5838
6144
  exports.parseEase = parseEase;
5839
6145
  exports.parseSpring = parseSpring;
@@ -5848,5 +6154,6 @@ exports.resolveNumber = resolveNumber;
5848
6154
  exports.spansMeta = spansMeta;
5849
6155
  exports.springDuration = springDuration;
5850
6156
  exports.timeRemapOf = timeRemapOf;
5851
- //# sourceMappingURL=chunk-KJSEQVBV.cjs.map
5852
- //# sourceMappingURL=chunk-KJSEQVBV.cjs.map
6157
+ exports.trimPolylines = trimPolylines;
6158
+ //# sourceMappingURL=chunk-QHIOOK5S.cjs.map
6159
+ //# sourceMappingURL=chunk-QHIOOK5S.cjs.map