pixi-effects 0.47.1 → 0.47.2

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 (68) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +5 -5
  3. package/ai/chat-template.html +3 -3
  4. package/dist/Composition-X6MCEFRH.cjs +16 -0
  5. package/dist/{Composition-AZEATHJB.cjs.map → Composition-X6MCEFRH.cjs.map} +1 -1
  6. package/dist/Composition-ZYMQ7ZRC.js +7 -0
  7. package/dist/{Composition-ME3L3EFT.js.map → Composition-ZYMQ7ZRC.js.map} +1 -1
  8. package/dist/{Spans-LTKEUHDN.cjs → Spans-6HSLKR5Q.cjs} +11 -11
  9. package/dist/{Spans-LTKEUHDN.cjs.map → Spans-6HSLKR5Q.cjs.map} +1 -1
  10. package/dist/{Spans-YV7K4X5I.js → Spans-LCCZ4PW7.js} +6 -6
  11. package/dist/{Spans-YV7K4X5I.js.map → Spans-LCCZ4PW7.js.map} +1 -1
  12. package/dist/{blendModes-56NHK2MP.js → blendModes-EMANEHZS.js} +4 -4
  13. package/dist/{blendModes-56NHK2MP.js.map → blendModes-EMANEHZS.js.map} +1 -1
  14. package/dist/{blendModes-ONOPMMAB.cjs → blendModes-JUISKPCA.cjs} +5 -5
  15. package/dist/{blendModes-ONOPMMAB.cjs.map → blendModes-JUISKPCA.cjs.map} +1 -1
  16. package/dist/{chunk-NEMWRJQS.cjs → chunk-2YV7ISX6.cjs} +4 -4
  17. package/dist/chunk-2YV7ISX6.cjs.map +1 -0
  18. package/dist/{chunk-BFERTUXK.cjs → chunk-4RC4GXEM.cjs} +92 -92
  19. package/dist/{chunk-BFERTUXK.cjs.map → chunk-4RC4GXEM.cjs.map} +1 -1
  20. package/dist/{chunk-QMVK55LC.js → chunk-AOQRB6AU.js} +5 -5
  21. package/dist/{chunk-QMVK55LC.js.map → chunk-AOQRB6AU.js.map} +1 -1
  22. package/dist/{chunk-53DXJEO7.cjs → chunk-DQVUKP5G.cjs} +5 -5
  23. package/dist/{chunk-53DXJEO7.cjs.map → chunk-DQVUKP5G.cjs.map} +1 -1
  24. package/dist/{chunk-7IDEWQPH.js → chunk-G4PXCV2B.js} +12 -8
  25. package/dist/chunk-G4PXCV2B.js.map +1 -0
  26. package/dist/{chunk-OVTTCX2E.js → chunk-M5P7TXZ2.js} +135 -63
  27. package/dist/chunk-M5P7TXZ2.js.map +1 -0
  28. package/dist/{chunk-NVKHUAHU.js → chunk-P2P7C2KZ.js} +4 -4
  29. package/dist/chunk-P2P7C2KZ.js.map +1 -0
  30. package/dist/{chunk-UTDELFOU.js → chunk-R43646JP.js} +4 -4
  31. package/dist/{chunk-UTDELFOU.js.map → chunk-R43646JP.js.map} +1 -1
  32. package/dist/{chunk-4NOTVQ3I.cjs → chunk-TVVC4GVK.cjs} +29 -29
  33. package/dist/{chunk-4NOTVQ3I.cjs.map → chunk-TVVC4GVK.cjs.map} +1 -1
  34. package/dist/{chunk-YXIEPTFG.cjs → chunk-UXPTDNNA.cjs} +181 -109
  35. package/dist/chunk-UXPTDNNA.cjs.map +1 -0
  36. package/dist/{chunk-6MHJKCXO.js → chunk-YF4JC2AL.js} +5 -5
  37. package/dist/{chunk-6MHJKCXO.js.map → chunk-YF4JC2AL.js.map} +1 -1
  38. package/dist/{chunk-SMHTOWXG.cjs → chunk-ZAHCGFGC.cjs} +12 -8
  39. package/dist/chunk-ZAHCGFGC.cjs.map +1 -0
  40. package/dist/index.cjs +37 -37
  41. package/dist/index.d.cts +4 -4
  42. package/dist/index.d.ts +4 -4
  43. package/dist/index.js +6 -6
  44. package/dist/loader.css +1 -1
  45. package/dist/present.cjs +6 -6
  46. package/dist/present.js +6 -6
  47. package/dist/sound.cjs +2 -2
  48. package/dist/sound.js +1 -1
  49. package/dist/three.cjs +93 -26
  50. package/dist/three.cjs.map +1 -1
  51. package/dist/three.d.cts +19 -4
  52. package/dist/three.d.ts +19 -4
  53. package/dist/three.js +89 -22
  54. package/dist/three.js.map +1 -1
  55. package/docs/dsl.md +7 -2
  56. package/llms-full.txt +9 -4
  57. package/package.json +1 -1
  58. package/skills/pixi-effects/SKILL.md +1 -1
  59. package/skills/pixi-effects/reference/recipes.md +1 -1
  60. package/skills/pixi-effects/template.html +6 -6
  61. package/dist/Composition-AZEATHJB.cjs +0 -16
  62. package/dist/Composition-ME3L3EFT.js +0 -7
  63. package/dist/chunk-7IDEWQPH.js.map +0 -1
  64. package/dist/chunk-NEMWRJQS.cjs.map +0 -1
  65. package/dist/chunk-NVKHUAHU.js.map +0 -1
  66. package/dist/chunk-OVTTCX2E.js.map +0 -1
  67. package/dist/chunk-SMHTOWXG.cjs.map +0 -1
  68. package/dist/chunk-YXIEPTFG.cjs.map +0 -1
