pixi-effects 0.18.0 → 0.19.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 (52) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +6 -6
  3. package/ai/CHAT.md +1 -1
  4. package/ai/SKILL.md +1 -1
  5. package/ai/chat-template.html +4 -4
  6. package/ai/reference/cheatsheet.md +5 -5
  7. package/ai/reference/pitfalls.md +5 -1
  8. package/ai/reference/recipes.md +65 -0
  9. package/ai/template.html +5 -5
  10. package/ai/tools/check.mjs +14 -3
  11. package/dist/{Base-BQUodYZK.d.ts → Base-B4WbUJO2.d.ts} +1 -1
  12. package/dist/{Base-OHqp8qvX.d.cts → Base-i88XXaiP.d.cts} +1 -1
  13. package/dist/Composition-KYNPRWK3.cjs +14 -0
  14. package/dist/{Composition-6JMXWNVV.cjs.map → Composition-KYNPRWK3.cjs.map} +1 -1
  15. package/dist/Composition-QBKEEJBV.js +5 -0
  16. package/dist/{Composition-MLBHYYFF.js.map → Composition-QBKEEJBV.js.map} +1 -1
  17. package/dist/Controller.d.cts +2 -2
  18. package/dist/Controller.d.ts +2 -2
  19. package/dist/{Movie-DlHQ9C02.d.ts → Movie-8IrqL3kO.d.ts} +6 -1
  20. package/dist/{Movie-K2YuVAdg.d.cts → Movie-CpmdNadg.d.cts} +6 -1
  21. package/dist/Presenter.d.cts +2 -2
  22. package/dist/Presenter.d.ts +2 -2
  23. package/dist/{chunk-UXDR3ZDU.js → chunk-B3YB2TNY.js} +4 -3
  24. package/dist/chunk-B3YB2TNY.js.map +1 -0
  25. package/dist/{chunk-JW67MDHQ.cjs → chunk-CTZRFSVU.cjs} +27 -26
  26. package/dist/chunk-CTZRFSVU.cjs.map +1 -0
  27. package/dist/{chunk-ANO5R2E6.cjs → chunk-VTBT6NNE.cjs} +755 -48
  28. package/dist/chunk-VTBT6NNE.cjs.map +1 -0
  29. package/dist/{chunk-SG3Y66FN.js → chunk-YRXTKOV5.js} +757 -51
  30. package/dist/chunk-YRXTKOV5.js.map +1 -0
  31. package/dist/index.cjs +73 -36
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +5 -5
  34. package/dist/index.d.ts +5 -5
  35. package/dist/index.js +50 -13
  36. package/dist/index.js.map +1 -1
  37. package/dist/loader.css +1 -1
  38. package/dist/three.cjs +5 -5
  39. package/dist/three.d.cts +2 -2
  40. package/dist/three.d.ts +2 -2
  41. package/dist/three.js +1 -1
  42. package/dist/{types-SS51lP6O.d.cts → types-bzLJ7aUx.d.cts} +16 -6
  43. package/dist/{types-SS51lP6O.d.ts → types-bzLJ7aUx.d.ts} +16 -6
  44. package/docs/dsl.md +36 -5
  45. package/llms-full.txt +112 -11
  46. package/package.json +1 -1
  47. package/dist/Composition-6JMXWNVV.cjs +0 -14
  48. package/dist/Composition-MLBHYYFF.js +0 -5
  49. package/dist/chunk-ANO5R2E6.cjs.map +0 -1
  50. package/dist/chunk-JW67MDHQ.cjs.map +0 -1
  51. package/dist/chunk-SG3Y66FN.js.map +0 -1
  52. package/dist/chunk-UXDR3ZDU.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- export { A as AudioInspectOptions, a as AudioReport, b as AudioSourceReport, C as ContactSheetOptions, F as FontReport, c as FrameEvent, I as InspectOptions, d as InspectReport, e as IssueGroup, L as LayerInfo, f as LoaderOption, M as MotionBlurOptions, g as MotionBlurSpec, h as Movie, i as MovieErrorEvent, j as MovieOptions, O as OnionSkinOptions, P as ProgressEvent, R as RenderOptions, k as ReviewOptions, l as ReviewReport, S as SnapshotOptions, m as SoundMeasure, n as StopEvent, o as StopImage, p as StopImagesOptions, T as TimelineData, q as TimelineHtmlOptions, r as TimelineRow, s as TimelineSvgOptions, t as TimelineTransition, V as VolumeEvent, u as dismissLoader, v as failLoader, w as resolveLoader } from './Movie-K2YuVAdg.cjs';
