pixi-effects 0.7.0 → 0.9.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 (42) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +8 -7
  3. package/ai/SKILL.md +6 -5
  4. package/ai/reference/cheatsheet.md +9 -1
  5. package/ai/template.html +4 -3
  6. package/ai/tools/check.mjs +8 -0
  7. package/dist/Composition-CM62XJKT.cjs +14 -0
  8. package/dist/{Composition-3KHQPRBA.cjs.map → Composition-CM62XJKT.cjs.map} +1 -1
  9. package/dist/Composition-RJDSQYTV.js +5 -0
  10. package/dist/{Composition-DT657FO5.js.map → Composition-RJDSQYTV.js.map} +1 -1
  11. package/dist/Controller.cjs +55 -20
  12. package/dist/Controller.cjs.map +1 -1
  13. package/dist/Controller.d.cts +31 -2
  14. package/dist/Controller.d.ts +31 -2
  15. package/dist/Controller.js +55 -21
  16. package/dist/Controller.js.map +1 -1
  17. package/dist/{Movie-B0OUKlZI.d.ts → Movie-QMlFyHkf.d.ts} +49 -1
  18. package/dist/{Movie-BK9daiTt.d.cts → Movie-qGHp15c_.d.cts} +49 -1
  19. package/dist/{chunk-6I55T4OH.cjs → chunk-AGMNSJJH.cjs} +13 -4
  20. package/dist/chunk-AGMNSJJH.cjs.map +1 -0
  21. package/dist/{chunk-4O2NYDJG.js → chunk-FNKSXBKB.js} +13 -4
  22. package/dist/chunk-FNKSXBKB.js.map +1 -0
  23. package/dist/{chunk-36Z4RIRK.js → chunk-O4AJYUPK.js} +3 -3
  24. package/dist/{chunk-36Z4RIRK.js.map → chunk-O4AJYUPK.js.map} +1 -1
  25. package/dist/{chunk-4VSIJLU3.cjs → chunk-PDBDDGG5.cjs} +21 -21
  26. package/dist/{chunk-4VSIJLU3.cjs.map → chunk-PDBDDGG5.cjs.map} +1 -1
  27. package/dist/index.cjs +141 -26
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +130 -15
  32. package/dist/index.js.map +1 -1
  33. package/dist/three.cjs +5 -5
  34. package/dist/three.js +1 -1
  35. package/docs/api.md +67 -0
  36. package/docs/dsl.md +14 -2
  37. package/llms-full.txt +96 -8
  38. package/package.json +4 -1
  39. package/dist/Composition-3KHQPRBA.cjs +0 -14
  40. package/dist/Composition-DT657FO5.js +0 -5
  41. package/dist/chunk-4O2NYDJG.js.map +0 -1
  42. package/dist/chunk-6I55T4OH.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk4VSIJLU3_cjs = require('./chunk-4VSIJLU3.cjs');
4
- var chunk6I55T4OH_cjs = require('./chunk-6I55T4OH.cjs');
3
+ var chunkPDBDDGG5_cjs = require('./chunk-PDBDDGG5.cjs');
4
+ var chunkAGMNSJJH_cjs = require('./chunk-AGMNSJJH.cjs');
5
5
  var chunkUQBGW5DO_cjs = require('./chunk-UQBGW5DO.cjs');
6
6
  var PIXI = require('pixi.js');
7
7
  var gsap = require('gsap');
@@ -308,6 +308,28 @@ var AUDIO_CODEC_BY_FORMAT = {
308
308
  webm: "opus",
309
309
  mkv: "opus"
310
310
  };