package/dist/three.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk4NOTVQ3I_cjs = require('./chunk-4NOTVQ3I.cjs');
4
- require('./chunk-NEMWRJQS.cjs');
3
+ var chunkTVVC4GVK_cjs = require('./chunk-TVVC4GVK.cjs');
4
+ require('./chunk-2YV7ISX6.cjs');
5
5
  require('./chunk-TWZNOUM7.cjs');
6
6
  var pixi_js = require('pixi.js');
7
7
  var three$1 = require('three');
@@ -170,7 +170,7 @@ function releaseThree(kind) {
170
170
 
171
171
  // src/three/ThreeSequence.ts
172
172
  var NOT_PURE = /\bMath\s*\.\s*random\s*\(|\bDate\s*\.\s*now\s*\(|\bperformance\s*\.\s*now\s*\(|\bnew\s+Date\s*\(/;
173
- var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
173
+ var ThreeSequence = class extends chunkTVVC4GVK_cjs.Sequence {
174
174
  _renderer = null;
175
175
  /** The renderer this layer draws with (`'webgl'` or `'webgpu'`), once it is built. */
176
176
  renderer = null;
@@ -194,6 +194,16 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
194
194
  /** Things to do just before every draw (the 2D layers shown on meshes: `threeLayerTexture`), and those layers' handles. Both go with the state to a layer that takes it over. */
195
195
  _drawHooks = /* @__PURE__ */ new Set();
196
196
  _layerTextures = [];
197
+ _pendingRebinds = [];
198
+ /** Every frame, whether this layer is alive or not: a 2D layer it shows stays off the stage (a tween of `autoAlpha` writes `visible = true` on it). */
199
+ syncFrame() {
200
+ super.syncFrame();
201
+ for (const h of this._layerTextures) h.keepHidden();
202
+ }
203
+ /** True when this layer shows 2D layers on its meshes (`threeLayerTexture`): the movie draws it after the rest of the frame is ready. */
204
+ get showsLayers() {
205
+ return this._layerTextures.length > 0;
206
+ }
197
207
  _scene = null;
198
208
  _camera = null;
199
209
  _ctx = null;
@@ -221,7 +231,7 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
221
231
  if (typeof spec.update === "function" && NOT_PURE.test(spec.update.toString())) {
222
232
  console.warn(`pixi-effects: three layer${spec.name ? ` "${spec.name}"` : ""}: 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`);
223
233
  }
224
- const scope = chunk4NOTVQ3I_cjs.buildScope(this, this.parent, this.root);
234
+ const scope = chunkTVVC4GVK_cjs.buildScope(this, this.parent, this.root);
225
235
  const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;
226
236
  const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;
227
237
  const resolution = spec.resolution ?? 1;
@@ -328,7 +338,7 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
328
338
  /** The 2D layer that a material shows (`threeLayerTexture`), for a click on the mesh to reach it (movie.pick); null for any other material. */
329
339
  screenOf(material) {
330
340
  const handle = this._layerTextures.find((h) => h.material === material);
331
- return handle ? { source: handle.source() } : null;
341
+ return handle ? { source: handle.source(), at: (u, v) => handle.sourceAt(u, v) } : null;
332
342
  }
333
343
  /** What `threeLayerTexture` asks of this layer: the layers listed before it, PixiJS's renderer, whether the GPU device is shared, and a place to hook in before every draw. */
334
344
  _makeHost() {
@@ -345,6 +355,10 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
345
355
  },
346
356
  track: (handle) => {
347
357
  this._layerTextures.push(handle);
358
+ return () => {
359
+ const i = this._layerTextures.indexOf(handle);
360
+ if (i >= 0) this._layerTextures.splice(i, 1);
361
+ };
348
362
  }
349
363
  };
350
364
  }
@@ -376,7 +390,7 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
376
390
  this._drawHooks = d._drawHooks;
377
391
  this._layerTextures = d._layerTextures;
378
392
  const host = this._makeHost();
379
- for (const h of this._layerTextures) h.rebind(host);
393
+ this._pendingRebinds = this._layerTextures.map((h) => h.prepare(host));
380
394
  if (this.spec && this._threeSpec.followCamera) this._checkFollowShape(width, height, name);
381
395
  this._makeSprite(this._texture, width, height, name);
382
396
  }
@@ -387,6 +401,8 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
387
401
  d._donated = true;
388
402
  d._tracked = false;
389
403
  this._borrowed = null;
404
+ for (const apply of this._pendingRebinds) apply();
405
+ this._pendingRebinds = [];
390
406
  }
391
407
  /**
392
408
  * Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method
@@ -784,7 +800,7 @@ var ThreeSequence = class extends chunk4NOTVQ3I_cjs.Sequence {
784
800
  function resolveDim(v, scope) {
785
801
  if (v === void 0) return void 0;
786
802
  if (typeof v === "number") return v;
787
- return chunk4NOTVQ3I_cjs.evaluateExpr(v, scope);
803
+ return chunkTVVC4GVK_cjs.evaluateExpr(v, scope);
788
804
  }
789
805
  var ids = /* @__PURE__ */ new WeakMap();
790
806
  var lastId = 0;
@@ -899,18 +915,39 @@ async function threeLayerTexture(ctx, name, options = {}) {
899
915
  if (source.spec.type !== "composition") {
900
916
  throw new Error(`${label}: "${name}" is a ${source.spec.type} layer: a layer shown on a mesh must be a composition (wrap it: { type: 'composition', name: '${name}', width: 480, height: 270, sequences: [ \u2026 ] })`);
901
917
  }
902
- const width = Math.max(1, Math.round(source.intrinsicWidth * resolution)), height = Math.max(1, Math.round(source.intrinsicHeight * resolution));
903
- const sharedRoute = host.shared && pixi.name === "webgpu";
904
- const rt = pixi_js.RenderTexture.create({ width, height, resolution: 1, ...sharedRoute ? { autoGenerateMipmaps: true } : {} });
905
- const gpuTexture = sharedRoute ? pixi.texture.getGpuSource?.(rt.source) : void 0;
906
- let texture, material, readCanvas = null;
907
- if (gpuTexture) {
908
- let webgpu, tsl;
918
+ {
919
+ const ini = source.spec.initial ?? {};
920
+ const moved = ["x", "y", "rotation", "pivotX", "pivotY"].some((k) => typeof ini[k] === "number" && ini[k] !== 0) || ["scale", "scaleX", "scaleY"].some((k) => typeof ini[k] === "number" && ini[k] !== 1);
921
+ if (moved && (source.maskSequence || source.spec.mask !== void 0)) {
922
+ console.warn(`${label}: "${name}" has a mask and is not at x: 0, y: 0 (anchor 0, scale 1, rotation 0): on the mesh its content is drawn from (0, 0) but its mask stays where the parent puts it, so the mask lands shifted. Put the screen at the origin (or mask a layer INSIDE the screen: that mask moves with it).`);
923
+ }
924
+ }
925
+ const logicalW = Math.max(1, Math.round(source.intrinsicWidth)), logicalH = Math.max(1, Math.round(source.intrinsicHeight));
926
+ const width = Math.max(1, Math.round(logicalW * resolution)), height = Math.max(1, Math.round(logicalH * resolution));
927
+ const limit = (() => {
928
+ const g = pixi;
929
+ return g.gpu?.device?.limits?.maxTextureDimension2D ?? (g.gl ? g.gl.getParameter(g.gl.MAX_TEXTURE_SIZE) : null) ?? 8192;
930
+ })();
931
+ if (width > limit || height > limit) {
932
+ throw new Error(`${label}: the texture would be ${width} x ${height} pixels (the layer is ${logicalW} x ${logicalH}, resolution ${resolution}), above what this GPU allows (${limit}). Use resolution ${Math.max(1, Math.floor(limit / Math.max(logicalW, logicalH) * 10) / 10)} or lower, or a smaller composition.`);
933
+ }
934
+ let sharedRoute = host.shared && pixi.name === "webgpu";
935
+ let webgpu, tsl;
936
+ if (sharedRoute) {
909
937
  try {
910
938
  [webgpu, tsl] = await Promise.all([import('three/webgpu'), import('three/tsl')]);
911
939
  } catch (err) {
912
940
  throw new Error(`${label}: needs "three/webgpu" and "three/tsl" in the import map (${err instanceof Error ? err.message : err})`);
913
941
  }
942
+ if (typeof webgpu.ExternalTexture !== "function") {
943
+ console.warn(`${label}: this page's three has no ExternalTexture (it came with three 0.180): the screen is read back every frame (1.6 ms at 480 x 270) instead of shared with the GPU. Use three 0.180 or later for the no-copy route.`);
944
+ sharedRoute = false;
945
+ }
946
+ }
947
+ const rt = pixi_js.RenderTexture.create({ width: logicalW, height: logicalH, resolution, ...sharedRoute ? { autoGenerateMipmaps: true } : {} });
948
+ const gpuTexture = sharedRoute ? pixi.texture.getGpuSource?.(rt.source) : void 0;
949
+ let texture, material, readCanvas = null;
950
+ if (gpuTexture) {
914
951
  const ext = new webgpu.ExternalTexture(gpuTexture);
915
952
  ext.colorSpace = webgpu.NoColorSpace;
916
953
  ext.minFilter = webgpu.LinearMipmapLinearFilter;
@@ -943,7 +980,7 @@ async function threeLayerTexture(ctx, name, options = {}) {
943
980
  }
944
981
  let current = source;
945
982
  let display = source.target;
946
- let sx = width / source.intrinsicWidth, sy = height / source.intrinsicHeight;
983
+ let sx = logicalW / source.intrinsicWidth, sy = logicalH / source.intrinsicHeight;
947
984
  let hidden = false;
948
985
  const hide = () => {
949
986
  display.visible = false;
@@ -979,30 +1016,54 @@ async function threeLayerTexture(ctx, name, options = {}) {
979
1016
  }
980
1017
  g.putImageData(new ImageData(pixels, w, h), 0, 0);
981
1018
  } else {
982
- g.clearRect(0, 0, width, height);
983
- g.drawImage(pixi.extract.canvas(rt), 0, 0);
1019
+ if (pixi.name === "webgl") {
1020
+ const { pixels, width: w, height: h } = pixi.extract.pixels(rt);
1021
+ for (let i = 3; i < pixels.length; i += 4) pixels[i] = 255;
1022
+ g.putImageData(new ImageData(pixels, w, h), 0, 0);
1023
+ } else {
1024
+ g.globalCompositeOperation = "source-over";
1025
+ g.fillStyle = "#000";
1026
+ g.fillRect(0, 0, width, height);
1027
+ g.drawImage(pixi.extract.canvas(rt), 0, 0);
1028
+ }
984
1029
  }
985
1030
  texture.needsUpdate = true;
986
1031
  }
987
1032
  };
988
1033
  const stop = host.beforeDraw(refresh);
989
1034
  refresh();
1035
+ let disposed = false;
990
1036
  const handle = {
991
1037
  material,
992
1038
  texture,
993
1039
  width,
994
1040
  height,
995
1041
  source: () => current,
996
- rebind(next) {
1042
+ sourceAt(u, v) {
1043
+ const t = texture;
1044
+ t.updateMatrix?.();
1045
+ const e = t.matrix?.elements;
1046
+ const tu = e ? e[0] * u + e[3] * v + e[6] : u, tv = e ? e[1] * u + e[4] * v + e[7] : v;
1047
+ return { x: tu, y: gpuTexture ? tv : 1 - tv };
1048
+ },
1049
+ prepare(next) {
997
1050
  const again = next.findLayer(name);
1051
+ if (disposed) return () => {
1052
+ };
998
1053
  if (!again) throw new Error(`${label}: after a rebuild there is no layer "${name}" before the three layer any more`);
999
- current = again;
1000
- display = again.target;
1001
- sx = width / again.intrinsicWidth;
1002
- sy = height / again.intrinsicHeight;
1003
- hide();
1004
- refresh();
1054
+ return () => {
1055
+ current = again;
1056
+ display = again.target;
1057
+ sx = logicalW / again.intrinsicWidth;
1058
+ sy = logicalH / again.intrinsicHeight;
1059
+ hide();
1060
+ refresh();
1061
+ };
1062
+ },
1063
+ keepHidden() {
1064
+ if (hidden && !disposed) display.visible = false;
1005
1065
  },
1066
+ // (the timeline can put it back: autoAlpha writes `visible`)
1006
1067
  dispose() {
1007
1068
  stop();
1008
1069
  if (hidden) {
@@ -1017,7 +1078,13 @@ async function threeLayerTexture(ctx, name, options = {}) {
1017
1078
  material.dispose?.();
1018
1079
  }
1019
1080
  };
1020
- host.track(handle);
1081
+ const untrack = host.track(handle);
1082
+ handle.dispose = /* @__PURE__ */ ((inner) => () => {
1083
+ if (disposed) return;
1084
+ disposed = true;
1085
+ untrack();
1086
+ inner();
1087
+ })(handle.dispose);
1021
1088
  return handle;
1022
1089
  }
1023
1090
 
@@ -1026,7 +1093,7 @@ function registerThree(options = {}) {
1026
1093
  const kind = options.renderer ?? "webgl";
1027
1094
  checkRendererKind(kind, "registerThree's renderer");
1028
1095
  setPageRenderer(kind);
1029
- chunk4NOTVQ3I_cjs.registerSequenceType("three", ThreeSequence);
1096
+ chunkTVVC4GVK_cjs.registerSequenceType("three", ThreeSequence);
1030
1097
  }
1031
1098
  function three(spec) {
1032
1099
  return spec;