2
- import { S as SequenceSpec, C as CompositionShape, I as ImageSequenceSpec, a as CameraSequenceSpec, K as Keyframe, T as TextSequenceSpec, M as MusicOptions, P as Props, b as TransitionSpec, c as CompositionSpec, d as SequenceCommon } from './types-SS51lP6O.cjs';
3
- export { A as ArcShapeSpec, e as AssetSpec, f as AudioAssetSpec, g as AudioMusicSpec, h as AudioSequenceSpec, i as AudioSfxSpec, j as ChromaKeyFilterSpec, k as CircleShapeSpec, l as CompositionSequenceSpec, m as CrossfadeTransition, n as CustomFilterSpec, D as DipTransition, o as DissolveTransition, E as EllipseShapeSpec, p as Expr, F as FilterSpec, G as GradientSpec, q as IrisTransition, L as LineShapeSpec, r as MusicDrum, s as MusicDrums, t as MusicInstrument, u as MusicLevel, v as MusicTrack, N as NullSequenceSpec, w as PathShapeSpec, x as PolygonShapeSpec, y as PropValue, R as RectShapeSpec, z as SfxKnobs, B as SfxOptions, H as SfxPreset, J as SfxVoice, O as ShapeSequenceSpec, Q as SlideTransition, U as Stop, V as StopSpec, W as TransitionCommon, X as VideoSequenceSpec, Y as WipeTransition, Z as ZoomTransition, _ as normalizeStops, $ as pictureStops } from './types-SS51lP6O.cjs';
4
- import { S as Sequence } from './Base-OHqp8qvX.cjs';
1
+ export { A as AudioInspectOptions, a as AudioReport, b as AudioSourceReport, C as ContactSheetOptions, F as FontReport, c as FrameEvent, I as InspectOptions, d as InspectReport, e as IssueGroup, L as LayerInfo, f as LoaderOption, M as MotionBlurOptions, g as MotionBlurSpec, h as Movie, i as MovieErrorEvent, j as MovieOptions, O as OnionSkinOptions, P as ProgressEvent, R as RenderOptions, k as ReviewOptions, l as ReviewReport, S as SnapshotOptions, m as SoundMeasure, n as StopEvent, o as StopImage, p as StopImagesOptions, T as TimelineData, q as TimelineHtmlOptions, r as TimelineRow, s as TimelineSvgOptions, t as TimelineTransition, V as VolumeEvent, u as dismissLoader, v as failLoader, w as resolveLoader } from './Movie-CpmdNadg.cjs';
2
+ import { S as SequenceSpec, C as CompositionShape, I as ImageSequenceSpec, a as CameraSequenceSpec, K as Keyframe, T as TextSequenceSpec, M as MusicOptions, P as Props, b as TransitionSpec, c as CompositionSpec, d as SequenceCommon } from './types-bzLJ7aUx.cjs';
3
+ export { A as ArcShapeSpec, e as AssetSpec, f as AudioAssetSpec, g as AudioMusicSpec, h as AudioSequenceSpec, i as AudioSfxSpec, j as ChromaKeyFilterSpec, k as CircleShapeSpec, l as CompositionSequenceSpec, m as CrossfadeTransition, n as CustomFilterSpec, D as DipTransition, o as DissolveTransition, E as EllipseShapeSpec, p as Expr, F as FilterSpec, G as GradientSpec, q as IrisTransition, L as LineShapeSpec, r as MusicDrum, s as MusicDrums, t as MusicInstrument, u as MusicLevel, v as MusicTrack, N as NullSequenceSpec, w as PathShapeSpec, x as PolygonShapeSpec, y as PropValue, R as RectShapeSpec, z as SfxKnobs, B as SfxOptions, H as SfxPreset, J as SfxVoice, O as ShapeSequenceSpec, Q as SlideTransition, U as Stop, V as StopSpec, W as TransitionCommon, X as VideoSequenceSpec, Y as WipeTransition, Z as ZoomTransition, _ as normalizeStops, $ as pictureStops } from './types-bzLJ7aUx.cjs';
4
+ import { S as Sequence } from './Base-i88XXaiP.cjs';
5
5
  import 'pixi.js';
