pixi-effects 0.9.0 → 0.11.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 (53) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +6 -6
  3. package/ai/SKILL.md +4 -3
  4. package/ai/reference/cheatsheet.md +17 -6
  5. package/ai/reference/pitfalls.md +3 -3
  6. package/ai/reference/recipes.md +141 -11
  7. package/ai/template.html +11 -8
  8. package/ai/tools/render.mjs +14 -5
  9. package/dist/{Base-CSIulyIq.d.cts → Base-CwUxTfja.d.cts} +1 -1
  10. package/dist/{Base-DVgwyIUj.d.ts → Base-CyvSLoCP.d.ts} +1 -1
  11. package/dist/Composition-7TEKHZNQ.cjs +14 -0
  12. package/dist/{Composition-CM62XJKT.cjs.map → Composition-7TEKHZNQ.cjs.map} +1 -1
  13. package/dist/Composition-HIISJAX2.js +5 -0
  14. package/dist/{Composition-RJDSQYTV.js.map → Composition-HIISJAX2.js.map} +1 -1
  15. package/dist/Controller.cjs +34 -0
  16. package/dist/Controller.cjs.map +1 -1
  17. package/dist/Controller.d.cts +12 -2
  18. package/dist/Controller.d.ts +12 -2
  19. package/dist/Controller.js +34 -0
  20. package/dist/Controller.js.map +1 -1
  21. package/dist/{Movie-qGHp15c_.d.cts → Movie-DSSNOF3T.d.cts} +61 -2
  22. package/dist/{Movie-QMlFyHkf.d.ts → Movie-nzmWsxWX.d.ts} +61 -2
  23. package/dist/{chunk-O4AJYUPK.js → chunk-3IPDNC3E.js} +90 -14
  24. package/dist/chunk-3IPDNC3E.js.map +1 -0
  25. package/dist/{chunk-AGMNSJJH.cjs → chunk-6NWJLVCA.cjs} +196 -12
  26. package/dist/chunk-6NWJLVCA.cjs.map +1 -0
  27. package/dist/{chunk-FNKSXBKB.js → chunk-C6QHKYC5.js} +193 -14
  28. package/dist/chunk-C6QHKYC5.js.map +1 -0
  29. package/dist/{chunk-PDBDDGG5.cjs → chunk-F7NCHS6Q.cjs} +108 -32
  30. package/dist/chunk-F7NCHS6Q.cjs.map +1 -0
  31. package/dist/index.cjs +542 -38
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +303 -5
  34. package/dist/index.d.ts +303 -5
  35. package/dist/index.js +511 -27
  36. package/dist/index.js.map +1 -1
  37. package/dist/loader.css +110 -0
  38. package/dist/three.cjs +5 -5
  39. package/dist/three.d.cts +2 -2
  40. package/dist/three.d.ts +2 -2
  41. package/dist/three.js +1 -1
  42. package/dist/{types-oJijbn-K.d.ts → types-BXu28nJj.d.cts} +26 -2
  43. package/dist/{types-oJijbn-K.d.cts → types-BXu28nJj.d.ts} +26 -2
  44. package/docs/api.md +16 -1
  45. package/docs/dsl.md +137 -2
  46. package/llms-full.txt +318 -26
  47. package/package.json +5 -2
  48. package/dist/Composition-CM62XJKT.cjs +0 -14
  49. package/dist/Composition-RJDSQYTV.js +0 -5
  50. package/dist/chunk-AGMNSJJH.cjs.map +0 -1
  51. package/dist/chunk-FNKSXBKB.js.map +0 -1
  52. package/dist/chunk-O4AJYUPK.js.map +0 -1
  53. package/dist/chunk-PDBDDGG5.cjs.map +0 -1
