pixi-effects 0.20.0 → 0.22.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 (83) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +6 -6
  3. package/ai/SKILL.md +3 -3
  4. package/ai/chat-template.html +3 -3
  5. package/ai/reference/cheatsheet.md +7 -7
  6. package/ai/reference/pitfalls.md +8 -1
  7. package/ai/reference/recipes.md +55 -0
  8. package/ai/template.html +5 -5
  9. package/ai/tools/check.mjs +15 -4
  10. package/dist/{Base-wYJQ2g5Q.d.cts → Base-BzlPgd-D.d.cts} +1 -1
  11. package/dist/{Base-CzfLGoDr.d.ts → Base-gu-5X0Cv.d.ts} +1 -1
  12. package/dist/Composition-BK5SH6J7.cjs +16 -0
  13. package/dist/{Composition-LL2XXU5N.cjs.map → Composition-BK5SH6J7.cjs.map} +1 -1
  14. package/dist/Composition-Q5TVG3HM.js +7 -0
  15. package/dist/{Composition-6PA4C4TV.js.map → Composition-Q5TVG3HM.js.map} +1 -1
  16. package/dist/Controller.cjs +2 -2
  17. package/dist/Controller.d.cts +2 -2
  18. package/dist/Controller.d.ts +2 -2
  19. package/dist/Controller.js +1 -1
  20. package/dist/{Movie-CBxGH5ms.d.ts → Movie--_TJvdJa.d.ts} +3 -1
  21. package/dist/{Movie-CzzJw8A-.d.cts → Movie-DMxOoTdW.d.cts} +3 -1
  22. package/dist/Presenter.cjs +2 -2
  23. package/dist/Presenter.d.cts +2 -2
  24. package/dist/Presenter.d.ts +2 -2
  25. package/dist/Presenter.js +1 -1
  26. package/dist/blendModes-5E4G2ZZQ.cjs +94 -0
  27. package/dist/blendModes-5E4G2ZZQ.cjs.map +1 -0
  28. package/dist/blendModes-HCP5XTNP.js +90 -0
  29. package/dist/blendModes-HCP5XTNP.js.map +1 -0
  30. package/dist/chunk-BPTW7L25.cjs +275 -0
  31. package/dist/chunk-BPTW7L25.cjs.map +1 -0
  32. package/dist/{chunk-DQHXVNOI.js → chunk-DC4JPY6A.js} +108 -273
  33. package/dist/chunk-DC4JPY6A.js.map +1 -0
  34. package/dist/chunk-E7RONUZ7.js +268 -0
  35. package/dist/chunk-E7RONUZ7.js.map +1 -0
  36. package/dist/{chunk-NO26HWR7.cjs → chunk-IFZOI3JQ.cjs} +131 -295
  37. package/dist/chunk-IFZOI3JQ.cjs.map +1 -0
  38. package/dist/chunk-K4JVI5HK.cjs +143 -0
  39. package/dist/chunk-K4JVI5HK.cjs.map +1 -0
  40. package/dist/{chunk-FFYA3UBU.cjs → chunk-MHOO2CVU.cjs} +290 -62
  41. package/dist/chunk-MHOO2CVU.cjs.map +1 -0
  42. package/dist/{chunk-MNM56B3X.js → chunk-NHICCDTC.js} +13 -3
  43. package/dist/chunk-NHICCDTC.js.map +1 -0
  44. package/dist/{chunk-TSPMKV2F.js → chunk-UQDEDYVM.js} +261 -33
  45. package/dist/chunk-UQDEDYVM.js.map +1 -0
  46. package/dist/{chunk-WTRKDIKH.cjs → chunk-UZTKEYFP.cjs} +13 -3
  47. package/dist/chunk-UZTKEYFP.cjs.map +1 -0
  48. package/dist/chunk-YEPDQ7I3.js +132 -0
  49. package/dist/chunk-YEPDQ7I3.js.map +1 -0
  50. package/dist/index.cjs +72 -68
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +4 -4
  53. package/dist/index.d.ts +4 -4
  54. package/dist/index.js +11 -7
  55. package/dist/index.js.map +1 -1
  56. package/dist/loader.css +1 -1
  57. package/dist/{music-CFEC7HKL.js → music-FUN7N225.js} +3 -3
  58. package/dist/{music-CFEC7HKL.js.map → music-FUN7N225.js.map} +1 -1
  59. package/dist/{music-UAN7DXK4.cjs → music-GEAH2XCT.cjs} +7 -7
  60. package/dist/{music-UAN7DXK4.cjs.map → music-GEAH2XCT.cjs.map} +1 -1
  61. package/dist/{sfx-EX4PUBMV.cjs → sfx-2DYTYNYW.cjs} +8 -8
  62. package/dist/{sfx-EX4PUBMV.cjs.map → sfx-2DYTYNYW.cjs.map} +1 -1
  63. package/dist/{sfx-U3GM2MED.js → sfx-3IDAJ3UZ.js} +3 -3
  64. package/dist/{sfx-U3GM2MED.js.map → sfx-3IDAJ3UZ.js.map} +1 -1
  65. package/dist/three.cjs +7 -6
  66. package/dist/three.cjs.map +1 -1
  67. package/dist/three.d.cts +2 -2
  68. package/dist/three.d.ts +2 -2
  69. package/dist/three.js +3 -2
  70. package/dist/three.js.map +1 -1
  71. package/dist/{types-YmUaViL1.d.cts → types-DBbZVKGS.d.cts} +7 -4
  72. package/dist/{types-YmUaViL1.d.ts → types-DBbZVKGS.d.ts} +7 -4
  73. package/docs/dsl.md +82 -3
  74. package/llms-full.txt +155 -14
  75. package/package.json +1 -1
  76. package/dist/Composition-6PA4C4TV.js +0 -5
  77. package/dist/Composition-LL2XXU5N.cjs +0 -14
  78. package/dist/chunk-DQHXVNOI.js.map +0 -1
  79. package/dist/chunk-FFYA3UBU.cjs.map +0 -1
  80. package/dist/chunk-MNM56B3X.js.map +0 -1
  81. package/dist/chunk-NO26HWR7.cjs.map +0 -1
  82. package/dist/chunk-TSPMKV2F.js.map +0 -1
  83. package/dist/chunk-WTRKDIKH.cjs.map +0 -1
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkWTRKDIKH_cjs = require('./chunk-WTRKDIKH.cjs');
3
+ var chunkBPTW7L25_cjs = require('./chunk-BPTW7L25.cjs');
4
+ var chunkUZTKEYFP_cjs = require('./chunk-UZTKEYFP.cjs');
4
5
  var PIXI = require('pixi.js');