311
+ var AUDIO_PREFERENCE = {
312
+ mp4: ["aac", "opus", "mp3", "flac"],
313
+ mov: ["aac", "mp3"],
314
+ webm: ["opus", "vorbis"],
315
+ mkv: ["opus", "vorbis", "aac", "flac", "mp3"]
316
+ };
317
+ async function chooseAudioCodec(fmt, requested, container, audio, bitrate) {
318
+ const supported = container.getSupportedAudioCodecs?.();
319
+ const preferred = AUDIO_PREFERENCE[fmt].filter((c) => !supported || supported.includes(c));
320
+ const canEncode = (list) => mediabunny.getFirstEncodableAudioCodec(list, { numberOfChannels: audio.numberOfChannels ?? 2, sampleRate: audio.sampleRate, bitrate });
321
+ if (requested) {
322
+ if (await canEncode([requested])) return requested;
323
+ const alt = await canEncode(preferred.filter((c) => c !== requested));
324
+ throw new Error(`pixi-effects: this browser cannot encode "${requested}" audio for ${fmt}` + (alt ? `; "${alt}" would work: render({ format: '${fmt}', audio: { codec: '${alt}' } }), or leave audio.codec out and the best one is chosen.` : "; it has no audio encoder for this format at all (try another browser, or a movie without sound)."));
325
+ }
326
+ const chosen = await canEncode(preferred);
327
+ if (!chosen) throw new Error(`pixi-effects: this browser has no audio encoder for ${fmt} (it tried ${preferred.join(", ")}): try another browser, or render a movie without sound.`);
328
+ if (chosen !== preferred[0]) {
329
+ console.warn(`pixi-effects: this browser cannot encode ${preferred[0].toUpperCase()} audio (Chrome on Linux has no AAC encoder), so the ${fmt} carries ${chosen} instead; current players play it. A webm export needs no AAC.`);
330
+ }
331
+ return chosen;
332
+ }
311
333
  var qualityMap = {
312
334
  "very-low": mediabunny.QUALITY_VERY_LOW,
313
335
  "low": mediabunny.QUALITY_LOW,
@@ -340,8 +362,10 @@ async function exportFrames(movie, options = {}) {
340
362
  bitrate: qualityMap[options.audio?.bitrate ?? "high"] ?? mediabunny.QUALITY_HIGH
341
363
  }
342
364
  };
365
+ const container = makeOutputFormat(opts.format);
366
+ if (movie.audioBuffer) opts.audio.codec = await chooseAudioCodec(fmt, options.audio?.codec, container, movie.audioBuffer, opts.audio.bitrate);
343
367
  const output = new mediabunny.Output({
344
- format: makeOutputFormat(opts.format),
368
+ format: container,
345
369
  target: new mediabunny.BufferTarget()
346
370
  });
347
371
  const canvasSource = new mediabunny.CanvasSource(movie.app.canvas, {
@@ -819,16 +843,16 @@ function expandTransitions(spec) {
819
843
  if (toUses > 1) {
820
844
  throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
821
845
  }
822
- const tStart = chunk6I55T4OH_cjs.resolveAt(t.at, parentDuration);
846
+ const tStart = chunkAGMNSJJH_cjs.resolveAt(t.at, parentDuration);
823
847
  const tEnd = tStart + t.duration;
824
848
  const fromSeq = fromEntry.seq;
825
- const fromStart = chunk6I55T4OH_cjs.resolveAt(fromSeq.at, parentDuration);
849
+ const fromStart = chunkAGMNSJJH_cjs.resolveAt(fromSeq.at, parentDuration);
826
850
  const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
827
851
  if (tStart < fromStart || tEnd > fromEnd) {
828
852
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
829
853
  }
830
854
  const toSeq = toEntry.seq;
831
- const toStart = chunk6I55T4OH_cjs.resolveAt(toSeq.at, parentDuration);
855
+ const toStart = chunkAGMNSJJH_cjs.resolveAt(toSeq.at, parentDuration);
832
856
  const toEnd = toStart + (toSeq.duration ?? parentDuration);
833
857
  if (tStart < toStart || tEnd > toEnd) {
834
858
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
@@ -1168,7 +1192,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1168
1192
  onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
1169
1193
  if (area === 0) onCanvas = "none";
1170
1194
  }
1171
- const keys = chunk6I55T4OH_cjs.collectPropKeys(seq.spec);
1195
+ const keys = chunkAGMNSJJH_cjs.collectPropKeys(seq.spec);
1172
1196
  const moving = parentMoving || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
1173
1197
  const scale = t?.scale;
1174
1198
  const zero = parentZero || !!scale && (scale.x === 0 || scale.y === 0);
@@ -1184,7 +1208,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1184
1208
  const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
1185
1209
  if (group) scene.set(info, group);
1186
1210
  if (zero || seq.showsNothingYet) scaledToNothing.add(info);
1187
- if (seq instanceof chunk4VSIJLU3_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1211
+ if (seq instanceof chunkPDBDDGG5_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1188
1212
  });
1189
1213
  };
1190
1214
  walk2(root, "", false, true);
@@ -1244,10 +1268,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions) {
1244
1268
  const start = parentStart + (seq.at ?? 0);
1245
1269
  const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
1246
1270
  const span = end - start;
1247
- const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunk6I55T4OH_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1271
+ const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkAGMNSJJH_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1248
1272
  const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq) };