@@ -24,6 +24,41 @@ function _interopNamespace(e) {
24
24
 
25
25
  var PIXI__namespace = /*#__PURE__*/_interopNamespace(PIXI);
26
26
 
27
+ // src/expr/random.ts
28
+ function mix(h) {
29
+ h = Math.imul(h ^ h >>> 16, 2246822507);
30
+ h = Math.imul(h ^ h >>> 13, 3266489909);
31
+ return (h ^ h >>> 16) >>> 0;
32
+ }
33
+ function fold(n) {
34
+ if (!Number.isFinite(n)) return 0;
35
+ const i = Math.floor(n);
36
+ const f = n - i;
37
+ return (i | 0) ^ Math.imul(Math.floor(f * 1048576), 2654435761);
38
+ }
39
+ function rand(seed) {
40
+ return mix(fold(seed) + 2654435769) / 4294967296;
41
+ }
42
+ function random(seed) {
43
+ let a = fold(seed) + 1831565813 | 0;
44
+ return () => {
45
+ a = a + 1831565813 | 0;
46
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
47
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
48
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
49
+ };
50
+ }
51
+ function noise(x, seed = 0) {
52
+ if (!Number.isFinite(x)) return 0;
53
+ const i = Math.floor(x);
54
+ const f = x - i;
55
+ const s = fold(seed) * 668265261;
56
+ const a = mix((i | 0) + s) / 2147483648 - 1;
57
+ const b = mix((i + 1 | 0) + s) / 2147483648 - 1;
58
+ const u = f * f * f * (f * (f * 6 - 15) + 10);
59
+ return a + (b - a) * u;
60
+ }
61
+
27
62
  // src/expr/Parser.ts
28
63
  var FUNCS = {
29
64
  min: Math.min,
@@ -36,8 +71,19 @@ var FUNCS = {
36
71
  pow: Math.pow,
37
72
  sin: Math.sin,
38
73
  cos: Math.cos,
39
- tan: Math.tan
74
+ tan: Math.tan,
75
+ rand: (seed) => rand(seed),
76
+ noise: (x, seed = 0) => noise(x, seed),
77
+ lerp: (a, b, t) => a + (b - a) * t,
78
+ clamp: (x, lo, hi) => Math.min(Math.max(x, lo), hi),
79
+ smoothstep: (a, b, x) => {
80
+ const u = Math.min(Math.max((x - a) / (b - a), 0), 1);
81
+ return u * u * (3 - 2 * u);
82
+ },
83
+ mod: (a, b) => (a % b + b) % b,
84
+ step: (edge, x) => x >= edge ? 1 : 0
40
85
  };
86
+ var CONSTS = { PI: Math.PI };
41
87
  function isDigit(c) {
42
88
  return c >= "0" && c <= "9";
43
89
  }
@@ -183,6 +229,7 @@ function evalNode(node, scope) {
183
229
  case "num":
184
230
  return node.value;
185
231
  case "var": {
232
+ if (node.name in CONSTS) return CONSTS[node.name];
186
233
  const v = scope[node.name];
187
234
  if (typeof v !== "number") throw new Error(`undefined variable: ${node.name}`);
188
235
  return v;
@@ -964,6 +1011,12 @@ var Sequence = class {
964
1011
  this.target = null;
965
1012
  }
966
1013
  };
1014
+ var NullSequence = class extends Sequence {
1015
+ async build() {
1016
+ this.target = new PIXI.Container();
1017
+ this.buildFilters();
1018
+ }
1019
+ };
967
1020
 
968
1021
  // src/space/specKeys.ts
969
1022
  function collectPropKeys(spec) {
@@ -2094,6 +2147,85 @@ function slice(line, a, b) {
2094
2147
  return out;
2095
2148
  }
2096
2149
 
2150
+ // src/sequences/morphPath.ts
2151
+ function resample(line, n) {
2152
+ const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
2153
+ const cum = [0];
2154
+ for (let i = 2; i < p.length; i += 2) cum.push(cum[cum.length - 1] + Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]));
2155
+ const total = cum[cum.length - 1];
2156
+ const out = [];
2157
+ if (!(total > 0)) {
2158
+ for (let i = 0; i < n; i++) out.push(p[0], p[1]);
2159
+ return out;
2160
+ }
2161
+ let seg = 1;
2162
+ for (let i = 0; i < n; i++) {
2163
+ const s = line.closed ? i * total / n : n === 1 ? 0 : i * total / (n - 1);
2164
+ while (seg < cum.length - 1 && cum[seg] < s) seg++;
2165
+ const len = cum[seg] - cum[seg - 1];
2166
+ const t = len > 0 ? (s - cum[seg - 1]) / len : 0;
2167
+ const k = seg * 2;
2168
+ out.push(p[k - 2] + (p[k] - p[k - 2]) * t, p[k - 1] + (p[k + 1] - p[k - 1]) * t);
2169
+ }
2170
+ return out;
2171
+ }
2172
+ var centroid = (pts) => {
2173
+ let x = 0, y = 0;
2174
+ for (let i = 0; i < pts.length; i += 2) {
2175
+ x += pts[i];
2176
+ y += pts[i + 1];
2177
+ }
2178
+ const n = pts.length / 2;
2179
+ return [x / n, y / n];
2180
+ };
2181
+ function align(a, b) {
2182
+ const n = a.length / 2;
2183
+ let best = b, bestCost = Infinity;
2184
+ for (const reversed of [false, true]) {
2185
+ for (let k = 0; k < n; k++) {
2186
+ let cost = 0;
2187
+ for (let i = 0; i < n && cost < bestCost; i++) {
2188
+ const j = reversed ? ((k - i) % n + n) % n : (k + i) % n;
2189
+ cost += (a[2 * i] - b[2 * j]) ** 2 + (a[2 * i + 1] - b[2 * j + 1]) ** 2;
2190
+ }
2191
+ if (cost < bestCost) {
2192
+ bestCost = cost;
2193
+ const out = [];
2194
+ for (let i = 0; i < n; i++) {
2195
+ const j = reversed ? ((k - i) % n + n) % n : (k + i) % n;
2196
+ out.push(b[2 * j], b[2 * j + 1]);
2197
+ }
2198
+ best = out;
2199
+ }
2200
+ }
2201
+ }
2202
+ return best;
2203
+ }
2204
+ function buildMorph(from, to, n = 128) {
2205
+ if (from.length === 0 || to.length === 0) return [];
2206
+ const pairs = [];
2207
+ const count = Math.max(from.length, to.length);
2208
+ for (let i = 0; i < count; i++) {
2209
+ const fa = from[i], fb = to[i];
2210
+ const closed = (fa?.closed ?? fb.closed) && (fb?.closed ?? fa.closed);
2211
+ const a = fa ? resample({ pts: fa.pts, closed }, n) : collapsed(resample({ pts: fb.pts, closed }, n));
2212
+ let b = fb ? resample({ pts: fb.pts, closed }, n) : collapsed(a);
2213
+ if (closed && fa && fb) b = align(a, b);
2214
+ pairs.push({ a, b, closed });
2215
+ }
2216
+ return pairs;
2217
+ }
2218
+ function collapsed(pts) {
2219
+ const [cx, cy] = centroid(pts);
2220
+ const out = [];
2221
+ for (let i = 0; i < pts.length; i += 2) out.push(cx, cy);
2222
+ return out;
2223
+ }
2224
+ function morphAt(pairs, t) {
2225
+ const u = Math.min(Math.max(t, 0), 1);
2226
+ return pairs.map(({ a, b, closed }) => ({ pts: a.map((v, i) => v + (b[i] - v) * u), closed }));
2227
+ }
2228
+
2097
2229
  // src/sequences/Shape.ts
2098
2230
  var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
2099
2231
  var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
@@ -2105,7 +2237,7 @@ var GEOMETRY_KEYS_BY_SHAPE = {
2105
2237
  arc: ["radius", "innerRadius", "startAngle", "endAngle"],
2106
2238
  line: [...TRIM_KEYS],
2107
2239
  polygon: [...TRIM_KEYS],
2108
- path: [...TRIM_KEYS]
2240
+ path: [...TRIM_KEYS, "morph"]
2109
2241
  };
2110
2242
  var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse", "arc"]);
2111
2243
  var ShapeSequence = class extends Sequence {
@@ -2148,8 +2280,9 @@ var ShapeSequence = class extends Sequence {
2148
2280
  }
2149
2281
  const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
2150
2282
  if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
2151
- this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
2152
- this._outline = makeOutline(this.spec, scope, this._state);
2283
+ const morph = this._setupMorph();
2284
+ this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state, morph);
2285
+ this._outline = makeOutline(this.spec, scope, this._state, morph);
2153
2286
  const { trimStart, trimEnd } = this._state;
2154
2287
  this._state.trimStart = 0;
2155
2288
  this._state.trimEnd = 1;
@@ -2178,6 +2311,33 @@ var ShapeSequence = class extends Sequence {
2178
2311
  this._redraw();
2179
2312
  this.buildFilters();
2180
2313
  }
2314
+ /** The prepared morph between `d` and `morphTo`, or null (and a warning when the spec asked for one that cannot work). */
2315
+ _setupMorph() {
2316
+ const who = describeLayer(this.spec);
2317
+ const top = this.spec;
2318
+ const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || collectPropKeys(this.spec).has("morph"));
2319
+ if (this.spec.shape !== "path") {
2320
+ if ("morphTo" in top) console.warn(`pixi-effects: ${who}: morphTo only works on a path shape (shape: 'path'); ignored`);
2321
+ return null;
2322
+ }
2323
+ if (top.morphTo === void 0) {
2324
+ if (wanted) console.warn(`pixi-effects: ${who}: morph needs morphTo (the outline to morph into); ignored`);
2325
+ return null;
2326
+ }
2327
+ let points2 = 128;
2328
+ if (top.morphPoints !== void 0) {
2329
+ const n = Number(top.morphPoints);
2330
+ if (Number.isInteger(n) && n >= 8 && n <= 2048) points2 = n;
2331
+ else console.warn(`pixi-effects: ${who}: morphPoints must be a whole number from 8 to 2048, got ${String(top.morphPoints)}; using 128`);
2332
+ }
2333
+ const pairs = buildMorph(flattenSvgPath(this.spec.d), flattenSvgPath(String(top.morphTo)), points2);
2334
+ if (pairs.length === 0) {
2335
+ console.warn(`pixi-effects: ${who}: morphTo "${String(top.morphTo)}" (or d) draws nothing, so there is nothing to morph; ignored`);
2336
+ return null;
2337
+ }
2338
+ this._state.morph ??= 0;
2339
+ return { pairs, to: String(top.morphTo) };
2340
+ }
2181
2341
  _fresh = false;
2182
2342
  _outline = null;
2183
2343
  _redraw() {
@@ -2412,7 +2572,7 @@ var STATE_DRAWERS = {
2412
2572
  ellipse: drawEllipseFromState,
2413
2573
  arc: drawArcFromState
2414
2574
  };
2415
- function makeDrawGeometry(spec, scope, state) {
2575
+ function makeDrawGeometry(spec, scope, state, morph) {
2416
2576
  const stateDrawer = STATE_DRAWERS[spec.shape];
2417
2577
  if (stateDrawer) return (g) => stateDrawer(g, state);
2418
2578
  switch (spec.shape) {
@@ -2420,13 +2580,30 @@ function makeDrawGeometry(spec, scope, state) {
2420
2580
  return makeLineDraw(spec, scope);
2421
2581
  case "polygon":
2422
2582
  return makePolygonDraw(spec, scope);
2423
- case "path":
2424
- return makePathDraw(spec);
2583
+ case "path": {
2584
+ const plain = makePathDraw(spec);
2585
+ if (!morph) return plain;
2586
+ const last = makePathDraw({ ...spec, d: morph.to });
2587
+ return (g) => {
2588
+ const t = state.morph ?? 0;
2589
+ if (t <= 0) plain(g);
2590
+ else if (t >= 1) last(g);
2591
+ else for (const part of morphAt(morph.pairs, t)) drawPolyline(g, part);
2592
+ };
2593
+ }
2425
2594
  }
2426
2595
  return () => {
2427
2596
  };
2428
2597
  }
2429
- function makeOutline(spec, scope, s) {
2598
+ function drawPolyline(g, part) {
2599
+ if (part.closed) {
2600
+ g.poly(part.pts, true);
2601
+ return;
2602
+ }
2603
+ g.moveTo(part.pts[0], part.pts[1]);
2604
+ for (let i = 2; i < part.pts.length; i += 2) g.lineTo(part.pts[i], part.pts[i + 1]);
2605
+ }
2606
+ function makeOutline(spec, scope, s, morph) {
2430
2607
  switch (spec.shape) {
2431
2608
  case "rect":
2432
2609
  return () => {
@@ -2454,6 +2631,7 @@ function makeOutline(spec, scope, s) {
2454
2631
  return () => lines;
2455
2632
  }
2456
2633
  case "path": {
2634
+ if (morph) return () => morphAt(morph.pairs, s.morph ?? 0);
2457
2635
  let lines = null;
2458
2636
  return () => lines ??= flattenSvgPath(spec.d);
2459
2637
  }
@@ -2534,7 +2712,7 @@ function numOrZero(v, scope) {
2534
2712
  var _CompositionSequence = null;
2535
2713
  async function getCompositionSequence() {
2536
2714
  if (!_CompositionSequence) {
2537
- _CompositionSequence = (await import('./Composition-CM62XJKT.cjs')).CompositionSequence;
2715
+ _CompositionSequence = (await import('./Composition-7TEKHZNQ.cjs')).CompositionSequence;
2538
2716
  }
2539
2717
  return _CompositionSequence;
2540
2718
  }
@@ -2544,7 +2722,8 @@ var staticTypes = {
2544
2722
  audio: AudioSequence,
2545
2723
  video: VideoSequence,
2546
2724
  shape: ShapeSequence,
2547
- camera: CameraSequence
2725
+ camera: CameraSequence,
2726
+ null: NullSequence
2548
2727
  };
2549
2728
  var registry2 = {};
2550
2729
  function registerSequenceType(type, ctor) {
@@ -2575,6 +2754,7 @@ exports.CameraSequence = CameraSequence;
2575
2754
  exports.DEFAULT_FOV = DEFAULT_FOV;
2576
2755
  exports.DEG = DEG;
2577
2756
  exports.NEAR = NEAR;
2757
+ exports.NullSequence = NullSequence;
2578
2758
  exports.Sequence = Sequence;
2579
2759
  exports.buildScope = buildScope;
2580
2760
  exports.buildSequenceTree = buildSequenceTree;
@@ -2583,13 +2763,17 @@ exports.collectPropKeys = collectPropKeys;
2583
2763
  exports.describeLayer = describeLayer;
2584
2764
  exports.ensureFilterLibrary = ensureFilterLibrary;
2585
2765
  exports.evaluateExpr = evaluateExpr;
2766
+ exports.flattenSvgPath = flattenSvgPath;
2586
2767
  exports.homeCamera = homeCamera;
2587
2768
  exports.homeDistance = homeDistance;
2588
2769
  exports.lintText = lintText;
2589
2770
  exports.lintTiming = lintTiming;
2771
+ exports.noise = noise;
2590
2772
  exports.projectLayer = projectLayer;
2773
+ exports.rand = rand;
2774
+ exports.random = random;
2591
2775
  exports.registerSequenceType = registerSequenceType;
2592
2776
  exports.resolveAt = resolveAt;
2593
2777
  exports.summarizeWarnings = summarizeWarnings;
2594
- //# sourceMappingURL=chunk-AGMNSJJH.cjs.map
2595
- //# sourceMappingURL=chunk-AGMNSJJH.cjs.map
2778
+ //# sourceMappingURL=chunk-6NWJLVCA.cjs.map
2779
+ //# sourceMappingURL=chunk-6NWJLVCA.cjs.map