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,4 +1,5 @@
1
- import { suggestName, warnUnknownOptions } from './chunk-MNM56B3X.js';
1
+ import { collectPropKeys, describeLayer } from './chunk-E7RONUZ7.js';
2
+ import { suggestName, warnUnknownOptions } from './chunk-NHICCDTC.js';
2
3
  import * as PIXI from 'pixi.js';
3
4
  import { Rectangle, Container, GraphicsPath, Graphics, Assets, Texture, Sprite, FillGradient, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup, Color } from 'pixi.js';
4
5
  import { gsap } from 'gsap';
@@ -1408,267 +1409,6 @@ var NullSequence = class extends Sequence {
1408
1409
  this.buildFilters();
1409
1410
  }
1410
1411
  };
1411
-
1412
- // src/space/specKeys.ts
1413
- function collectPropKeys(spec) {
1414
- const out = /* @__PURE__ */ new Set();
1415
- for (const k of Object.keys(spec.initial ?? {})) out.add(k);
1416
- for (const kf of spec.keyframes ?? []) {
1417
- for (const bag of [kf.set, kf.to, kf.from]) {
1418
- for (const k of Object.keys(bag ?? {})) out.add(k);
1419
- }
1420
- }
1421
- return out;
1422
- }
1423
-
1424
- // src/core/layerKeys.ts
1425
- var COMMON = ["type", "name", "parent", "at", "duration", "initial", "keyframes", "filters", "filterArea", "mask", "maskInverted", "blendMode", "threeD", "hideBehindCamera"];
1426
- var VIDEO = [...COMMON, "asset", "loop", "audio", "volume", "speed"];
1427
- var IMAGE = [...COMMON, "asset", "colorSpace"];
1428
- var TEXT = [...COMMON, "text", "format", "style", "colorSpace", "fillGradient"];
1429
- var AUDIO = [...COMMON, "volume", "asset", "loop", "sfx", "music", "speed"];
1430
- var COMPOSITION = [...COMMON, "width", "height", "sequences", "transitions", "speed"];
1431
- var CAMERA = [...COMMON];
1432
- var NULL = [...COMMON];
1433
- var SHAPE = [...COMMON, "shape", "fillGradient", "colorSpace", "strokeCap", "strokeJoin"];
1434
- var TRIM = ["trimStart", "trimEnd", "trimEach"];
1435
- var RECT = [...SHAPE, ...TRIM, "width", "height", "cornerRadius", "anchorX", "anchorY"];
1436
- var CIRCLE = [...SHAPE, ...TRIM, "radius", "anchorX", "anchorY"];
1437
- var ELLIPSE = [...SHAPE, ...TRIM, "radiusX", "radiusY", "anchorX", "anchorY"];
1438
- var ARC = [...SHAPE, "radius", "innerRadius", "startAngle", "endAngle"];
1439
- var LINE = [...SHAPE, ...TRIM, "from", "to"];
1440
- var POLYGON = [...SHAPE, ...TRIM, "points", "open"];
1441
- var PATH = [...SHAPE, ...TRIM, "d", "morphTo", "morph", "morphPoints"];
1442
- var SHAPES = { rect: RECT, circle: CIRCLE, ellipse: ELLIPSE, arc: ARC, line: LINE, polygon: POLYGON, path: PATH };
1443
- var BY_TYPE = { video: VIDEO, image: IMAGE, text: TEXT, audio: AUDIO, composition: COMPOSITION, camera: CAMERA, null: NULL };
1444
- function kindName(spec) {
1445
- return spec.type === "shape" && spec.shape ? `${spec.shape} shape` : `${spec.type} layer`;
1446
- }
1447
- function layerKeys(spec) {
1448
- if (spec.type === "shape") return spec.shape && SHAPES[spec.shape] || null;
1449
- return BY_TYPE[spec.type] ?? null;
1450
- }
1451
- function kindsWithKey(key) {
1452
- const out = [];
1453
- for (const [shape, keys] of Object.entries(SHAPES)) if (keys.includes(key)) out.push(`${shape} shape`);
1454
- for (const [type, keys] of Object.entries(BY_TYPE)) if (keys.includes(key)) out.push(`${type} layer`);
1455
- return out;
1456
- }
1457
- var PROP_KEYS = /* @__PURE__ */ new Set([
1458
- // transform and look (GSAP + PixiPlugin names)
1459
- "x",
1460
- "y",
1461
- "z",
1462
- "alpha",
1463
- "rotation",
1464
- "rotationX",
1465
- "rotationY",
1466
- "width",
1467
- "height",
1468
- "visible",
1469
- "autoAlpha",
1470
- "scale",
1471
- "scaleX",
1472
- "scaleY",
1473
- "anchor",
1474
- "anchorX",
1475
- "anchorY",
1476
- "pivot",
1477
- "pivotX",
1478
- "pivotY",
1479
- "skew",
1480
- "skewX",
1481
- "skewY",
1482
- "position",
1483
- "positionX",
1484
- "positionY",
1485
- "tint",
1486
- "colorize",
1487
- "colorizeAmount",
1488
- "blur",
1489
- "blurX",
1490
- "blurY",
1491
- "blurPadding",
1492
- // shapes
1493
- "fillColor",
1494
- "fillAlpha",
1495
- "strokeColor",
1496
- "strokeAlpha",
1497
- "strokeWidth",
1498
- "lineColor",
1499
- "lineAlpha",
1500
- "cornerRadius",
1501
- "radius",
1502
- "radiusX",
1503
- "radiusY",
1504
- "innerRadius",
1505
- "startAngle",
1506
- "endAngle",
1507
- "trimStart",
1508
- "trimEnd",
1509
- "trimEach",
1510
- "morph",
1511
- "fillGradient",
1512
- "strokeCap",
1513
- "strokeJoin",
1514
- // text, audio, video
1515
- "fill",
1516
- "value",
1517
- "visibleChars",
1518
- "text",
1519
- "volume",
1520
- "time",
1521
- // camera
1522
- "lookAtX",
1523
- "lookAtY",
1524
- "lookAtZ",
1525
- "fov",
1526
- "offsetX",
1527
- "offsetY",
1528
- "offsetZ",
1529
- "lookOffsetX",
1530
- "lookOffsetY",
1531
- "lookOffsetZ"
1532
- ]);
1533
- var STYLE_KEYS = [
1534
- "fontSize",
1535
- "fontFamily",
1536
- "fontWeight",
1537
- "fontStyle",
1538
- "fontVariant",
1539
- "fill",
1540
- "stroke",
1541
- "dropShadow",
1542
- "letterSpacing",
1543
- "lineHeight",
1544
- "leading",
1545
- "align",
1546
- "wordWrap",
1547
- "wordWrapWidth",
1548
- "breakWords",
1549
- "whiteSpace",
1550
- "padding",
1551
- "textBaseline",
1552
- "trim",
1553
- "lineJoin",
1554
- "miterLimit",
1555
- "filters",
1556
- "tagStyles"
1557
- ];
1558
-
1559
- // src/core/lint.ts
1560
- var defaultWarn = (m) => console.warn(m);
1561
- function describeLayer(spec) {
1562
- return spec.name ? `layer "${spec.name}"` : `unnamed ${spec.type} layer`;
1563
- }
1564
- function lintTiming(spec, parentDuration, warn = defaultWarn) {
1565
- const who = describeLayer(spec);
1566
- const at = spec.at ?? 0;
1567
- if (at >= parentDuration) {
1568
- warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
1569
- }
1570
- if (spec.type === "audio" && (spec.sfx !== void 0 || spec.music !== void 0) && spec.duration === void 0) return;
1571
- const duration = spec.duration ?? parentDuration;
1572
- (spec.keyframes ?? []).forEach((kf, i) => {
1573
- const kat = kf.at ?? 0;
1574
- if (kat >= duration) {
1575
- warn(
1576
- `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.`,
1577
- "late-keyframe"
1578
- );
1579
- }
1580
- });
1581
- }
1582
- function summarizeWarnings(messages, shown = 3) {
1583
- if (messages.length <= shown) return messages;
1584
- 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.`];
1585
- }
1586
- function lintText(spec, warn = defaultWarn) {
1587
- if (spec.type !== "text") return;
1588
- const strings = [spec.text ?? "", ...(spec.keyframes ?? []).map((kf) => String(kf.set?.text ?? ""))];
1589
- const hasPlaceholder = strings.some((t) => t.includes("{value}"));
1590
- if (hasPlaceholder && !collectPropKeys(spec).has("value")) {
1591
- 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}").`);
1592
- }
1593
- if (collectPropKeys(spec).has("value") && !hasPlaceholder) {
1594
- 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').`);
1595
- }
1596
- }
1597
- var REMAPPABLE = /* @__PURE__ */ new Set(["video", "audio", "composition"]);
1598
- var REMAP_NAMES = /* @__PURE__ */ new Set(["time", "timeRemap", "reverse"]);
1599
- var TIME_BAGS = ["set", "to", "from"];
1600
- function lintRemap(spec, warn) {
1601
- const s = spec;
1602
- const who = describeLayer(spec);
1603
- const kfs = s.keyframes ?? [];
1604
- const bags = [s.initial, ...kfs.flatMap((kf) => TIME_BAGS.map((b) => kf[b]))];
1605
- const timeInInitial = !!s.initial && s.initial.time !== void 0;
1606
- const timeInKeyframes = kfs.some((kf) => TIME_BAGS.some((b) => kf[b] && kf[b].time !== void 0));
1607
- const timed = timeInInitial || timeInKeyframes;
1608
- if (bags.some((bag) => bag && bag.speed !== void 0)) {
1609
- 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' }])`);
1610
- }
1611
- if (!REMAPPABLE.has(spec.type)) {
1612
- 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)`);
1613
- return;
1614
- }
1615
- if (s.reverse !== void 0) warn(`pixi-effects: ${who}: "reverse" is not a key: write speed: -1 to play backward`);
1616
- if (s.timeRemap !== void 0) warn(`pixi-effects: ${who}: "timeRemap" is not a key: animate time in keyframes (from / to / set), or write speed`);
1617
- if (s.time !== void 0) warn(`pixi-effects: ${who}: "time" belongs in initial or keyframes (initial: { time: 2 }), not on the layer`);
1618
- if (spec.type === "audio" && (s.sfx !== void 0 || s.music !== void 0) && (s.speed !== void 0 || timed)) {
1619
- 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`);
1620
- return;
1621
- }
1622
- if (s.speed !== void 0 && (typeof s.speed !== "number" || !Number.isFinite(s.speed) || s.speed === 0)) {
1623
- 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`);
1624
- }
1625
- if (s.speed !== void 0 && timeInKeyframes) {
1626
- warn(`pixi-effects: ${who}: speed and keyframed time are both set; time wins and speed is ignored. Use one of them`);
1627
- }
1628
- if (timeInInitial && typeof s.initial.time !== "number") {
1629
- warn(`pixi-effects: ${who}: initial.time must be a number of seconds, got ${JSON.stringify(s.initial.time)}`);
1630
- }
1631
- kfs.forEach((kf, i) => {
1632
- for (const b of TIME_BAGS) {
1633
- const v = kf[b]?.time;
1634
- 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)}`);
1635
- }
1636
- });
1637
- }
1638
- function lintKeys(spec, warn = defaultWarn) {
1639
- const who = describeLayer(spec);
1640
- const valid = layerKeys(spec);
1641
- if (valid) {
1642
- for (const key of Object.keys(spec)) {
1643
- if (valid.includes(key) || spec[key] === void 0) continue;
1644
- if (REMAPPABLE.has(spec.type) && REMAP_NAMES.has(key)) continue;
1645
- const guess = suggestName(key, valid.filter((k) => k !== "type"));
1646
- const owners = kindsWithKey(key);
1647
- const belongs = owners.length ? ` (it belongs to ${owners.slice(0, 3).join(", ")})` : "";
1648
- const hint = guess ? ` \u2014 did you mean "${guess}"?${belongs}` : belongs;
1649
- warn(`pixi-effects: ${who}: "${key}" is not a ${kindName(spec)} key${hint}. Valid keys: ${valid.join(", ")}`);
1650
- }
1651
- }
1652
- lintRemap(spec, warn);
1653
- const said = /* @__PURE__ */ new Set();
1654
- const bags = [spec.initial, ...(spec.keyframes ?? []).flatMap((kf) => [kf.set, kf.to, kf.from])];
1655
- for (const bag of bags) {
1656
- for (const key of Object.keys(bag ?? {})) {
1657
- if (bag[key] === void 0) continue;
1658
- if (PROP_KEYS.has(key) || key.includes(".") || /^gradient/i.test(key) || said.has(key) || key === "speed") continue;
1659
- said.add(key);
1660
- const guess = suggestName(key, [...PROP_KEYS]);
1661
- 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`);
1662
- }
1663
- }
1664
- if (spec.type === "text" && spec.style && typeof spec.style === "object") {
1665
- for (const key of Object.keys(spec.style)) {
1666
- if (STYLE_KEYS.includes(key) || spec.style[key] === void 0) continue;
1667
- const guess = suggestName(key, STYLE_KEYS);
1668
- 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(", ")}`);
1669
- }
1670
- }
1671
- }
1672
1412
  var BAGS = ["set", "to", "from"];
