pixi-effects 0.33.0 → 0.35.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 (55) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +5 -5
  3. package/ai/chat-template.html +3 -3
  4. package/dist/Composition-NDXKQHB4.js +7 -0
  5. package/dist/{Composition-7XNPTM7L.js.map → Composition-NDXKQHB4.js.map} +1 -1
  6. package/dist/Composition-OLH7RC5Z.cjs +16 -0
  7. package/dist/{Composition-L6OALWHI.cjs.map → Composition-OLH7RC5Z.cjs.map} +1 -1
  8. package/dist/Controller.cjs +130 -1
  9. package/dist/Controller.cjs.map +1 -1
  10. package/dist/Controller.d.cts +23 -1
  11. package/dist/Controller.d.ts +23 -1
  12. package/dist/Controller.js +130 -1
  13. package/dist/Controller.js.map +1 -1
  14. package/dist/{Movie-CL6SsAWe.d.cts → Movie-Db4QnMIH.d.cts} +24 -1
  15. package/dist/{Movie-f0tQG9y5.d.ts → Movie-VYtUN4TS.d.ts} +24 -1
  16. package/dist/{Spans-KPZ2QDCN.js → Spans-QHHWC2PB.js} +4 -4
  17. package/dist/{Spans-KPZ2QDCN.js.map → Spans-QHHWC2PB.js.map} +1 -1
  18. package/dist/{Spans-VXNQXSI3.cjs → Spans-QRMN2EZO.cjs} +9 -9
  19. package/dist/{Spans-VXNQXSI3.cjs.map → Spans-QRMN2EZO.cjs.map} +1 -1
  20. package/dist/{chunk-WST432AP.js → chunk-2GNK6DPV.js} +88 -10
  21. package/dist/chunk-2GNK6DPV.js.map +1 -0
  22. package/dist/{chunk-SBBXKPBP.cjs → chunk-5IJENZOG.cjs} +62 -62
  23. package/dist/{chunk-SBBXKPBP.cjs.map → chunk-5IJENZOG.cjs.map} +1 -1
  24. package/dist/{chunk-LD4VKNPQ.cjs → chunk-7TTCPHAV.cjs} +120 -42
  25. package/dist/chunk-7TTCPHAV.cjs.map +1 -0
  26. package/dist/{chunk-BVMZUPDU.cjs → chunk-LEECUCTG.cjs} +22 -5
  27. package/dist/chunk-LEECUCTG.cjs.map +1 -0
  28. package/dist/{chunk-BMH4OCDX.js → chunk-XV4L72FW.js} +3 -3
  29. package/dist/{chunk-BMH4OCDX.js.map → chunk-XV4L72FW.js.map} +1 -1
  30. package/dist/{chunk-E53QWHBK.js → chunk-Y253JQOH.js} +22 -5
  31. package/dist/chunk-Y253JQOH.js.map +1 -0
  32. package/dist/index.cjs +31 -31
  33. package/dist/index.d.cts +2 -2
  34. package/dist/index.d.ts +2 -2
  35. package/dist/index.js +3 -3
  36. package/dist/loader.css +1 -1
  37. package/dist/present.cjs +3 -3
  38. package/dist/present.d.cts +1 -1
  39. package/dist/present.d.ts +1 -1
  40. package/dist/present.js +3 -3
  41. package/dist/three.cjs +5 -5
  42. package/dist/three.js +1 -1
  43. package/docs/api.md +10 -0
  44. package/docs/dsl.md +7 -2
  45. package/llms-full.txt +20 -3
  46. package/package.json +1 -1
  47. package/skills/pixi-effects/SKILL.md +1 -1
  48. package/skills/pixi-effects/reference/pitfalls.md +2 -0
  49. package/skills/pixi-effects/template.html +6 -6
  50. package/dist/Composition-7XNPTM7L.js +0 -7
  51. package/dist/Composition-L6OALWHI.cjs +0 -16
  52. package/dist/chunk-BVMZUPDU.cjs.map +0 -1
  53. package/dist/chunk-E53QWHBK.js.map +0 -1
  54. package/dist/chunk-LD4VKNPQ.cjs.map +0 -1
  55. package/dist/chunk-WST432AP.js.map +0 -1