1249
1273
  const inner = [];
1250
- const isComp = seq instanceof chunk4VSIJLU3_cjs.CompositionSequence;
1274
+ const isComp = seq instanceof chunkPDBDDGG5_cjs.CompositionSequence;
1251
1275
  if (isComp) walk(seq, start, end, depth + 1, prefix + name + "/", inner, transitions);
1252
1276
  entries.push({ row, inner, groupable: !isComp });
1253
1277
  });
@@ -1425,6 +1449,21 @@ function startWhenRunning(ctx, start, gesture) {
1425
1449
  }
1426
1450
  var GESTURES = ["pointerdown", "mousedown", "touchend", "keydown"];
1427
1451
 
1452
+ // src/core/poster.ts
1453
+ function normalizePoster(poster, duration, frameRate) {
1454
+ if (poster === void 0 || poster === null) return { seconds: null, frame: null };
1455
+ if (typeof poster !== "number" || !Number.isFinite(poster)) {
1456
+ console.warn(`pixi-effects: movie.init({ poster }): ${JSON.stringify(poster)} is not a time in seconds; ignored`);
1457
+ return { seconds: null, frame: null };
1458
+ }
1459
+ let seconds = poster < 0 ? Math.max(0, duration + poster) : poster;
1460
+ if (seconds > duration) {
1461
+ console.warn(`pixi-effects: movie.init({ poster }): the poster time ${poster} s is past the end of the movie (${duration} s); using the last frame`);
1462
+ seconds = duration;
1463
+ }
1464
+ return { seconds, frame: Math.round(seconds * frameRate) };
1465
+ }
1466
+
1428
1467
  // src/core/Movie.ts
1429
1468
  PIXI.extensions.add(PIXI.CullerPlugin);
1430
1469
  gsap.gsap.registerPlugin(PixiPlugin.PixiPlugin);