1673
1413
  function timeRemapOf(spec, prop = "time") {
1674
1414
  const hasInitial = !!spec.initial && "time" in spec.initial;
@@ -1891,12 +1631,82 @@ function projectLayer(t, frame, b) {
1891
1631
  const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
1892
1632
  return { corners, depth: origin.depth, visible };
1893
1633
  }
1634
+
1635
+ // src/space/focus.ts
1636
+ var DEFAULT_APERTURE = 30;
1637
+ var MIN_BLUR = 0.05;
1638
+ var MAX_BLUR = 32;
1639
+ var MANY_BLURRED = 20;
1640
+ function blurRadius(aperture, focal, depth, focusDepth) {
1641
+ if (!(aperture > 0) || !(focal > 0) || !(depth > 0) || !(focusDepth > 0)) return 0;
1642
+ const r = aperture * focal * Math.abs(1 / depth - 1 / focusDepth) / 2;
1643
+ return Math.min(r, MAX_BLUR);
1644
+ }
1645
+ var SCOPE_NAMES = /* @__PURE__ */ new Set(["w", "h", "W", "H", "GW", "GH", "contain", "cover", "t", "d", "T"]);
1646
+ function looksLikeLayerName(s) {
1647
+ return /^[A-Za-z_][\w-]*$/.test(s) && !SCOPE_NAMES.has(s);
1648
+ }
1649
+ var isName = (v, known) => typeof v === "string" && (known.has(v) || looksLikeLayerName(v));
1650
+ function focusNames(props, known) {
1651
+ const out = [];
1652
+ const read = (bag) => {
1653
+ const v = bag?.focus;
1654
+ if (isName(v, known)) out.push(v);
1655
+ };
1656
+ read(props.initial);
1657
+ for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from]) read(bag);
1658
+ return out;
1659
+ }
1660
+ function withFocusResolved(props, zOf, known = /* @__PURE__ */ new Set()) {
1661
+ if (focusNames(props, known).length === 0) return props;
1662
+ const fix = (bag) => {
1663
+ const v = bag?.focus;
1664
+ if (!bag || !isName(v, known)) return bag;
1665
+ return { ...bag, focus: zOf(v) ?? 0 };
1666
+ };
1667
+ return {
1668
+ ...props,
1669
+ initial: fix(props.initial),
1670
+ keyframes: props.keyframes?.map((kf) => ({ ...kf, set: fix(kf.set), to: fix(kf.to), from: fix(kf.from) }))
1671
+ };
1672
+ }
1673
+ function layerInitialZ(spec, scope) {
1674
+ const z = spec.initial?.z;
1675
+ if (typeof z === "number") return z;
1676
+ if (typeof z === "string") return evaluateExpr(z, scope);
1677
+ return 0;
1678
+ }
1679
+ var movesZ = (spec) => (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((bag) => bag && "z" in bag));
1680
+ function focusProblems(camera, siblings) {
1681
+ const out = [];
1682
+ const said = /* @__PURE__ */ new Set();
1683
+ const threeD = siblings.filter((s) => s.threeD && s.name).map((s) => s.name);
1684
+ const known = new Set(siblings.map((s) => s.name).filter((n) => !!n));
1685
+ for (const name of focusNames(camera, known)) {
1686
+ if (said.has(name)) continue;
1687
+ said.add(name);
1688
+ const same = siblings.filter((s) => s.name === name);
1689
+ const hit = same.find((s) => s.threeD) ?? same[0];
1690
+ if (!hit) out.push({ kind: "missing", name, hint: suggestName(name, threeD) });
1691
+ else if (!hit.threeD) out.push({ kind: "not-threeD", name });
1692
+ else {
1693
+ if (same.length > 1) out.push({ kind: "duplicate", name, count: same.length });
1694
+ if (movesZ(hit)) out.push({ kind: "moving", name });
1695
+ }
1696
+ }
1697
+ return out;
1698
+ }
1894
1699
  var CameraSequence = class extends Sequence {
1895
1700
  /** True when `z` is never specified anywhere: z then follows `fov`. */
1896
1701
  autoZ = true;
1897
1702
  compH = 0;
1898
1703
  warnedFov = false;
1899
1704
  warnedLookAt = false;
1705
+ warnedAperture = false;
1706
+ /** True when the camera writes `focus` or `aperture` anywhere: depth of field is on. */
1707
+ dof = false;
1708
+ zOfName = null;
1709
+ layerNames = /* @__PURE__ */ new Set();
1900
1710
  async build() {
1901
1711
  const compW = this.parent?.width ?? this.root.width;
1902
1712
  this.compH = this.parent?.height ?? this.root.height;
@@ -1912,10 +1722,33 @@ var CameraSequence = class extends Sequence {
1912
1722
  carrier.lookAtY = home.lookAtY;
1913
1723
  carrier.lookAtZ = home.lookAtZ;
1914
1724
  carrier.fov = home.fov;
1725
+ carrier.focus = 0;
1726
+ carrier.aperture = DEFAULT_APERTURE;
1915
1727
  carrier.offsetX = carrier.offsetY = carrier.offsetZ = 0;
1916
1728
  carrier.lookOffsetX = carrier.lookOffsetY = carrier.lookOffsetZ = 0;
1917
1729
  this.target = carrier;
1918
- this.autoZ = !collectPropKeys(this.spec).has("z");
1730
+ const keys = collectPropKeys(this.spec);
1731
+ this.autoZ = !keys.has("z");
1732
+ this.dof = keys.has("focus") || keys.has("aperture");
1733
+ }
1734
+ /** 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). */
1735
+ apertureNow(a) {
1736
+ if (!this.dof) return 0;
1737
+ if (!(a >= 0) && !this.warnedAperture) {
1738
+ this.warnedAperture = true;
1739
+ const who = this.spec.name ? ` "${this.spec.name}"` : "";
1740
+ 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)`);
1741
+ }
1742
+ return a > 0 ? a : 0;
1743
+ }
1744
+ /** Called by the composition once its children exist: how a layer name in `focus` becomes the z of that layer. */
1745
+ resolveFocusNames(zOf, names = /* @__PURE__ */ new Set()) {
1746
+ this.zOfName = zOf;
1747
+ this.layerNames = names;
1748
+ }
1749
+ displayProps() {
1750
+ const base = super.displayProps();
1751
+ return this.zOfName ? withFocusResolved(base, this.zOfName, this.layerNames) : base;
1919
1752
  }
1920
1753
  /** The camera's state at the current timeline position. */
1921
1754
  state() {
@@ -1939,7 +1772,9 @@ var CameraSequence = class extends Sequence {
1939
1772
  lookAtX: c.lookAtX + c.lookOffsetX,
1940
1773
  lookAtY: c.lookAtY + c.lookOffsetY,
1941
1774
  lookAtZ: c.lookAtZ + c.lookOffsetZ,
1942
- fov
1775
+ fov,
1776
+ focus: Number.isFinite(c.focus) ? c.focus : 0,
1777
+ aperture: this.apertureNow(c.aperture)
1943
1778
  };
1944
1779
  }
1945
1780
  /** Lifespan on the global timeline (valid after bindTimeline). */
@@ -2706,7 +2541,7 @@ var AudioSequence = class extends Sequence {
2706
2541
  const raw = spec;
2707
2542
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
2708
2543
  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)`);
2709
- const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-U3GM2MED.js');
2544
+ const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-3IDAJ3UZ.js');
2710
2545
  const sfx = resolveSfx(spec.sfx, spec.duration, who);
2711
2546
  if (!sfx) return;
2712
2547
  this.duration = sfx.length;
@@ -2725,7 +2560,7 @@ var AudioSequence = class extends Sequence {
2725
2560
  const raw = spec;
2726
2561
  if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
2727
2562
  if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
2728
- const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-CFEC7HKL.js');
2563
+ const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-FUN7N225.js');
2729
2564
  const music = resolveMusic(spec.music, who);
2730
2565
  if (!music) return;
2731
2566
  const natural = musicLength(music);
@@ -3204,7 +3039,7 @@ function morphAt(pairs, t) {
3204
3039
  }
3205
3040
 
3206
3041
  // src/sequences/Shape.ts
3207
- var STYLE_KEYS2 = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
3042
+ var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
3208
3043
  var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
3209
3044
  var TRIM_KEYS = ["trimStart", "trimEnd"];
3210
3045
  var GEOMETRY_KEYS_BY_SHAPE = {
@@ -3230,7 +3065,7 @@ var ShapeSequence = class extends Sequence {
3230
3065
  // by `Container.onRender`.
3231
3066
  _drawGeometry = () => {
3232
3067
  };
3233
- _liveKeys = new Set(STYLE_KEYS2);
3068
+ _liveKeys = new Set(STYLE_KEYS);
3234
3069
  async build() {
3235
3070
  const graphics = new Graphics({ label: this.spec.name });
3236
3071
  graphics.cullable = true;
@@ -3424,7 +3259,7 @@ function seedStrokeStyle(state, spec, initial, who) {
3424
3259
  }
3425
3260
  }
3426
3261
  function seedStyle(state, initial, scope) {
3427
- for (const k of STYLE_KEYS2) {
3262
+ for (const k of STYLE_KEYS) {
3428
3263
  const v = initial[k];
3429
3264
  if (v === void 0) continue;
3430
3265
  state[k] = COLOR_KEYS.has(k) ? v : numOrZero(v, scope);
@@ -3719,7 +3554,7 @@ function numOrZero(v, scope) {
3719
3554
  var _CompositionSequence = null;
3720
3555
  async function getCompositionSequence() {
3721
3556
  if (!_CompositionSequence) {
3722
- _CompositionSequence = (await import('./Composition-6PA4C4TV.js')).CompositionSequence;
3557
+ _CompositionSequence = (await import('./Composition-Q5TVG3HM.js')).CompositionSequence;
3723
3558
  }
3724
3559
  return _CompositionSequence;
3725
3560
  }
@@ -3757,6 +3592,6 @@ async function buildSequenceTree(specs, parent, root) {
3757
3592
  return out;
3758
3593
  }
3759
3594
 
3760
- export { CameraSequence, DEFAULT_FOV, DEG, NEAR, NullSequence, Sequence, bindClock, buildScope, buildSequenceTree, cameraBasis, checkEase, clockTable, collectPropKeys, contentLength, describeLayer, ensureFilterLibrary, evaluateExpr, flattenSvgPath, homeCamera, homeDistance, lintKeys, lintText, lintTiming, noise, projectLayer, rand, random, registerSequenceType, remapOf, resolveAt, summarizeWarnings, timeRemapOf };
3761
- //# sourceMappingURL=chunk-DQHXVNOI.js.map
3762
- //# sourceMappingURL=chunk-DQHXVNOI.js.map
3595
+ export { CameraSequence, DEFAULT_FOV, DEG, MANY_BLURRED, MAX_BLUR, MIN_BLUR, NEAR, NullSequence, Sequence, bindClock, blurRadius, buildScope, buildSequenceTree, cameraBasis, checkEase, clockTable, contentLength, ensureFilterLibrary, evaluateExpr, flattenSvgPath, focusProblems, homeCamera, homeDistance, layerInitialZ, noise, projectLayer, projectPoint, rand, random, registerSequenceType, remapOf, resolveAt, timeRemapOf };
3596
+ //# sourceMappingURL=chunk-DC4JPY6A.js.map
3597
+ //# sourceMappingURL=chunk-DC4JPY6A.js.map