6
6
  import 'gsap';
7
7
 
@@ -419,7 +419,7 @@ interface AnimateTextOptions {
419
419
  duration: number;
420
420
  /** How a piece arrives: a preset (`'rise'` default, `'drop'`, `'fade'`, `'pop'`, `'zoom'`, `'slide'`, `'spin'`), your own tween, or `false` for none. */
421
421
  in?: TextPreset | AnimateTextTween | false;
422
- /** How a piece leaves, in the same wave (the entrance backwards, eased the other way). Default none. */
422
+ /** How a piece leaves, in the same wave (the entrance backwards, eased the other way). It leaves from the END of the layer (`at + duration`) and has no `at` of its own: to be gone at time T, set `duration` to T − `at`. Default none. */
423
423
  out?: TextPreset | AnimateTextTween | false;
424
424
  /** The wave: see {@link stagger}. Default `{ each: 0.04 }`. */
425
425
  stagger?: StaggerOptions;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { A as AudioInspectOptions, a as AudioReport, b as AudioSourceReport, C as ContactSheetOptions, F as FontReport, c as FrameEvent, I as InspectOptions, d as InspectReport, e as IssueGroup, L as LayerInfo, f as LoaderOption, M as MotionBlurOptions, g as MotionBlurSpec, h as Movie, i as MovieErrorEvent, j as MovieOptions, O as OnionSkinOptions, P as ProgressEvent, R as RenderOptions, k as ReviewOptions, l as ReviewReport, S as SnapshotOptions, m as SoundMeasure, n as StopEvent, o as StopImage, p as StopImagesOptions, T as TimelineData, q as TimelineHtmlOptions, r as TimelineRow, s as TimelineSvgOptions, t as TimelineTransition, V as VolumeEvent, u as dismissLoader, v as failLoader, w as resolveLoader } from './Movie-DlHQ9C02.js';
2
- import { S as SequenceSpec, C as CompositionShape, I as ImageSequenceSpec, a as CameraSequenceSpec, K as Keyframe, T as TextSequenceSpec, M as MusicOptions, P as Props, b as TransitionSpec, c as CompositionSpec, d as SequenceCommon } from './types-SS51lP6O.js';
3
- export { A as ArcShapeSpec, e as AssetSpec, f as AudioAssetSpec, g as AudioMusicSpec, h as AudioSequenceSpec, i as AudioSfxSpec, j as ChromaKeyFilterSpec, k as CircleShapeSpec, l as CompositionSequenceSpec, m as CrossfadeTransition, n as CustomFilterSpec, D as DipTransition, o as DissolveTransition, E as EllipseShapeSpec, p as Expr, F as FilterSpec, G as GradientSpec, q as IrisTransition, L as LineShapeSpec, r as MusicDrum, s as MusicDrums, t as MusicInstrument, u as MusicLevel, v as MusicTrack, N as NullSequenceSpec, w as PathShapeSpec, x as PolygonShapeSpec, y as PropValue, R as RectShapeSpec, z as SfxKnobs, B as SfxOptions, H as SfxPreset, J as SfxVoice, O as ShapeSequenceSpec, Q as SlideTransition, U as Stop, V as StopSpec, W as TransitionCommon, X as VideoSequenceSpec, Y as WipeTransition, Z as ZoomTransition, _ as normalizeStops, $ as pictureStops } from './types-SS51lP6O.js';
4
- import { S as Sequence } from './Base-BQUodYZK.js';
1
+ export { A as AudioInspectOptions, a as AudioReport, b as AudioSourceReport, C as ContactSheetOptions, F as FontReport, c as FrameEvent, I as InspectOptions, d as InspectReport, e as IssueGroup, L as LayerInfo, f as LoaderOption, M as MotionBlurOptions, g as MotionBlurSpec, h as Movie, i as MovieErrorEvent, j as MovieOptions, O as OnionSkinOptions, P as ProgressEvent, R as RenderOptions, k as ReviewOptions, l as ReviewReport, S as SnapshotOptions, m as SoundMeasure, n as StopEvent, o as StopImage, p as StopImagesOptions, T as TimelineData, q as TimelineHtmlOptions, r as TimelineRow, s as TimelineSvgOptions, t as TimelineTransition, V as VolumeEvent, u as dismissLoader, v as failLoader, w as resolveLoader } from './Movie-8IrqL3kO.js';
2
+ import { S as SequenceSpec, C as CompositionShape, I as ImageSequenceSpec, a as CameraSequenceSpec, K as Keyframe, T as TextSequenceSpec, M as MusicOptions, P as Props, b as TransitionSpec, c as CompositionSpec, d as SequenceCommon } from './types-bzLJ7aUx.js';
3
+ export { A as ArcShapeSpec, e as AssetSpec, f as AudioAssetSpec, g as AudioMusicSpec, h as AudioSequenceSpec, i as AudioSfxSpec, j as ChromaKeyFilterSpec, k as CircleShapeSpec, l as CompositionSequenceSpec, m as CrossfadeTransition, n as CustomFilterSpec, D as DipTransition, o as DissolveTransition, E as EllipseShapeSpec, p as Expr, F as FilterSpec, G as GradientSpec, q as IrisTransition, L as LineShapeSpec, r as MusicDrum, s as MusicDrums, t as MusicInstrument, u as MusicLevel, v as MusicTrack, N as NullSequenceSpec, w as PathShapeSpec, x as PolygonShapeSpec, y as PropValue, R as RectShapeSpec, z as SfxKnobs, B as SfxOptions, H as SfxPreset, J as SfxVoice, O as ShapeSequenceSpec, Q as SlideTransition, U as Stop, V as StopSpec, W as TransitionCommon, X as VideoSequenceSpec, Y as WipeTransition, Z as ZoomTransition, _ as normalizeStops, $ as pictureStops } from './types-bzLJ7aUx.js';
4
+ import { S as Sequence } from './Base-B4WbUJO2.js';
5
5
  import 'pixi.js';
6
6
  import 'gsap';
7
7
 
@@ -419,7 +419,7 @@ interface AnimateTextOptions {
419
419
  duration: number;
420
420
  /** How a piece arrives: a preset (`'rise'` default, `'drop'`, `'fade'`, `'pop'`, `'zoom'`, `'slide'`, `'spin'`), your own tween, or `false` for none. */
421
421
  in?: TextPreset | AnimateTextTween | false;
422
- /** How a piece leaves, in the same wave (the entrance backwards, eased the other way). Default none. */
422
+ /** How a piece leaves, in the same wave (the entrance backwards, eased the other way). It leaves from the END of the layer (`at + duration`) and has no `at` of its own: to be gone at time T, set `duration` to T − `at`. Default none. */
423
423
  out?: TextPreset | AnimateTextTween | false;
424
424
  /** The wave: see {@link stagger}. Default `{ each: 0.04 }`. */
425
425
  stagger?: StaggerOptions;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { CompositionSequence } from './chunk-UXDR3ZDU.js';
2
- import { ensureFilterLibrary, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, resolveAt, checkEase, collectPropKeys } from './chunk-SG3Y66FN.js';
3
- export { noise, rand, random, registerSequenceType } from './chunk-SG3Y66FN.js';
1
+ import { CompositionSequence } from './chunk-B3YB2TNY.js';
2
+ import { ensureFilterLibrary, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, rand, DEG, resolveAt, checkEase, collectPropKeys } from './chunk-YRXTKOV5.js';
3
+ export { noise, rand, random, registerSequenceType } from './chunk-YRXTKOV5.js';
4
4
  import { warnUnknownOptions, suggestName } from './chunk-DKGG7WD4.js';
5
5
  import * as PIXI from 'pixi.js';
6
6
  import { extensions, CullerPlugin, Application, Container, Rectangle, Culler, CanvasTextMetrics, TextStyle, Assets, ExtensionType, Filter, UniformGroup, GpuProgram, GlProgram, defaultFilterVert } from 'pixi.js';
@@ -469,6 +469,14 @@ function namedScenes(rows) {
469
469
  return rows.filter((r) => r.depth === 0 && r.type === "composition" && !/[#×]/.test(r.name) && r.end - r.start >= 1).map((r) => ({ name: r.name, start: r.start, end: r.end }));
470
470
  }
471
471
 
472
+ // src/core/timeFilters.ts
473
+ function collectTimeFilters(seq, out = []) {
474
+ for (const f of seq.filters ?? []) if (typeof f.setTime === "function") out.push(f);
475
+ if (seq.maskSequence) collectTimeFilters(seq.maskSequence, out);
476
+ for (const child of seq._children ?? []) collectTimeFilters(child, out);
477
+ return out;
478
+ }
479
+
472
480
  // src/core/review.ts
473
481
  function sampleFrames({ totalFrames, frameRate, scenes = [], step = 0.25, cap = 240 }) {
474
482
  const last = totalFrames;
@@ -2074,6 +2082,15 @@ var Movie = class {
2074
2082
  background = "#000000";
2075
2083
  _audioContext = null;
2076
2084
  _rootSequence = null;
2085
+ /** The filters that take the time of the frame they draw (`grain`), collected once after the build. */
2086
+ _timeFilters = [];
2087
+ /** While a motion-blurred frame is exposed: the frame's own time, so all its sub-frames share one grain frame (and not the playhead's). */
2088
+ _nominalTime = null;
2089
+ _feedTimeFilters() {
2090
+ if (!this._timeFilters.length) return;
2091
+ const t = this._nominalTime ?? this._timeOf(this.currentFrame);
2092
+ for (const f of this._timeFilters) f.setTime(t);
2093
+ }
2077
2094
  _rootContainer = null;
2078
2095
  _raf = null;
2079
2096
  /** What went into the mix, and its peak before limiting — kept for inspectAudio(). */
@@ -2205,6 +2222,7 @@ var Movie = class {
2205
2222
  this._rootSequence = composition;
2206
2223
  if (composition.target) root.addChild(composition.target);
2207
2224
  composition.bindTimeline(this.timeline);
2225
+ this._timeFilters = collectTimeFilters(composition);
2208
2226
  const audios = [];
2209
2227
  composition.collectAudio(audios, 0);
2210
2228
  if (audios.length > 0) {
@@ -2542,6 +2560,7 @@ var Movie = class {
2542
2560
  if (!app?.renderer) return;
2543
2561
  if (!this._synced) this._rootSequence?.syncFrame();
2544
2562
  this._synced = false;
2563
+ this._feedTimeFilters();
2545
2564
  Culler.shared.cull(app.stage, app.renderer.screen, false);
2546
2565
  app.renderer.render({ container: app.stage });
2547
2566
  }
@@ -2558,6 +2577,7 @@ var Movie = class {
2558
2577
  * the frame before (after a jump seek, a card whose children were animated showed a stale picture).
2559
2578
  */
2560
2579
  _updateSpace(t = this._timeOf(this.currentFrame)) {
2580
+ this._feedTimeFilters();
2561
2581
  if (!this._rootSequence || !this.app) return;
2562
2582
  this._rootSequence.syncFrame();
2563
2583
  this._synced = true;
@@ -2576,15 +2596,20 @@ var Movie = class {
2576
2596
  const stage = this.app.canvas;
2577
2597
  this._atPoster = false;
2578
2598
  const times = blurTimes(frame, this.frameRate, mb, Math.max(0, this.duration - END_MARGIN));
2579
- for (let k = 0; k < times.length; k++) {
2580
- const t = times[k];
2581
- this.timeline.time(t);
2582
- await this._awaitVideoFrames(t);
2583
- this._updateSpace(t);
2584
- this._renderNow();
2585
- if (k === 0) g.clearRect(0, 0, target.width, target.height);
2586
- g.globalAlpha = 1 / (k + 1);
2587
- g.drawImage(stage, 0, 0, target.width, target.height);
2599
+ this._nominalTime = this._timeOf(Math.max(0, Math.min(frame, this.totalFrames)));
2600
+ try {
2601
+ for (let k = 0; k < times.length; k++) {
2602
+ const t = times[k];
2603
+ this.timeline.time(t);
2604
+ await this._awaitVideoFrames(t);
2605
+ this._updateSpace(t);
2606
+ this._renderNow();
2607
+ if (k === 0) g.clearRect(0, 0, target.width, target.height);
2608
+ g.globalAlpha = 1 / (k + 1);
2609
+ g.drawImage(stage, 0, 0, target.width, target.height);
2610
+ }
2611
+ } finally {
2612
+ this._nominalTime = null;
2588
2613
  }
2589
2614
  g.globalAlpha = 1;
2590
2615
  if (settle) await this._goto(frame);
@@ -2806,6 +2831,7 @@ var Movie = class {
2806
2831
  }
2807
2832
  async destroy() {
2808
2833
  safeRun(() => this.pause());
2834
+ this._timeFilters = [];
2809
2835
  safeRun(() => this._rootSequence?.destroy());
2810
2836
  this._rootSequence = null;
2811
2837
  safeRun(() => this.timeline?.kill());
@@ -3324,7 +3350,8 @@ function stagger(items, options = {}) {
3324
3350
  const max = dist2.reduce((m, d) => Math.max(m, d), 0);
3325
3351
  const total = amount !== void 0 ? amount : (each ?? 0.1) * max;
3326
3352
  const shape = parseEase(ease);
3327
- const delays = dist2.map((d) => max === 0 ? 0 : Math.round(total * shape(d / max) * 1e6) / 1e6);
3353
+ const clamp01 = (v) => Math.min(1, Math.max(0, v));
3354
+ const delays = dist2.map((d) => max === 0 ? 0 : Math.round(total * clamp01(shape(d / max)) * 1e6) / 1e6);
3328
3355
  if (isCount) return delays;
3329
3356
  return items.map((layer, i) => ({ ...layer, at: Math.round(((layer.at ?? 0) + delays[i]) * 1e6) / 1e6 }));
3330
3357
  }
@@ -3403,6 +3430,8 @@ function wiggle(opts) {
3403
3430
  }
3404
3431
 
3405
3432
  // src/presets/animateText.ts
3433
+ var TWEEN_KEYS = ["preset", "from", "to", "duration", "ease"];
3434
+ var TIME_KEYS = ["at", "delay", "start", "begin", "time"];
3406
3435
  var KEYS5 = ["by", "x", "y", "align", "name", "at", "duration", "in", "out", "stagger", "idle", "styleFor"];
3407
3436
  var PRESETS = {
3408
3437
  rise: { from: { y: 40, alpha: 0 }, duration: 0.5, ease: "back.out(2)" },
@@ -3486,6 +3515,14 @@ function animateText(text, style, options) {
3486
3515
  }
3487
3516
  function resolveTween(spec, which) {
3488
3517
  const t = typeof spec === "string" ? { preset: spec } : spec;
3518
+ if (typeof spec === "object" && spec) {
3519
+ for (const key of Object.keys(spec)) {
3520
+ if (TWEEN_KEYS.includes(key)) continue;
3521
+ if (TIME_KEYS.includes(key)) {
3522
+ console.warn(`pixi-effects: animateText(): ${which}.${key} ("${key}") is ignored: ${which === "out" ? "an out leaves from the END of the layer (at + duration), so to make the text gone at a time T set duration to T \u2212 at" : "the entrance starts when the piece starts (the options' at, plus the stagger)"}`);
3523
+ } else warnUnknownOptions(`animateText() ${which}`, { [key]: 1 }, TWEEN_KEYS);
3524
+ }
3525
+ }
3489
3526
  if (t.preset !== void 0 && !(t.preset in PRESETS)) {
3490
3527
  const guess = suggestName(String(t.preset), PRESET_NAMES);
3491
3528
  throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")})`);