@@ -1438,6 +1477,13 @@ var Movie = class {
1438
1477
  audioSource = null;
1439
1478
  gainNode = null;
1440
1479
  _cancelAudioStart = null;
1480
+ /** The poster time in seconds (`movie.init({ poster })`), or null. */
1481
+ poster = null;
1482
+ _posterFrame = null;
1483
+ /** The canvas shows the poster picture while the playhead is still at frame 0 (like `<video poster>`): the first seek or play replaces it. */
1484
+ _atPoster = false;
1485
+ /** > 0 while the movie moves its own playhead (playback, render, snapshot, contactSheet): those are not the seeks `seeking` / `seeked` report. */
1486
+ _quiet = 0;
1441
1487
  _volume = 1;
1442
1488
  _muted = false;
1443
1489
  isPlaying = false;
@@ -1479,6 +1525,36 @@ var Movie = class {
1479
1525
  get isReady() {
1480
1526
  return this._initState === "ready";
1481
1527
  }
1528
+ /** The poster time as a frame number, or null. */
1529
+ get posterFrame() {
1530
+ return this._posterFrame;
1531
+ }
1532
+ /** Draw the poster frame on the canvas and leave the playhead where it is (frame 0): the picture before the movie plays. */
1533
+ async _showPoster() {
1534
+ if (this._posterFrame === null || !this.timeline) return;
1535
+ const back = this.currentFrame;
1536
+ this.currentFrame = this._posterFrame;
1537
+ try {
1538
+ this.timeline.time(this._posterFrame / this.frameRate);
1539
+ await this._awaitVideoFrames();
1540
+ this._updateSpace();
1541
+ this._renderNow();
1542
+ } finally {
1543
+ this.currentFrame = back;
1544
+ }
1545
+ this._atPoster = true;
1546
+ }
1547
+ async posterImage(opts = {}) {
1548
+ this._requireReady("posterImage");
1549
+ const back = this.currentFrame, wasAtPoster = this._atPoster;
1550
+ try {
1551
+ return await this.snapshot(this._posterFrame ?? 0, opts);
1552
+ } finally {
1553
+ this.currentFrame = back;
1554
+ if (wasAtPoster) await this._showPoster();
1555
+ else await this._quietly(() => this.gotoFrame(back, true));
1556
+ }
1557
+ }
1482
1558
  _ensureAudioContext() {
1483
1559
  if (!this._audioContext) {
1484
1560
  const Ctx = window.AudioContext ?? window.webkitAudioContext;
@@ -1487,7 +1563,7 @@ var Movie = class {
1487
1563
  return this._audioContext;
1488
1564
  }
1489
1565
  async init(options = {}) {
1490
- chunkUQBGW5DO_cjs.warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition"]);
1566
+ chunkUQBGW5DO_cjs.warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition", "poster"]);
1491
1567
  this._initState = "pending";
1492
1568
  try {
1493
1569
  this.width = options.width ?? 1920;
@@ -1495,6 +1571,9 @@ var Movie = class {
1495
1571
  this.duration = options.duration ?? 10;
1496
1572
  this.frameRate = options.frameRate ?? 30;
1497
1573
  this.totalFrames = Math.round(this.duration * this.frameRate);
1574
+ const poster = normalizePoster(options.poster, this.duration, this.frameRate);
1575
+ this.poster = poster.seconds;
1576
+ this._posterFrame = poster.frame;
1498
1577
  this.background = options.background ?? "#000000";
1499
1578
  this.timeline = gsap.gsap.timeline({ paused: true, defaults: { ease: "none" } });
1500
1579
  this.timeline.add(gsap.gsap.to({}, { duration: this.duration }));
@@ -1531,7 +1610,7 @@ var Movie = class {
1531
1610
  height: options.composition.height ?? this.height,
1532
1611
  duration: options.composition.duration ?? this.duration
1533
1612
  } : void 0;
1534
- await chunk6I55T4OH_cjs.ensureFilterLibrary(seededComposition);
1613
+ await chunkAGMNSJJH_cjs.ensureFilterLibrary(seededComposition);
1535
1614
  const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
1536
1615
  const rootSeqSpec = {
1537
1616
  type: "composition",
@@ -1541,7 +1620,7 @@ var Movie = class {
1541
1620
  ...userComposition
1542
1621
  };
1543
1622
  if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
1544
- const composition = new chunk4VSIJLU3_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
1623
+ const composition = new chunkPDBDDGG5_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
1545
1624
  await composition.build();
1546
1625
  this._rootSequence = composition;
1547
1626
  if (composition.target) root.addChild(composition.target);
@@ -1558,6 +1637,7 @@ var Movie = class {
1558
1637
  this._updateSpace();
1559
1638
  this._renderNow();
1560
1639
  this._initState = "ready";
1640
+ if (this._posterFrame !== null) await this._showPoster();
1561
1641
  this.emit("ready");
1562
1642
  } catch (err) {
1563
1643
  try {
@@ -1565,12 +1645,33 @@ var Movie = class {
1565
1645
  } catch (cleanupErr) {
1566
1646
  console.warn("pixi-effects: cleanup after init failure also threw:", cleanupErr);
1567
1647
  }
1648
+ this._emitError("init", err);
1568
1649
  throw err;
1569
1650
  }
1570
1651
  }
1571
1652
  async gotoFrame(frame, force = false) {
1572
1653
  if (this._initState !== "ready") return;
1573
- if (!force && this.currentFrame === frame) return;
1654
+ if (!force && !this._atPoster && this.currentFrame === frame) return;
1655
+ if (this._quiet > 0) return this._goto(frame);
1656
+ const target = Math.max(0, Math.min(frame, this.totalFrames));
1657
+ this.emit("seeking", { frame: target, totalFrames: this.totalFrames });
1658
+ await this._goto(frame);
1659
+ this.emit("seeked", { frame: this.currentFrame, totalFrames: this.totalFrames });
1660
+ }
1661
+ /** Run `fn` with `seeking` / `seeked` silenced: the movie is moving its own playhead, not answering a seek. */
1662
+ async _quietly(fn) {
1663
+ this._quiet++;
1664
+ try {
1665
+ return await fn();
1666
+ } finally {
1667
+ this._quiet--;
1668
+ }
1669
+ }
1670
+ _emitError(where, error) {
1671
+ this.emit("error", { where, message: error instanceof Error ? error.message : String(error), error });
1672
+ }
1673
+ async _goto(frame) {
1674
+ this._atPoster = false;
1574
1675
  this.currentFrame = Math.max(0, Math.min(frame, this.totalFrames));
1575
1676
  this.timeline.time(this.currentFrame / this.frameRate);
1576
1677
  await this._awaitVideoFrames();
@@ -1592,7 +1693,7 @@ var Movie = class {
1592
1693
  async snapshot(frame = this.currentFrame, opts = {}) {
1593
1694
  chunkUQBGW5DO_cjs.warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as"]);
1594
1695
  this._requireReady("snapshot");
1595
- await this.gotoFrame(clampFrame(frame, this.totalFrames), true);
1696
+ await this._quietly(() => this.gotoFrame(clampFrame(frame, this.totalFrames), true));
1596
1697
  const scale = opts.scale ?? 1;
1597
1698
  const out = document.createElement("canvas");
1598
1699
  out.width = Math.max(1, Math.round(this.width * scale));
@@ -1612,11 +1713,11 @@ var Movie = class {
1612
1713
  const g = sheet.getContext("2d");
1613
1714
  g.fillStyle = "#10131c";
1614
1715
  g.fillRect(0, 0, L.width, L.height);
1615
- const back = this.currentFrame;
1716
+ const back = this.currentFrame, wasAtPoster = this._atPoster;
1616
1717
  try {
1617
1718
  for (let i = 0; i < frames.length; i++) {
1618
1719
  const f = frames[i];
1619
- await this.gotoFrame(f, true);
1720
+ await this._quietly(() => this.gotoFrame(f, true));
1620
1721
  const { x, y } = L.positions[i];
1621
1722
  g.drawImage(this.app.canvas, x, y + LABEL_H, L.cellW, L.cellH);
1622
1723
  g.fillStyle = "#e8ecf8";
@@ -1625,7 +1726,8 @@ var Movie = class {
1625
1726
  g.fillText(`frame ${f} \xB7 ${(f / this.frameRate).toFixed(2)}s`, x + 8, y + LABEL_H / 2);
1626
1727
  }
1627
1728
  } finally {
1628
- await this.gotoFrame(back, true);
1729
+ if (wasAtPoster) await this._showPoster();
1730
+ else await this._quietly(() => this.gotoFrame(back, true));
1629
1731
  }
1630
1732
  return encodeCanvas(sheet, "image/png", opts.as ?? "blob");
1631
1733
  }
@@ -1708,17 +1810,20 @@ var Movie = class {
1708
1810
  const frame = Math.floor(elapsed * this.frameRate);
1709
1811
  if (frame <= this.totalFrames) {
1710
1812
  inFlight = true;
1711
- this.gotoFrame(frame).catch((err) => {
1813
+ this._goto(frame).catch((err) => {
1712
1814
  console.warn("pixi-effects: gotoFrame failed during playback:", err);
1815
+ this._emitError("playback", err);
1713
1816
  }).finally(() => {
1714
1817
  inFlight = false;
1715
1818
  });
1716
1819
  this._raf = requestAnimationFrame(tick);
1717
1820
  } else {
1718
1821
  this.pause();
1719
- this.gotoFrame(this.totalFrames).catch((err) => {
1822
+ this._goto(this.totalFrames).catch((err) => {
1720
1823
  console.warn("pixi-effects: final gotoFrame failed:", err);
1824
+ this._emitError("playback", err);
1721
1825
  });
1826
+ this.emit("ended");
1722
1827
  }
1723
1828
  };
1724
1829
  this._raf = requestAnimationFrame(tick);
@@ -1762,15 +1867,20 @@ var Movie = class {
1762
1867
  if (wasPlaying) this.emit("pause");
1763
1868
  }
1764
1869
  set volume(v) {
1765
- this._volume = Math.max(0, Math.min(1, v));
1870
+ const next = Math.max(0, Math.min(1, v));
1871
+ const changed = next !== this._volume;
1872
+ this._volume = next;
1766
1873
  if (this.gainNode) this.gainNode.gain.value = this._muted ? 0 : this._volume;
1874
+ if (changed) this.emit("volumechange", { volume: this._volume, muted: this._muted });
1767
1875
  }
1768
1876
  get volume() {
1769
1877
  return this._volume;
1770
1878
  }
1771
1879
  set muted(v) {
1880
+ const changed = !!v !== this._muted;
1772
1881
  this._muted = !!v;
1773
1882
  if (this.gainNode) this.gainNode.gain.value = this._muted ? 0 : this._volume;
1883
+ if (changed) this.emit("volumechange", { volume: this._volume, muted: this._muted });
1774
1884
  }
1775
1885
  get muted() {
1776
1886
  return this._muted;
@@ -1781,7 +1891,12 @@ var Movie = class {
1781
1891
  }
1782
1892
  async render(options) {
1783
1893
  chunkUQBGW5DO_cjs.warnUnknownOptions("movie.render()", options, ["format", "video", "audio"]);
1784
- return await exportFrames(this, options);
1894
+ try {
1895
+ return await this._quietly(() => exportFrames(this, options));
1896
+ } catch (err) {
1897
+ this._emitError("render", err);
1898
+ throw err;
1899
+ }
1785
1900
  }
1786
1901
  async destroy() {
1787
1902
  safeRun(() => this.pause());
@@ -2004,17 +2119,17 @@ function orbit(opts) {
2004
2119
  throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
2005
2120
  }
2006
2121
  const [cx, cy] = opts.center ?? [width / 2, height / 2];
2007
- const fixedR = opts.radius ?? chunk6I55T4OH_cjs.homeDistance(height, fov ?? chunk6I55T4OH_cjs.DEFAULT_FOV);
2122
+ const fixedR = opts.radius ?? chunkAGMNSJJH_cjs.homeDistance(height, fov ?? chunkAGMNSJJH_cjs.DEFAULT_FOV);
2008
2123
  const start = opts.start ?? -degrees / 2;
2009
2124
  const steps = Math.max(1, Math.round(duration * stepsPerSecond));
2010
2125
  const easeFn = parseEase(ease);
2011
2126
  const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
2012
2127
  const pos = (i) => {
2013
2128
  const p = i / steps;
2014
- const a = (start + degrees * easeFn(p)) * chunk6I55T4OH_cjs.DEG;
2129
+ const a = (start + degrees * easeFn(p)) * chunkAGMNSJJH_cjs.DEG;
2015
2130
  if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
2016
2131
  const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
2017
- const R = chunk6I55T4OH_cjs.homeDistance(height, f);
2132
+ const R = chunkAGMNSJJH_cjs.homeDistance(height, f);
2018
2133
  return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
2019
2134
  };
2020
2135
  const keyframes = [];
@@ -2063,7 +2178,7 @@ function withFade(spec, opts) {
2063
2178
 
2064
2179
  Object.defineProperty(exports, "registerSequenceType", {
2065
2180
  enumerable: true,
2066
- get: function () { return chunk6I55T4OH_cjs.registerSequenceType; }
2181
+ get: function () { return chunkAGMNSJJH_cjs.registerSequenceType; }
2067
2182
  });
2068
2183
  exports.Movie = Movie;
2069
2184
  exports.kenBurns = kenBurns;