@@ -527,6 +527,12 @@ interface RenderOptions {
527
527
  /** For looking, not for delivering: `scale: 0.5`, `video.bitrate: 'low'` and no motion blur. Anything you set yourself wins. */
528
528
  draft?: boolean;
529
529
  }
530
+ interface ThumbnailOptions {
531
+ /** Width of the picture in px (default 160); the height follows the movie's shape. */
532
+ width?: number;
533
+ /** Instead of `width`: the size relative to the canvas (0 to 4). */
534
+ scale?: number;
535
+ }
530
536
  interface SnapshotOptions {
531
537
  /** Motion blur for this picture (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
532
538
  motionBlur?: MotionBlurSpec;
@@ -665,6 +671,10 @@ declare class Movie {
665
671
  private _silent;
666
672
  /** render() / peek() in flight: a rebuild does not swap the composition under them. */
667
673
  private _busy;
674
+ /** > 0 while the movie is moving its scene to another moment (a seek, a motion-blurred frame, the poster): a thumbnail does not start then. */
675
+ private _moving;
676
+ /** The thumbnail being drawn, if any: a seek waits for it (it has the scene on another moment for a few microtasks). */
677
+ private _thumbRun;
668
678
  private _idleWaiters;
669
679
  /** What went into the mix, and its peak before limiting — kept for inspectAudio(). */
670
680
  private _audioSources;
@@ -763,6 +773,19 @@ declare class Movie {
763
773
  private _frameCanvas;
764
774
  /** Seek to `frame` (quietly, and stay there) and encode the canvas as a picture. */
765
775
  private _captureFrame;
776
+ /**
777
+ * Why `thumbnail()` is off for this movie: `'variables'` (it declares `vars`: the picture depends on them and changes when they do) or `'video'` (a video
778
+ * layer: its frame must be waited for, which would seek the playing video). `null`: it works.
779
+ */
780
+ get thumbnailsOff(): 'variables' | 'video' | null;
781
+ /**
782
+ * A small picture of any frame, drawn WITHOUT moving the playhead or changing what is on the canvas, so it can be made while the movie plays or is
783
+ * paused (a seek-bar preview). The scene is put on that moment, drawn, copied, and put back, all within the microtasks of one task: the browser never
784
+ * shows the in-between. Gives `null` when it cannot be made right now: the movie has thumbnails off (see `thumbnailsOff`), is moving somewhere else
785
+ * (a seek, a render, a peek), or is another thumbnail's turn. It is the picture `snapshot()` gives at that size (without motion blur).
786
+ */
787
+ thumbnail(frame: number, opts?: ThumbnailOptions): Promise<HTMLCanvasElement | null>;
788
+ private _drawThumbnail;
766
789
  /**
767
790
  * One picture of a movement: `count` frames from `from` to `to` drawn one over the other, each later one stronger, so a thing that
768
791
  * moves leaves a trail (its path and its easing: even steps = constant speed, bunched = slow) and what stays still stays itself.
@@ -874,4 +897,4 @@ declare class Movie {
874
897
  destroy(): Promise<void>;
875
898
  }
876
899
 
877
- export { type AudioInspectOptions as A, type TimelineRow as B, type ContactSheetOptions as C, type TimelineSvgOptions as D, type TimelineTransition as E, type FontReport as F, dismissLoader as G, failLoader as H, type InspectOptions as I, resolveLoader as J, type LayerInfo as L, type MusicEvents as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type TimelineData as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type FrameEvent as c, type InspectReport as d, type IssueGroup as e, type LoadProgressState as f, type LoadStage as g, type LoaderOption as h, type LoopEvent as i, type MotionBlurOptions as j, type MotionBlurSpec as k, Movie as l, type MovieErrorEvent as m, type MovieOptions as n, type MusicDrumEvents as o, type MusicDrumHit as p, type MusicNote as q, type MusicSummary as r, type MusicTrackEvents as s, type RebuildReason as t, type RebuildReport as u, type RenderOptions as v, type ReviewOptions as w, type ReviewReport as x, type SoundMeasure as y, type TimelineHtmlOptions as z };
900
+ export { type AudioInspectOptions as A, type TimelineHtmlOptions as B, type ContactSheetOptions as C, type TimelineRow as D, type TimelineSvgOptions as E, type FontReport as F, type TimelineTransition as G, dismissLoader as H, type InspectOptions as I, failLoader as J, resolveLoader as K, type LayerInfo as L, type MusicEvents as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type ThumbnailOptions as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type FrameEvent as c, type InspectReport as d, type IssueGroup as e, type LoadProgressState as f, type LoadStage as g, type LoaderOption as h, type LoopEvent as i, type MotionBlurOptions as j, type MotionBlurSpec as k, Movie as l, type MovieErrorEvent as m, type MovieOptions as n, type MusicDrumEvents as o, type MusicDrumHit as p, type MusicNote as q, type MusicSummary as r, type MusicTrackEvents as s, type RebuildReason as t, type RebuildReport as u, type RenderOptions as v, type ReviewOptions as w, type ReviewReport as x, type SoundMeasure as y, type TimelineData as z };
@@ -1,5 +1,5 @@
1
- import { CompositionSequence } from './chunk-BMH4OCDX.js';
2
- import { spansMeta, resolveNumber, bindCounterKeyframes, TextSequence } from './chunk-E53QWHBK.js';
1
+ import { CompositionSequence } from './chunk-XV4L72FW.js';
2
+ import { spansMeta, resolveNumber, bindCounterKeyframes, TextSequence } from './chunk-Y253JQOH.js';
3
3
  import './chunk-RTJD3ZSW.js';
4
4
  import './chunk-ITDYFBB6.js';
5
5
  import './chunk-BXOCEZ4U.js';
@@ -49,5 +49,5 @@ var SpansSequence = class extends CompositionSequence {
49
49
  };
50
50
 
51
51
  export { SpansSequence };
52
- //# sourceMappingURL=Spans-KPZ2QDCN.js.map
53
- //# sourceMappingURL=Spans-KPZ2QDCN.js.map
52
+ //# sourceMappingURL=Spans-QHHWC2PB.js.map
53
+ //# sourceMappingURL=Spans-QHHWC2PB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sequences/Spans.ts"],"names":[],"mappings":";;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4B,mBAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAI,aAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAA,oBAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiB,YAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-KPZ2QDCN.js","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/sequences/Spans.ts"],"names":[],"mappings":";;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4B,mBAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAI,aAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAA,oBAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiB,YAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-QHHWC2PB.js","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkSBBXKPBP_cjs = require('./chunk-SBBXKPBP.cjs');
4
- var chunkBVMZUPDU_cjs = require('./chunk-BVMZUPDU.cjs');
3
+ var chunk5IJENZOG_cjs = require('./chunk-5IJENZOG.cjs');
4
+ var chunkLEECUCTG_cjs = require('./chunk-LEECUCTG.cjs');
5
5
  require('./chunk-IMQJVRMT.cjs');
6
6
  require('./chunk-GL2AQFLQ.cjs');
7
7
  require('./chunk-TWZNOUM7.cjs');
@@ -12,12 +12,12 @@ var strip = (props) => {
12
12
  const { visibleChars: _gone, ...rest } = props;
13
13
  return rest;
14
14
  };
15
- var SpansSequence = class extends chunkSBBXKPBP_cjs.CompositionSequence {
15
+ var SpansSequence = class extends chunk5IJENZOG_cjs.CompositionSequence {
16
16
  _meta;
17
17
  _count = { value: 0, visibleChars: 0 };
18
18
  constructor(spec, parent, root) {
19
19
  super(spec, parent, root);
20
- this._meta = chunkBVMZUPDU_cjs.spansMeta.get(spec);
20
+ this._meta = chunkLEECUCTG_cjs.spansMeta.get(spec);
21
21
  }
22
22
  /** `visibleChars` is the group's own counter, not a property to write on the container. */
23
23
  displayProps() {
@@ -33,8 +33,8 @@ var SpansSequence = class extends chunkSBBXKPBP_cjs.CompositionSequence {
33
33
  if (!this._meta?.typed) return;
34
34
  const scope = this.scope();
35
35
  const first = this.spec.initial?.visibleChars;
36
- this._count.visibleChars = first === void 0 ? 0 : chunkBVMZUPDU_cjs.resolveNumber(first, scope);
37
- chunkBVMZUPDU_cjs.bindCounterKeyframes(timeline, this._count, "visibleChars", () => this._distribute(), this.spec.keyframes ?? [], this.duration, offset + this.at, scope);
36
+ this._count.visibleChars = first === void 0 ? 0 : chunkLEECUCTG_cjs.resolveNumber(first, scope);
37
+ chunkLEECUCTG_cjs.bindCounterKeyframes(timeline, this._count, "visibleChars", () => this._distribute(), this.spec.keyframes ?? [], this.duration, offset + this.at, scope);
38
38
  this._distribute();
39
39
  }
40
40
  /** Every piece shows its part of the first N characters of the whole text. */
@@ -43,7 +43,7 @@ var SpansSequence = class extends chunkSBBXKPBP_cjs.CompositionSequence {
43
43
  const total = Math.max(0, Math.floor(this._count.visibleChars));
44
44
  let i = 0;
45
45
  for (const child of this._children) {
46
- if (!(child instanceof chunkBVMZUPDU_cjs.TextSequence)) continue;
46
+ if (!(child instanceof chunkLEECUCTG_cjs.TextSequence)) continue;
47
47
  const p = pieces[i++];
48
48
  if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));
49
49
  }
@@ -51,5 +51,5 @@ var SpansSequence = class extends chunkSBBXKPBP_cjs.CompositionSequence {
51
51
  };
52
52
 
53
53
  exports.SpansSequence = SpansSequence;
54
- //# sourceMappingURL=Spans-VXNQXSI3.cjs.map
55
- //# sourceMappingURL=Spans-VXNQXSI3.cjs.map
54
+ //# sourceMappingURL=Spans-QRMN2EZO.cjs.map
55
+ //# sourceMappingURL=Spans-QRMN2EZO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sequences/Spans.ts"],"names":["CompositionSequence","spansMeta","resolveNumber","bindCounterKeyframes","TextSequence"],"mappings":";;;;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4BA,qCAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQC,2BAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAIC,+BAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAAC,sCAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiBC,8BAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-VXNQXSI3.cjs","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/sequences/Spans.ts"],"names":["CompositionSequence","spansMeta","resolveNumber","bindCounterKeyframes","TextSequence"],"mappings":";;;;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4BA,qCAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQC,2BAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAIC,+BAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAAC,sCAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiBC,8BAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-QRMN2EZO.cjs","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { CompositionSequence, maskSourceOf } from './chunk-BMH4OCDX.js';
2
- import { EXPRESSION_NAMES, createTimeline, lengthen, ensureFilterLibrary, checkEase, parseEase, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, timeRemapOf, contentLength, resolveAt, parseSpring, springDuration, spansMeta } from './chunk-E53QWHBK.js';
1
+ import { CompositionSequence, maskSourceOf } from './chunk-XV4L72FW.js';
2
+ import { EXPRESSION_NAMES, createTimeline, lengthen, ensureFilterLibrary, checkEase, parseEase, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, timeRemapOf, contentLength, resolveAt, parseSpring, springDuration, spansMeta } from './chunk-Y253JQOH.js';
3
3
  import { usesAdvancedBlend, enableAdvancedBlend } from './chunk-RTJD3ZSW.js';
4
4
  import { warnUnknownOptions, suggestName } from './chunk-BXOCEZ4U.js';
5
5
  import { extensions, CullerPlugin, Application, Container, Rectangle, Culler, CanvasTextMetrics, TextStyle, Assets, ExtensionType, Filter, Texture, UniformGroup, GpuProgram, GlProgram, defaultFilterVert } from 'pixi.js';
@@ -2643,6 +2643,10 @@ var Movie = class {
2643
2643
  _silent = 0;
2644
2644
  /** render() / peek() in flight: a rebuild does not swap the composition under them. */
2645
2645
  _busy = 0;
2646
+ /** > 0 while the movie is moving its scene to another moment (a seek, a motion-blurred frame, the poster): a thumbnail does not start then. */
2647
+ _moving = 0;
2648
+ /** The thumbnail being drawn, if any: a seek waits for it (it has the scene on another moment for a few microtasks). */
2649
+ _thumbRun = null;
2646
2650
  _idleWaiters = [];
2647
2651
  /** What went into the mix, and its peak before limiting — kept for inspectAudio(). */
2648
2652
  _audioSources = [];
@@ -2690,6 +2694,7 @@ var Movie = class {
2690
2694
  if (this._posterFrame === null || !this.timeline) return;
2691
2695
  const back = this.currentFrame;
2692
2696
  this.currentFrame = this._posterFrame;
2697
+ this._moving++;
2693
2698
  try {
2694
2699
  this.timeline.time(this._timeOf(this._posterFrame));
2695
2700
  await this._awaitVideoFrames();
@@ -2697,6 +2702,7 @@ var Movie = class {
2697
2702
  this._renderNow();
2698
2703
  } finally {
2699
2704
  this.currentFrame = back;
2705
+ this._moving--;
2700
2706
  }
2701
2707
  this._atPoster = true;
2702
2708
  }
@@ -3083,12 +3089,18 @@ var Movie = class {
3083
3089
  this.emit("error", { where, message: error instanceof Error ? error.message : String(error), error });
3084
3090
  }
3085
3091
  async _goto(frame) {
3086
- this._atPoster = false;
3087
- this.currentFrame = Math.max(0, Math.min(frame, this.totalFrames));
3088
- this.timeline.time(this._timeOf(this.currentFrame));
3089
- await this._awaitVideoFrames();
3090
- this._updateSpace();
3091
- this._renderNow();
3092
+ if (this._thumbRun) await this._thumbRun;
3093
+ this._moving++;
3094
+ try {
3095
+ this._atPoster = false;
3096
+ this.currentFrame = Math.max(0, Math.min(frame, this.totalFrames));
3097
+ this.timeline.time(this._timeOf(this.currentFrame));
3098
+ await this._awaitVideoFrames();
3099
+ this._updateSpace();
3100
+ this._renderNow();
3101
+ } finally {
3102
+ this._moving--;
3103
+ }
3092
3104
  this.emit("frame", { frame: this.currentFrame, totalFrames: this.totalFrames });
3093
3105
  }
3094
3106
  /**
@@ -3136,6 +3148,69 @@ var Movie = class {
3136
3148
  if (o.as === "imageData") return out.getContext("2d").getImageData(0, 0, out.width, out.height);
3137
3149
  return encodeCanvas(out, o.type, o.as, o.quality);
3138
3150
  }
3151
+ /**
3152
+ * Why `thumbnail()` is off for this movie: `'variables'` (it declares `vars`: the picture depends on them and changes when they do) or `'video'` (a video
3153
+ * layer: its frame must be waited for, which would seek the playing video). `null`: it works.
3154
+ */
3155
+ get thumbnailsOff() {
3156
+ if (this._declared.size > 0) return "variables";
3157
+ if (!this._rootSequence) return null;
3158
+ const found = [];
3159
+ collectVideoSequences(this._rootSequence, found);
3160
+ return found.some((v) => v.spec?.type === "video") ? "video" : null;
3161
+ }
3162
+ /**
3163
+ * A small picture of any frame, drawn WITHOUT moving the playhead or changing what is on the canvas, so it can be made while the movie plays or is
3164
+ * paused (a seek-bar preview). The scene is put on that moment, drawn, copied, and put back, all within the microtasks of one task: the browser never
3165
+ * shows the in-between. Gives `null` when it cannot be made right now: the movie has thumbnails off (see `thumbnailsOff`), is moving somewhere else
3166
+ * (a seek, a render, a peek), or is another thumbnail's turn. It is the picture `snapshot()` gives at that size (without motion blur).
3167
+ */
3168
+ async thumbnail(frame, opts = {}) {
3169
+ warnUnknownOptions("movie.thumbnail()", opts, ["width", "scale"]);
3170
+ this._requireReady("thumbnail");
3171
+ if (opts.width !== void 0 && !(opts.width > 0 && opts.width <= this.width * 4)) throw new Error(`pixi-effects: movie.thumbnail(): width must be above 0 and at most ${this.width * 4} px, got ${opts.width}`);
3172
+ if (opts.scale !== void 0 && !(opts.scale > 0 && opts.scale <= 4)) throw new Error(`pixi-effects: movie.thumbnail(): scale must be above 0 and at most 4, got ${opts.scale}`);
3173
+ if (this.thumbnailsOff || this._moving > 0 || this._busy > 0 || this._thumbRun) return null;
3174
+ const w = Math.max(1, Math.round(opts.width ?? (opts.scale !== void 0 ? this.width * opts.scale : 160)));
3175
+ const h = Math.max(1, Math.round(w * this.height / this.width));
3176
+ let done;
3177
+ this._thumbRun = new Promise((r) => {
3178
+ done = r;
3179
+ });
3180
+ try {
3181
+ return await this._drawThumbnail(clampFrame(frame, this.totalFrames), w, h);
3182
+ } finally {
3183
+ this._thumbRun = null;
3184
+ done();
3185
+ }
3186
+ }
3187
+ async _drawThumbnail(frame, w, h) {
3188
+ const stage = this.app.canvas;
3189
+ const out = document.createElement("canvas");
3190
+ out.width = w;
3191
+ out.height = h;
3192
+ const keep = this.timeline.time();
3193
+ const t = this._timeOf(frame);
3194
+ this._nominalTime = t;
3195
+ try {
3196
+ this.timeline.time(t);
3197
+ await this._awaitVideoFrames(t);
3198
+ this._updateSpace(t);
3199
+ this._renderNow();
3200
+ out.getContext("2d").drawImage(stage, 0, 0, w, h);
3201
+ } finally {
3202
+ this._nominalTime = keep;
3203
+ try {
3204
+ this.timeline.time(keep);
3205
+ await this._awaitVideoFrames(keep);
3206
+ this._updateSpace(keep);
3207
+ this._renderNow();
3208
+ } finally {
3209
+ this._nominalTime = null;
3210
+ }
3211
+ }
3212
+ return out;
3213
+ }
3139
3214
  async onionSkin(opts = {}) {
3140
3215
  warnUnknownOptions("movie.onionSkin()", opts, ["from", "to", "count", "scale", "as", "motionBlur"]);
3141
3216
  this._requireReady("onionSkin");
@@ -3314,9 +3389,11 @@ var Movie = class {
3314
3389
  async _exposeFrame(frame, mb, target, settle) {
3315
3390
  const g = target.getContext("2d");
3316
3391
  const stage = this.app.canvas;
3392
+ if (this._thumbRun) await this._thumbRun;
3317
3393
  this._atPoster = false;
3318
3394
  const times = blurTimes(frame, this.frameRate, mb, Math.max(0, this.duration - END_MARGIN));
3319
3395
  this._nominalTime = this._timeOf(Math.max(0, Math.min(frame, this.totalFrames)));
3396
+ this._moving++;
3320
3397
  try {
3321
3398
  for (let k = 0; k < times.length; k++) {
3322
3399
  const t = times[k];
@@ -3330,6 +3407,7 @@ var Movie = class {
3330
3407
  }
3331
3408
  } finally {
3332
3409
  this._nominalTime = null;
3410
+ this._moving--;
3333
3411
  }
3334
3412
  g.globalAlpha = 1;
3335
3413
  if (settle) await this._goto(frame);
@@ -4620,5 +4698,5 @@ function withFade(spec, opts) {
4620
4698
  }
4621
4699
 
4622
4700
  export { Movie, animateText, audioEnvelope, bpmEnvelope, cameraPath, computeEnvelope, dismissLoader, failLoader, followPath, kenBurns, measureText, musicBuffer, musicEnvelope, musicEvents, orbit, parseEase2 as parseEase, particles, react, resolveLoader, splitText, stagger, wiggle, withFade };
4623
- //# sourceMappingURL=chunk-WST432AP.js.map
4624
- //# sourceMappingURL=chunk-WST432AP.js.map
4701
+ //# sourceMappingURL=chunk-2GNK6DPV.js.map
4702
+ //# sourceMappingURL=chunk-2GNK6DPV.js.map