5
6
  var gsap = require('gsap');
6
7
 
@@ -500,7 +501,7 @@ function checkEase(ease, where) {
500
501
  console.warn(`pixi-effects: ${where}: "${ease}" is a family, not an ease \u2014 write ${ease.toLowerCase()}.out, ${ease.toLowerCase()}.in or ${ease.toLowerCase()}.inOut`);
501
502
  return;
502
503
  }
503
- const guess = chunkWTRKDIKH_cjs.suggestName(ease, EASE_NAMES);
504
+ const guess = chunkUZTKEYFP_cjs.suggestName(ease, EASE_NAMES);
504
505
  console.warn(`pixi-effects: ${where}: unknown ease "${ease}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (GSAP would run it as its default ease, power1.out). Examples: ${EASE_NAMES.slice(0, 7).join(", ")}, back.out(1.7), elastic.out(1, 0.3), steps(8)`);
505
506
  }
506
507
 
@@ -1110,7 +1111,7 @@ var GRAIN_KEYS = ["amount", "size", "seed", "fps", "color"];
1110
1111
  var GrainFilter = class extends PIXI.Filter {
1111
1112
  _fps;
1112
1113
  constructor(options = {}) {
1113
- chunkWTRKDIKH_cjs.warnUnknownOptions("grain filter", options, GRAIN_KEYS);
1114
+ chunkUZTKEYFP_cjs.warnUnknownOptions("grain filter", options, GRAIN_KEYS);
1114
1115
  const { amount = 0.08, size = 1.5, seed = 0, fps = 24, color = 0 } = options;
1115
1116
  super({
1116
1117
  glProgram: PIXI.GlProgram.from({ vertex: GL_VERTEX, fragment: GL_FRAGMENT2, name: "grain-filter" }),
@@ -1218,7 +1219,7 @@ function isNamedFilterType(t) {
1218
1219
  return !NOT_NAMED.has(t);
1219
1220
  }
1220
1221
  function unknownType(t) {
1221
- const guess = chunkWTRKDIKH_cjs.suggestName(t, FILTER_TYPES);
1222
+ const guess = chunkUZTKEYFP_cjs.suggestName(t, FILTER_TYPES);
1222
1223
  return new Error(`pixi-effects: unknown filter type "${t}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${[...FILTER_TYPES, "chromaKey", "custom"].join(", ")})`);
1223
1224
  }
1224
1225
  var library = null;
@@ -1267,7 +1268,7 @@ function colorMatrix(params) {
1267
1268
  const preset = params.preset;
1268
1269
  if (preset !== void 0) {
1269
1270
  if (!MATRIX_PRESETS.includes(preset)) {
1270
- const guess = chunkWTRKDIKH_cjs.suggestName(preset, MATRIX_PRESETS);
1271
+ const guess = chunkUZTKEYFP_cjs.suggestName(preset, MATRIX_PRESETS);
1271
1272
  throw new Error(`pixi-effects: colorMatrix preset "${preset}" is not one of ${MATRIX_PRESETS.join(", ")}${guess ? ` \u2014 did you mean "${guess}"?` : ""}`);
1272
1273
  }
1273
1274
  f[preset === "grayscale" ? "desaturate" : preset].call(f);
@@ -1429,267 +1430,6 @@ var NullSequence = class extends Sequence {
1429
1430
  this.buildFilters();
1430
1431
  }
1431
1432
  };
1432
-
1433
- // src/space/specKeys.ts
1434
- function collectPropKeys(spec) {
1435
- const out = /* @__PURE__ */ new Set();
1436
- for (const k of Object.keys(spec.initial ?? {})) out.add(k);
1437
- for (const kf of spec.keyframes ?? []) {
1438
- for (const bag of [kf.set, kf.to, kf.from]) {
1439
- for (const k of Object.keys(bag ?? {})) out.add(k);
1440
- }
1441
- }
1442
- return out;
1443
- }
1444
-
1445
- // src/core/layerKeys.ts
1446
- var COMMON = ["type", "name", "parent", "at", "duration", "initial", "keyframes", "filters", "filterArea", "mask", "maskInverted", "blendMode", "threeD", "hideBehindCamera"];
1447
- var VIDEO = [...COMMON, "asset", "loop", "audio", "volume", "speed"];
1448
- var IMAGE = [...COMMON, "asset", "colorSpace"];
1449
- var TEXT = [...COMMON, "text", "format", "style", "colorSpace", "fillGradient"];
1450
- var AUDIO = [...COMMON, "volume", "asset", "loop", "sfx", "music", "speed"];
1451
- var COMPOSITION = [...COMMON, "width", "height", "sequences", "transitions", "speed"];
1452
- var CAMERA = [...COMMON];
1453
- var NULL = [...COMMON];
1454
- var SHAPE = [...COMMON, "shape", "fillGradient", "colorSpace", "strokeCap", "strokeJoin"];
1455
- var TRIM = ["trimStart", "trimEnd", "trimEach"];
1456
- var RECT = [...SHAPE, ...TRIM, "width", "height", "cornerRadius", "anchorX", "anchorY"];
1457
- var CIRCLE = [...SHAPE, ...TRIM, "radius", "anchorX", "anchorY"];
1458
- var ELLIPSE = [...SHAPE, ...TRIM, "radiusX", "radiusY", "anchorX", "anchorY"];
1459
- var ARC = [...SHAPE, "radius", "innerRadius", "startAngle", "endAngle"];
1460
- var LINE = [...SHAPE, ...TRIM, "from", "to"];
1461
- var POLYGON = [...SHAPE, ...TRIM, "points", "open"];
1462
- var PATH = [...SHAPE, ...TRIM, "d", "morphTo", "morph", "morphPoints"];
1463
- var SHAPES = { rect: RECT, circle: CIRCLE, ellipse: ELLIPSE, arc: ARC, line: LINE, polygon: POLYGON, path: PATH };
1464
- var BY_TYPE = { video: VIDEO, image: IMAGE, text: TEXT, audio: AUDIO, composition: COMPOSITION, camera: CAMERA, null: NULL };
1465
- function kindName(spec) {
1466
- return spec.type === "shape" && spec.shape ? `${spec.shape} shape` : `${spec.type} layer`;
1467
- }
1468
- function layerKeys(spec) {
1469
- if (spec.type === "shape") return spec.shape && SHAPES[spec.shape] || null;
1470
- return BY_TYPE[spec.type] ?? null;
1471
- }
1472
- function kindsWithKey(key) {
1473
- const out = [];
1474
- for (const [shape, keys] of Object.entries(SHAPES)) if (keys.includes(key)) out.push(`${shape} shape`);
1475
- for (const [type, keys] of Object.entries(BY_TYPE)) if (keys.includes(key)) out.push(`${type} layer`);
1476
- return out;
1477
- }
1478
- var PROP_KEYS = /* @__PURE__ */ new Set([
1479
- // transform and look (GSAP + PixiPlugin names)
1480
- "x",
1481
- "y",
1482
- "z",
1483
- "alpha",
1484
- "rotation",
1485
- "rotationX",
1486
- "rotationY",
1487
- "width",
1488
- "height",
1489
- "visible",
1490
- "autoAlpha",
1491
- "scale",
1492
- "scaleX",
1493
- "scaleY",
1494
- "anchor",
1495
- "anchorX",
1496
- "anchorY",
1497
- "pivot",
1498
- "pivotX",
1499
- "pivotY",
1500
- "skew",
1501
- "skewX",
1502
- "skewY",
1503
- "position",
1504
- "positionX",
1505
- "positionY",
1506
- "tint",
1507
- "colorize",
1508
- "colorizeAmount",
1509
- "blur",
1510
- "blurX",
1511
- "blurY",
1512
- "blurPadding",
1513
- // shapes
1514
- "fillColor",
1515
- "fillAlpha",
1516
- "strokeColor",
1517
- "strokeAlpha",
1518
- "strokeWidth",
1519
- "lineColor",
1520
- "lineAlpha",
1521
- "cornerRadius",
1522
- "radius",
1523
- "radiusX",
1524
- "radiusY",
1525
- "innerRadius",
1526
- "startAngle",
1527
- "endAngle",
1528
- "trimStart",
1529
- "trimEnd",
1530
- "trimEach",
1531
- "morph",
1532
- "fillGradient",
1533
- "strokeCap",
1534
- "strokeJoin",
1535
- // text, audio, video
1536
- "fill",
1537
- "value",
1538
- "visibleChars",
1539
- "text",
1540
- "volume",
1541
- "time",
1542
- // camera
1543
- "lookAtX",
1544
- "lookAtY",
1545
- "lookAtZ",
1546
- "fov",
1547
- "offsetX",
1548
- "offsetY",
1549
- "offsetZ",
1550
- "lookOffsetX",
1551
- "lookOffsetY",
1552
- "lookOffsetZ"
1553
- ]);
1554
- var STYLE_KEYS = [
1555
- "fontSize",
1556
- "fontFamily",
1557
- "fontWeight",
1558
- "fontStyle",
1559
- "fontVariant",
1560
- "fill",
1561
- "stroke",
1562
- "dropShadow",
1563
- "letterSpacing",
1564
- "lineHeight",
1565
- "leading",
1566
- "align",
1567
- "wordWrap",
1568
- "wordWrapWidth",
1569
- "breakWords",
1570
- "whiteSpace",
1571
- "padding",
1572
- "textBaseline",
1573
- "trim",
1574
- "lineJoin",
1575
- "miterLimit",
1576
- "filters",
1577
- "tagStyles"
1578
- ];
1579
-
1580
- // src/core/lint.ts
1581
- var defaultWarn = (m) => console.warn(m);
1582
- function describeLayer(spec) {
1583
- return spec.name ? `layer "${spec.name}"` : `unnamed ${spec.type} layer`;
1584
- }
1585
- function lintTiming(spec, parentDuration, warn = defaultWarn) {
1586
- const who = describeLayer(spec);
1587
- const at = spec.at ?? 0;
1588
- if (at >= parentDuration) {
1589
- warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
1590
- }
1591
- if (spec.type === "audio" && (spec.sfx !== void 0 || spec.music !== void 0) && spec.duration === void 0) return;
1592
- const duration = spec.duration ?? parentDuration;
1593
- (spec.keyframes ?? []).forEach((kf, i) => {
1594
- const kat = kf.at ?? 0;
1595
- if (kat >= duration) {
1596
- warn(
1597
- `pixi-effects: ${who}: keyframes[${i}] starts at ${kat}s, after the layer ends (duration ${duration}s), so it never plays. Keyframe \`at\` is measured from the start of this layer, not from the start of the composition.`,
1598
- "late-keyframe"
1599
- );
1600
- }
1601
- });
1602
- }
1603
- function summarizeWarnings(messages, shown = 3) {
1604
- if (messages.length <= shown) return messages;
1605
- return [...messages.slice(0, shown), `pixi-effects: ${messages.length - shown} more layers with the same problem (the same loop or helper is probably building them): fix the ones above and these go away.`];
1606
- }
1607
- function lintText(spec, warn = defaultWarn) {
1608
- if (spec.type !== "text") return;
1609
- const strings = [spec.text ?? "", ...(spec.keyframes ?? []).map((kf) => String(kf.set?.text ?? ""))];
1610
- const hasPlaceholder = strings.some((t) => t.includes("{value}"));
1611
- if (hasPlaceholder && !collectPropKeys(spec).has("value")) {
1612
- warn(`pixi-effects: ${describeLayer(spec)}: the text has a {value} placeholder but nothing sets or animates \`value\`, so it prints 0. Set initial: { value: \u2026 } or animate it; {value} is reserved for counters (there is no way to print a literal "{value}").`);
1613
- }
1614
- if (collectPropKeys(spec).has("value") && !hasPlaceholder) {
1615
- warn(`pixi-effects: ${describeLayer(spec)}: \`value\` is set or animated but the text has no {value} placeholder, so nothing shows it. Use text: '{value}' (or e.g. '{value} users').`);
1616
- }
1617
- }
1618
- var REMAPPABLE = /* @__PURE__ */ new Set(["video", "audio", "composition"]);
1619
- var REMAP_NAMES = /* @__PURE__ */ new Set(["time", "timeRemap", "reverse"]);
1620
- var TIME_BAGS = ["set", "to", "from"];
1621
- function lintRemap(spec, warn) {
1622
- const s = spec;
1623
- const who = describeLayer(spec);
1624
- const kfs = s.keyframes ?? [];
1625
- const bags = [s.initial, ...kfs.flatMap((kf) => TIME_BAGS.map((b) => kf[b]))];
1626
- const timeInInitial = !!s.initial && s.initial.time !== void 0;
1627
- const timeInKeyframes = kfs.some((kf) => TIME_BAGS.some((b) => kf[b] && kf[b].time !== void 0));
1628
- const timed = timeInInitial || timeInKeyframes;
1629
- if (bags.some((bag) => bag && bag.speed !== void 0)) {
1630
- warn(`pixi-effects: ${who}: speed is a fixed setting, not an animatable property: write it on the layer (speed: 2); to change the speed over time, animate time (keyframes: [{ at: 0, from: { time: 0 }, to: { time: 4 }, duration: 2, ease: 'power2.in' }])`);
1631
- }
1632
- if (!REMAPPABLE.has(spec.type)) {
1633
- if (timed) warn(`pixi-effects: ${who}: "time" only works on video, audio and composition layers; put this layer in a composition and remap that (it is ignored here)`);
1634
- return;
1635
- }
1636
- if (s.reverse !== void 0) warn(`pixi-effects: ${who}: "reverse" is not a key: write speed: -1 to play backward`);
1637
- if (s.timeRemap !== void 0) warn(`pixi-effects: ${who}: "timeRemap" is not a key: animate time in keyframes (from / to / set), or write speed`);
1638
- if (s.time !== void 0) warn(`pixi-effects: ${who}: "time" belongs in initial or keyframes (initial: { time: 2 }), not on the layer`);
1639
- if (spec.type === "audio" && (s.sfx !== void 0 || s.music !== void 0) && (s.speed !== void 0 || timed)) {
1640
- warn(`pixi-effects: ${who}: speed and time do not apply to a synthesised sound (sfx, music); change an sfx's pitch with pitch (semitones), or put it in a composition and remap that`);
1641
- return;
1642
- }
1643
- if (s.speed !== void 0 && (typeof s.speed !== "number" || !Number.isFinite(s.speed) || s.speed === 0)) {
1644
- warn(`pixi-effects: ${who}: speed ${JSON.stringify(s.speed)} cannot be used: write a number other than 0 (negative plays backward); to hold a moment, key time to the same value twice`);
1645
- }
1646
- if (s.speed !== void 0 && timeInKeyframes) {
1647
- warn(`pixi-effects: ${who}: speed and keyframed time are both set; time wins and speed is ignored. Use one of them`);
1648
- }
1649
- if (timeInInitial && typeof s.initial.time !== "number") {
1650
- warn(`pixi-effects: ${who}: initial.time must be a number of seconds, got ${JSON.stringify(s.initial.time)}`);
1651
- }
1652
- kfs.forEach((kf, i) => {
1653
- for (const b of TIME_BAGS) {
1654
- const v = kf[b]?.time;
1655
- if (v !== void 0 && typeof v !== "number" && typeof v !== "string") warn(`pixi-effects: ${who}: keyframes[${i}].${b}.time must be a number of seconds, got ${JSON.stringify(v)}`);
1656
- }
1657
- });
1658
- }
1659
- function lintKeys(spec, warn = defaultWarn) {
1660
- const who = describeLayer(spec);
1661
- const valid = layerKeys(spec);
1662
- if (valid) {
1663
- for (const key of Object.keys(spec)) {
1664
- if (valid.includes(key) || spec[key] === void 0) continue;
1665
- if (REMAPPABLE.has(spec.type) && REMAP_NAMES.has(key)) continue;
1666
- const guess = chunkWTRKDIKH_cjs.suggestName(key, valid.filter((k) => k !== "type"));
1667
- const owners = kindsWithKey(key);
1668
- const belongs = owners.length ? ` (it belongs to ${owners.slice(0, 3).join(", ")})` : "";
1669
- const hint = guess ? ` \u2014 did you mean "${guess}"?${belongs}` : belongs;
1670
- warn(`pixi-effects: ${who}: "${key}" is not a ${kindName(spec)} key${hint}. Valid keys: ${valid.join(", ")}`);
1671
- }
1672
- }
1673
- lintRemap(spec, warn);
1674
- const said = /* @__PURE__ */ new Set();
1675
- const bags = [spec.initial, ...(spec.keyframes ?? []).flatMap((kf) => [kf.set, kf.to, kf.from])];
1676
- for (const bag of bags) {
1677
- for (const key of Object.keys(bag ?? {})) {
1678
- if (bag[key] === void 0) continue;
1679
- if (PROP_KEYS.has(key) || key.includes(".") || /^gradient/i.test(key) || said.has(key) || key === "speed") continue;
1680
- said.add(key);
1681
- const guess = chunkWTRKDIKH_cjs.suggestName(key, [...PROP_KEYS]);
1682
- warn(`pixi-effects: ${who}: "${key}" is not an animatable property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (in initial, set, to or from). See the cheatsheet for the properties of this kind of layer`);
1683
- }
1684
- }
1685
- if (spec.type === "text" && spec.style && typeof spec.style === "object") {
1686
- for (const key of Object.keys(spec.style)) {
1687
- if (STYLE_KEYS.includes(key) || spec.style[key] === void 0) continue;
1688
- const guess = chunkWTRKDIKH_cjs.suggestName(key, STYLE_KEYS);
1689
- warn(`pixi-effects: ${who}: style.${key} is not a text style key${guess ? ` \u2014 did you mean "${guess}"?` : ""} (it is ignored). Keys: ${STYLE_KEYS.join(", ")}`);
1690
- }
1691
- }
1692
- }
1693
1433
  var BAGS = ["set", "to", "from"];
1694
1434
  function timeRemapOf(spec, prop = "time") {
1695
1435
  const hasInitial = !!spec.initial && "time" in spec.initial;
@@ -1912,12 +1652,82 @@ function projectLayer(t, frame, b) {
1912
1652
  const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
1913
1653
  return { corners, depth: origin.depth, visible };
1914
1654
  }
1655
+
1656
+ // src/space/focus.ts
1657
+ var DEFAULT_APERTURE = 30;
1658
+ var MIN_BLUR = 0.05;
1659
+ var MAX_BLUR = 32;
1660
+ var MANY_BLURRED = 20;
1661
+ function blurRadius(aperture, focal, depth, focusDepth) {
1662
+ if (!(aperture > 0) || !(focal > 0) || !(depth > 0) || !(focusDepth > 0)) return 0;
1663
+ const r = aperture * focal * Math.abs(1 / depth - 1 / focusDepth) / 2;
1664
+ return Math.min(r, MAX_BLUR);
1665
+ }
1666
+ var SCOPE_NAMES = /* @__PURE__ */ new Set(["w", "h", "W", "H", "GW", "GH", "contain", "cover", "t", "d", "T"]);
1667
+ function looksLikeLayerName(s) {
1668
+ return /^[A-Za-z_][\w-]*$/.test(s) && !SCOPE_NAMES.has(s);
1669
+ }
1670
+ var isName = (v, known) => typeof v === "string" && (known.has(v) || looksLikeLayerName(v));
1671
+ function focusNames(props, known) {
1672
+ const out = [];
1673
+ const read = (bag) => {
1674
+ const v = bag?.focus;
1675
+ if (isName(v, known)) out.push(v);
1676
+ };
1677
+ read(props.initial);
1678
+ for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from]) read(bag);
1679
+ return out;
1680
+ }
1681
+ function withFocusResolved(props, zOf, known = /* @__PURE__ */ new Set()) {
1682
+ if (focusNames(props, known).length === 0) return props;
1683
+ const fix = (bag) => {
1684
+ const v = bag?.focus;
1685
+ if (!bag || !isName(v, known)) return bag;
1686
+ return { ...bag, focus: zOf(v) ?? 0 };
1687
+ };
1688
+ return {
1689
+ ...props,
1690
+ initial: fix(props.initial),
1691
+ keyframes: props.keyframes?.map((kf) => ({ ...kf, set: fix(kf.set), to: fix(kf.to), from: fix(kf.from) }))
1692
+ };
1693
+ }
1694
+ function layerInitialZ(spec, scope) {
1695
+ const z = spec.initial?.z;
1696
+ if (typeof z === "number") return z;
1697
+ if (typeof z === "string") return evaluateExpr(z, scope);
1698
+ return 0;
1699
+ }
1700
+ var movesZ = (spec) => (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((bag) => bag && "z" in bag));
1701
+ function focusProblems(camera, siblings) {
1702
+ const out = [];
1703
+ const said = /* @__PURE__ */ new Set();
1704
+ const threeD = siblings.filter((s) => s.threeD && s.name).map((s) => s.name);
1705
+ const known = new Set(siblings.map((s) => s.name).filter((n) => !!n));
1706
+ for (const name of focusNames(camera, known)) {
1707
+ if (said.has(name)) continue;
1708
+ said.add(name);
1709
+ const same = siblings.filter((s) => s.name === name);
1710
+ const hit = same.find((s) => s.threeD) ?? same[0];
1711
+ if (!hit) out.push({ kind: "missing", name, hint: chunkUZTKEYFP_cjs.suggestName(name, threeD) });
1712
+ else if (!hit.threeD) out.push({ kind: "not-threeD", name });
1713
+ else {
1714
+ if (same.length > 1) out.push({ kind: "duplicate", name, count: same.length });
1715
+ if (movesZ(hit)) out.push({ kind: "moving", name });
1716
+ }
1717
+ }
1718
+ return out;
1719
+ }
1915
1720
  var CameraSequence = class extends Sequence {
1916
1721
  /** True when `z` is never specified anywhere: z then follows `fov`. */
1917
1722
  autoZ = true;
1918
1723
  compH = 0;
1919
1724
  warnedFov = false;
1920
1725
  warnedLookAt = false;
1726
+ warnedAperture = false;
1727
+ /** True when the camera writes `focus` or `aperture` anywhere: depth of field is on. */
1728
+ dof = false;
1729
+ zOfName = null;
1730
+ layerNames = /* @__PURE__ */ new Set();
1921
1731
  async build() {
1922
1732
  const compW = this.parent?.width ?? this.root.width;
1923
1733
  this.compH = this.parent?.height ?? this.root.height;
@@ -1933,10 +1743,33 @@ var CameraSequence = class extends Sequence {
1933
1743
  carrier.lookAtY = home.lookAtY;
1934
1744
  carrier.lookAtZ = home.lookAtZ;
1935
1745
  carrier.fov = home.fov;
1746
+ carrier.focus = 0;
1747
+ carrier.aperture = DEFAULT_APERTURE;
1936
1748
  carrier.offsetX = carrier.offsetY = carrier.offsetZ = 0;
1937
1749
  carrier.lookOffsetX = carrier.lookOffsetY = carrier.lookOffsetZ = 0;
1938
1750
  this.target = carrier;
1939
- this.autoZ = !collectPropKeys(this.spec).has("z");
1751
+ const keys = chunkBPTW7L25_cjs.collectPropKeys(this.spec);
1752
+ this.autoZ = !keys.has("z");
1753
+ this.dof = keys.has("focus") || keys.has("aperture");
1754
+ }
1755
+ /** The aperture to use now: off unless depth of field is on and the value is a number of 0 or more (said once if it is not). */
1756
+ apertureNow(a) {
1757
+ if (!this.dof) return 0;
1758
+ if (!(a >= 0) && !this.warnedAperture) {
1759
+ this.warnedAperture = true;
1760
+ const who = this.spec.name ? ` "${this.spec.name}"` : "";
1761
+ console.warn(`pixi-effects: camera${who}: aperture ${a} is not a number of 0 or more; depth of field is off (it is the lens diameter in px: 30 is the default, 0 turns it off)`);
1762
+ }
1763
+ return a > 0 ? a : 0;
1764
+ }
1765
+ /** Called by the composition once its children exist: how a layer name in `focus` becomes the z of that layer. */
1766
+ resolveFocusNames(zOf, names = /* @__PURE__ */ new Set()) {
1767
+ this.zOfName = zOf;
1768
+ this.layerNames = names;
1769
+ }
1770
+ displayProps() {
1771
+ const base = super.displayProps();
1772
+ return this.zOfName ? withFocusResolved(base, this.zOfName, this.layerNames) : base;
1940
1773
  }
1941
1774
  /** The camera's state at the current timeline position. */
1942
1775
  state() {
@@ -1960,7 +1793,9 @@ var CameraSequence = class extends Sequence {
1960
1793
  lookAtX: c.lookAtX + c.lookOffsetX,
1961
1794
  lookAtY: c.lookAtY + c.lookOffsetY,
1962
1795
  lookAtZ: c.lookAtZ + c.lookOffsetZ,
1963
- fov
1796
+ fov,
1797
+ focus: Number.isFinite(c.focus) ? c.focus : 0,
1798
+ aperture: this.apertureNow(c.aperture)
1964
1799
  };
1965
1800
  }
1966
1801
  /** Lifespan on the global timeline (valid after bindTimeline). */
@@ -2329,7 +2164,7 @@ function validateGradientKeyframes(spec, who, warn = (m) => console.warn(m), kin
2329
2164
  const p = value;
2330
2165
  for (const k of Object.keys(p)) {
2331
2166
  if (PATCH_KEYS.includes(k)) continue;
2332
- const guess = chunkWTRKDIKH_cjs.suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
2167
+ const guess = chunkUZTKEYFP_cjs.suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
2333
2168
  say(`fillGradient.${k} is not a gradient property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${PATCH_KEYS.join(", ")}); it is ignored`);
2334
2169
  }
2335
2170
  if (p.type !== void 0 && start && p.type !== start.type) say("fillGradient.type cannot change over time (linear <-> radial); it is ignored");
@@ -2537,7 +2372,7 @@ var TextSequence = class extends Sequence {
2537
2372
  this.intrinsicWidth = text.width;
2538
2373
  this.intrinsicHeight = text.height;
2539
2374
  }
2540
- validateGradientKeyframes(this.spec, describeLayer(this.spec), void 0, "text");
2375
+ validateGradientKeyframes(this.spec, chunkBPTW7L25_cjs.describeLayer(this.spec), void 0, "text");
2541
2376
  const gradientSpec = this.spec.fillGradient ?? initialProps.fillGradient;
2542
2377
  if (gradientSpec) {
2543
2378
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -2573,7 +2408,7 @@ var TextSequence = class extends Sequence {
2573
2408
  bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
2574
2409
  this._template = t;
2575
2410
  refresh();
2576
- }, describeLayer(this.spec));
2411
+ }, chunkBPTW7L25_cjs.describeLayer(this.spec));
2577
2412
  }
2578
2413
  };
2579
2414
  function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
@@ -2718,16 +2553,16 @@ var AudioSequence = class extends Sequence {
2718
2553
  const playable = this._remap && this._remap.timeKfs.length > 0 ? Infinity : (data.duration ?? Infinity) / constant;
2719
2554
  if (!spec.loop && Number.isFinite(playable) && this.duration > playable + 0.05) {
2720
2555
  console.warn(
2721
- `pixi-effects: ${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.`
2556
+ `pixi-effects: ${chunkBPTW7L25_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.`
2722
2557
  );
2723
2558
  }
2724
2559
  }
2725
2560
  async _buildSfx(spec) {
2726
- const who = describeLayer(spec);
2561
+ const who = chunkBPTW7L25_cjs.describeLayer(spec);
2727
2562
  const raw = spec;
2728
2563
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
2729
2564
  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)`);
2730
- const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-EX4PUBMV.cjs');
2565
+ const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-2DYTYNYW.cjs');
2731
2566
  const sfx = resolveSfx(spec.sfx, spec.duration, who);
2732
2567
  if (!sfx) return;
2733
2568
  this.duration = sfx.length;
@@ -2742,11 +2577,11 @@ var AudioSequence = class extends Sequence {
2742
2577
  });
2743
2578
  }
2744
2579
  async _buildMusic(spec) {
2745
- const who = describeLayer(spec);
2580
+ const who = chunkBPTW7L25_cjs.describeLayer(spec);
2746
2581
  const raw = spec;
2747
2582
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
2748
2583
  if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
2749
- const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-UAN7DXK4.cjs');
2584
+ const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-GEAH2XCT.cjs');
2750
2585
  const music = resolveMusic(spec.music, who);
2751
2586
  if (!music) return;
2752
2587
  const natural = musicLength(music);
@@ -2776,7 +2611,7 @@ var AudioSequence = class extends Sequence {
2776
2611
  out.push({
2777
2612
  ...sourceMap ? { sourceMap } : {},
2778
2613
  ...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
2779
- layer: describeLayer(this.spec),
2614
+ layer: chunkBPTW7L25_cjs.describeLayer(this.spec),
2780
2615
  source: this._source,
2781
2616
  loop: !this._synth && !!this.spec.loop,
2782
2617
  start: t0,
@@ -2996,7 +2831,7 @@ var VideoSequence = class extends Sequence {
2996
2831
  out.push({
2997
2832
  ...sourceMap ? { sourceMap } : {},
2998
2833
  buffer: this._audioBuffer,
2999
- layer: describeLayer(this.spec),
2834
+ layer: chunkBPTW7L25_cjs.describeLayer(this.spec),
3000
2835
  source: `video "${this.spec.asset}"`,
3001
2836
  loop: !!this.spec.loop,
3002
2837
  start: baseTime + this.at,
@@ -3225,7 +3060,7 @@ function morphAt(pairs, t) {
3225
3060
  }
3226
3061
 
3227
3062
  // src/sequences/Shape.ts
3228
- var STYLE_KEYS2 = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
3063
+ var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
3229
3064
  var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
3230
3065
  var TRIM_KEYS = ["trimStart", "trimEnd"];
3231
3066
  var GEOMETRY_KEYS_BY_SHAPE = {
@@ -3251,7 +3086,7 @@ var ShapeSequence = class extends Sequence {
3251
3086
  // by `Container.onRender`.
3252
3087
  _drawGeometry = () => {
3253
3088
  };
3254
- _liveKeys = new Set(STYLE_KEYS2);
3089
+ _liveKeys = new Set(STYLE_KEYS);
3255
3090
  async build() {
3256
3091
  const graphics = new PIXI.Graphics({ label: this.spec.name });
3257
3092
  graphics.cullable = true;
@@ -3264,20 +3099,20 @@ var ShapeSequence = class extends Sequence {
3264
3099
  for (const k of geomKeys) this._liveKeys.add(k);
3265
3100
  seedGeometry(this._state, this.spec, scope);
3266
3101
  seedStyle(this._state, this.spec.initial ?? {}, scope);
3267
- seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, describeLayer(this.spec));
3102
+ seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunkBPTW7L25_cjs.describeLayer(this.spec));
3268
3103
  if (this.spec.shape === "arc") {
3269
3104
  this._state.startAngle ??= 0;
3270
3105
  this._state.endAngle ??= 360;
3271
3106
  const top = this.spec, ini = this.spec.initial ?? {};
3272
3107
  if ("trimStart" in top || "trimEnd" in top || "trimStart" in ini || "trimEnd" in ini) {
3273
- console.warn(`pixi-effects: ${describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
3108
+ console.warn(`pixi-effects: ${chunkBPTW7L25_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
3274
3109
  }
3275
3110
  } else {
3276
3111
  this._state.trimStart ??= 0;
3277
3112
  this._state.trimEnd ??= 1;
3278
3113
  }
3279
3114
  const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
3280
- validateGradientKeyframes(this.spec, describeLayer(this.spec));
3115
+ validateGradientKeyframes(this.spec, chunkBPTW7L25_cjs.describeLayer(this.spec));
3281
3116
  if (gradientSpec) {
3282
3117
  if (hasGradientKeys(this.spec.keyframes)) {
3283
3118
  this._grad = { grad: gradStateFrom(gradientSpec) };
@@ -3319,9 +3154,9 @@ var ShapeSequence = class extends Sequence {
3319
3154
  }
3320
3155
  /** The prepared morph between `d` and `morphTo`, or null (and a warning when the spec asked for one that cannot work). */
3321
3156
  _setupMorph() {
3322
- const who = describeLayer(this.spec);
3157
+ const who = chunkBPTW7L25_cjs.describeLayer(this.spec);
3323
3158
  const top = this.spec;
3324
- const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || collectPropKeys(this.spec).has("morph"));
3159
+ const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunkBPTW7L25_cjs.collectPropKeys(this.spec).has("morph"));
3325
3160
  if (this.spec.shape !== "path") {
3326
3161
  if ("morphTo" in top) console.warn(`pixi-effects: ${who}: morphTo only works on a path shape (shape: 'path'); ignored`);
3327
3162
  return null;
@@ -3445,7 +3280,7 @@ function seedStrokeStyle(state, spec, initial, who) {
3445
3280
  }
3446
3281
  }
3447
3282
  function seedStyle(state, initial, scope) {
3448
- for (const k of STYLE_KEYS2) {
3283
+ for (const k of STYLE_KEYS) {
3449
3284
  const v = initial[k];
3450
3285
  if (v === void 0) continue;
3451
3286
  state[k] = COLOR_KEYS.has(k) ? v : numOrZero(v, scope);
@@ -3740,7 +3575,7 @@ function numOrZero(v, scope) {
3740
3575
  var _CompositionSequence = null;
3741
3576
  async function getCompositionSequence() {
3742
3577
  if (!_CompositionSequence) {
3743
- _CompositionSequence = (await import('./Composition-LL2XXU5N.cjs')).CompositionSequence;
3578
+ _CompositionSequence = (await import('./Composition-BK5SH6J7.cjs')).CompositionSequence;
3744
3579
  }
3745
3580
  return _CompositionSequence;
3746
3581
  }
@@ -3781,34 +3616,35 @@ async function buildSequenceTree(specs, parent, root) {
3781
3616
  exports.CameraSequence = CameraSequence;
3782
3617
  exports.DEFAULT_FOV = DEFAULT_FOV;
3783
3618
  exports.DEG = DEG;
3619
+ exports.MANY_BLURRED = MANY_BLURRED;
3620
+ exports.MAX_BLUR = MAX_BLUR;
3621
+ exports.MIN_BLUR = MIN_BLUR;
3784
3622
  exports.NEAR = NEAR;
3785
3623
  exports.NullSequence = NullSequence;
3786
3624
  exports.Sequence = Sequence;
3787
3625
  exports.bindClock = bindClock;
3626
+ exports.blurRadius = blurRadius;
3788
3627
  exports.buildScope = buildScope;
3789
3628
  exports.buildSequenceTree = buildSequenceTree;
3790
3629
  exports.cameraBasis = cameraBasis;
3791
3630
  exports.checkEase = checkEase;
3792
3631
  exports.clockTable = clockTable;
3793
- exports.collectPropKeys = collectPropKeys;
3794
3632
  exports.contentLength = contentLength;
3795
- exports.describeLayer = describeLayer;
3796
3633
  exports.ensureFilterLibrary = ensureFilterLibrary;
3797
3634
  exports.evaluateExpr = evaluateExpr;
3798
3635
  exports.flattenSvgPath = flattenSvgPath;
3636
+ exports.focusProblems = focusProblems;
3799
3637
  exports.homeCamera = homeCamera;
3800
3638
  exports.homeDistance = homeDistance;
3801
- exports.lintKeys = lintKeys;
3802
- exports.lintText = lintText;
3803
- exports.lintTiming = lintTiming;
3639
+ exports.layerInitialZ = layerInitialZ;
3804
3640
  exports.noise = noise;
3805
3641
  exports.projectLayer = projectLayer;
3642
+ exports.projectPoint = projectPoint;
3806
3643
  exports.rand = rand;
3807
3644
  exports.random = random;
3808
3645
  exports.registerSequenceType = registerSequenceType;
3809
3646
  exports.remapOf = remapOf;
3810
3647
  exports.resolveAt = resolveAt;
3811
- exports.summarizeWarnings = summarizeWarnings;
3812
3648
  exports.timeRemapOf = timeRemapOf;
3813
- //# sourceMappingURL=chunk-NO26HWR7.cjs.map
3814
- //# sourceMappingURL=chunk-NO26HWR7.cjs.map
3649
+ //# sourceMappingURL=chunk-IFZOI3JQ.cjs.map
3650
+ //# sourceMappingURL=chunk-IFZOI3JQ.cjs.map