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 +1 @@
1
- {"version":3,"sources":["../src/three/ThreeSequence.ts","../src/three/index.ts"],"names":["Sequence","buildScope","WebGLRenderer","Scene","PerspectiveCamera","Texture","Sprite","evaluateExpr","registerSequenceType"],"mappings":"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","file":"three.cjs","sourcesContent":["import { Sprite, Texture } from 'pixi.js';\nimport { PerspectiveCamera, Scene, WebGLRenderer, type Camera } from 'three';\nimport { Sequence } from '../sequences/Base';\nimport { buildScope } from '../expr/Scope';\nimport { evaluateExpr } from '../expr/Parser';\nimport type { PathRouters } from '../core/Timeline';\nimport type { PropValue } from '../types';\nimport type { ThreeContext, ThreeSequenceSpec } from './types';\n\nexport class ThreeSequence extends Sequence {\n private _renderer: WebGLRenderer | null = null;\n private _scene: Scene | null = null;\n private _camera: Camera | null = null;\n private _ctx: ThreeContext | null = null;\n private _objects: Record<string, object> = {};\n private _warnedUpdate = false;\n private _warnedPaths = new Set<string>();\n\n private get _threeSpec(): ThreeSequenceSpec {\n return this.spec as unknown as ThreeSequenceSpec;\n }\n\n protected override pathRouters(): PathRouters {\n return { three: (path) => this._resolveThreePath(path) };\n }\n\n async build(): Promise<void> {\n const spec = this._threeSpec;\n if (this.duration === undefined) {\n this.duration = this.parent?.duration ?? this.root.duration;\n }\n\n // Resolve layer size. Expressions see the usual scope; intrinsic w/h are\n // still 0 here (same chicken-and-egg as shapes), so W/H/GW/GH carry it.\n const scope = buildScope(this, this.parent, this.root) as unknown as Record<string, number>;\n const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;\n const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;\n const resolution = spec.resolution ?? 1;\n\n // Offscreen canvas — never attached to the DOM. document.createElement\n // (not OffscreenCanvas) so PIXI's Texture.from and three both accept it.\n const canvas = document.createElement('canvas');\n const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: true });\n this._renderer = renderer;\n try {\n renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);\n renderer.setClearColor(0x000000, 0);\n\n const scene = new Scene();\n const camera: Camera = new PerspectiveCamera(50, width / height, 0.1, 2000);\n const ctx: ThreeContext = { scene, camera, renderer, width, height };\n\n const result = await spec.setup(ctx);\n if (result?.camera) ctx.camera = result.camera;\n this._scene = scene;\n this._camera = ctx.camera;\n this._ctx = ctx;\n this._objects = { ...(result?.objects ?? {}) };\n if (!('camera' in this._objects)) this._objects.camera = this._camera;\n\n // Frame 0 so the texture is never blank before the first tick.\n renderer.render(scene, this._camera);\n\n const texture = Texture.from(canvas);\n const sprite = new Sprite({ texture, label: spec.name });\n sprite.cullable = true;\n // Texture is canvas-sized (layer px × resolution); scale back to comp px.\n sprite.width = width;\n sprite.height = height;\n this.target = sprite;\n this.intrinsicWidth = width;\n this.intrinsicHeight = height;\n this.buildFilters();\n } catch (err) {\n this._disposeRenderer();\n throw err;\n }\n }\n\n /**\n * Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method\n * (same contract as VideoSequence) and awaits it inside gotoFrame — the\n * single frame path shared by playback and export, which is what makes\n * three layers deterministic in both.\n */\n async awaitFrameAt(local: number): Promise<void> {\n if (!this._renderer || !this._scene || !this._camera || !this._ctx) return;\n const spec = this._threeSpec;\n const t = Math.max(0, Math.min(local, this.duration ?? local));\n if (spec.update) {\n try {\n spec.update(t, this._ctx);\n } catch (err) {\n if (!this._warnedUpdate) {\n this._warnedUpdate = true;\n console.warn('pixi-effects: three update() threw (reported once) —', err);\n }\n }\n }\n this._renderer.render(this._scene, this._camera);\n (this.target as Sprite | null)?.texture.source.update();\n }\n\n private _resolveThreePath(path: string): { target: object; prop: string } | null {\n const segs = path.split('.');\n if (segs.length < 2) {\n this._warnPath(path, 'needs at least <object>.<prop>');\n return null;\n }\n let obj: unknown = this._objects[segs[0]!];\n if (obj == null) {\n this._warnPath(path, `unknown object \"${segs[0]}\" — expose it via setup's { objects }`);\n return null;\n }\n for (let i = 1; i < segs.length - 1; i++) {\n obj = (obj as Record<string, unknown>)[segs[i]!];\n if (obj == null) {\n this._warnPath(path, `\"${segs[i]}\" is undefined along the path`);\n return null;\n }\n }\n const prop = segs[segs.length - 1]!;\n if (typeof obj !== 'object' || !(prop in (obj as object))) {\n this._warnPath(path, `no property \"${prop}\"`);\n return null;\n }\n return { target: obj as object, prop };\n }\n\n private _warnPath(path: string, why: string): void {\n if (this._warnedPaths.has(path)) return;\n this._warnedPaths.add(path);\n console.warn(`pixi-effects: keyframe path three.${path} ${why}; skipped`);\n }\n\n private _disposeRenderer(): void {\n if (!this._renderer) return;\n try {\n this._renderer.dispose();\n this._renderer.forceContextLoss();\n } catch (err) {\n console.warn('pixi-effects: three renderer dispose threw —', err);\n }\n this._renderer = null;\n }\n\n override destroy(): void {\n const spec = this._threeSpec;\n if (this._ctx && spec.dispose) {\n try { spec.dispose(this._ctx); } catch (err) {\n console.warn('pixi-effects: three dispose() threw —', err);\n }\n }\n const texture = (this.target as Sprite | null)?.texture;\n this._disposeRenderer();\n this._scene = null;\n this._camera = null;\n this._ctx = null;\n this._objects = {};\n super.destroy();\n texture?.destroy(true); // canvas-backed source is per-sequence; safe to kill\n }\n}\n\nfunction resolveDim(v: PropValue | undefined, scope: Record<string, number>): number | undefined {\n if (v === undefined) return undefined;\n if (typeof v === 'number') return v;\n return evaluateExpr(v, scope);\n}\n","/**\n * pixi-effects/three — optional three.js integration.\n *\n * Import this entry only when you use `type: 'three'` sequences; the core\n * `pixi-effects` entry never touches three.js. Call `registerThree()` once\n * before Movie.init builds a composition containing a three sequence.\n */\nimport { registerSequenceType, type SequenceCtor } from '../core/Composition';\nimport { ThreeSequence } from './ThreeSequence';\nimport type { SequenceSpec } from '../types';\nimport type { ThreeSequenceSpec } from './types';\n\nexport { ThreeSequence } from './ThreeSequence';\nexport type { ThreeContext, ThreeSetupResult, ThreeSequenceSpec } from './types';\n\n/** Register the 'three' sequence type. Idempotent; explicit call so `sideEffects: false` bundlers can't drop it. */\nexport function registerThree(): void {\n registerSequenceType('three', ThreeSequence as unknown as SequenceCtor);\n}\n\n/**\n * Typing helper: accepts a strongly-typed three spec and returns it as a\n * core SequenceSpec, keeping three.js types out of the core union.\n */\nexport function three(spec: ThreeSequenceSpec): SequenceSpec {\n return spec as unknown as SequenceSpec;\n}\n"]}
1
+ {"version":3,"sources":["../src/three/ThreeSequence.ts","../src/three/index.ts"],"names":["Sequence","buildScope","WebGLRenderer","Scene","PerspectiveCamera","Texture","Sprite","evaluateExpr","registerSequenceType"],"mappings":"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","file":"three.cjs","sourcesContent":["import { Sprite, Texture } from 'pixi.js';\nimport { PerspectiveCamera, Scene, WebGLRenderer, type Camera } from 'three';\nimport { Sequence } from '../sequences/Base';\nimport { buildScope } from '../expr/Scope';\nimport { evaluateExpr } from '../expr/Parser';\nimport type { PathRouters } from '../core/Timeline';\nimport type { PropValue } from '../types';\nimport type { ThreeContext, ThreeSequenceSpec } from './types';\n\nexport class ThreeSequence extends Sequence {\n private _renderer: WebGLRenderer | null = null;\n private _scene: Scene | null = null;\n private _camera: Camera | null = null;\n private _ctx: ThreeContext | null = null;\n private _objects: Record<string, object> = {};\n private _warnedUpdate = false;\n private _warnedPaths = new Set<string>();\n\n private get _threeSpec(): ThreeSequenceSpec {\n return this.spec as unknown as ThreeSequenceSpec;\n }\n\n protected override pathRouters(): PathRouters {\n return { three: (path) => this._resolveThreePath(path) };\n }\n\n async build(): Promise<void> {\n const spec = this._threeSpec;\n if (this.duration === undefined) {\n this.duration = this.parent?.duration ?? this.root.duration;\n }\n\n // Resolve layer size. Expressions see the usual scope; intrinsic w/h are\n // still 0 here (same chicken-and-egg as shapes), so W/H/GW/GH carry it.\n const scope = buildScope(this, this.parent, this.root) as unknown as Record<string, number>;\n const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;\n const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;\n const resolution = spec.resolution ?? 1;\n\n // Offscreen canvas — never attached to the DOM. document.createElement\n // (not OffscreenCanvas) so PIXI's Texture.from and three both accept it.\n const canvas = document.createElement('canvas');\n const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: true });\n this._renderer = renderer;\n try {\n renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);\n renderer.setClearColor(0x000000, 0);\n\n const scene = new Scene();\n const camera: Camera = new PerspectiveCamera(50, width / height, 0.1, 2000);\n const ctx: ThreeContext = { scene, camera, renderer, width, height };\n\n const result = await spec.setup(ctx);\n if (result?.camera) ctx.camera = result.camera;\n this._scene = scene;\n this._camera = ctx.camera;\n this._ctx = ctx;\n this._objects = { ...(result?.objects ?? {}) };\n if (!('camera' in this._objects)) this._objects.camera = this._camera;\n\n // Frame 0 so the texture is never blank before the first tick.\n renderer.render(scene, this._camera);\n\n const texture = Texture.from(canvas);\n const sprite = new Sprite({ texture, label: spec.name });\n sprite.cullable = true;\n // Texture is canvas-sized (layer px × resolution); scale back to comp px.\n sprite.width = width;\n sprite.height = height;\n this.target = sprite;\n this.intrinsicWidth = width;\n this.intrinsicHeight = height;\n this.buildFilters();\n } catch (err) {\n this._disposeRenderer();\n throw err;\n }\n }\n\n /**\n * Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method\n * (same contract as VideoSequence) and awaits it inside gotoFrame — the\n * single frame path shared by playback and export, which is what makes\n * three layers deterministic in both.\n */\n async awaitFrameAt(local: number): Promise<void> {\n if (!this._renderer || !this._scene || !this._camera || !this._ctx) return;\n const spec = this._threeSpec;\n const t = Math.max(0, Math.min(local, this.duration ?? local));\n if (spec.update) {\n try {\n spec.update(t, this._ctx);\n } catch (err) {\n if (!this._warnedUpdate) {\n this._warnedUpdate = true;\n console.warn('pixi-effects: three update() threw (reported once) —', err);\n }\n }\n }\n this._renderer.render(this._scene, this._camera);\n (this.target as Sprite | null)?.texture.source.update();\n }\n\n private _resolveThreePath(path: string): { target: object; prop: string } | null {\n const segs = path.split('.');\n if (segs.length < 2) {\n this._warnPath(path, 'needs at least <object>.<prop>');\n return null;\n }\n let obj: unknown = this._objects[segs[0]!];\n if (obj == null) {\n this._warnPath(path, `unknown object \"${segs[0]}\" — expose it via setup's { objects }`);\n return null;\n }\n for (let i = 1; i < segs.length - 1; i++) {\n obj = (obj as Record<string, unknown>)[segs[i]!];\n if (obj == null) {\n this._warnPath(path, `\"${segs[i]}\" is undefined along the path`);\n return null;\n }\n }\n const prop = segs[segs.length - 1]!;\n if (typeof obj !== 'object' || !(prop in (obj as object))) {\n this._warnPath(path, `no property \"${prop}\"`);\n return null;\n }\n return { target: obj as object, prop };\n }\n\n private _warnPath(path: string, why: string): void {\n if (this._warnedPaths.has(path)) return;\n this._warnedPaths.add(path);\n console.warn(`pixi-effects: keyframe path three.${path} ${why}; skipped`);\n }\n\n private _disposeRenderer(): void {\n if (!this._renderer) return;\n try {\n this._renderer.dispose();\n this._renderer.forceContextLoss();\n } catch (err) {\n console.warn('pixi-effects: three renderer dispose threw —', err);\n }\n this._renderer = null;\n }\n\n override destroy(): void {\n const spec = this._threeSpec;\n if (this._ctx && spec.dispose) {\n try { spec.dispose(this._ctx); } catch (err) {\n console.warn('pixi-effects: three dispose() threw —', err);\n }\n }\n const texture = (this.target as Sprite | null)?.texture;\n this._disposeRenderer();\n this._scene = null;\n this._camera = null;\n this._ctx = null;\n this._objects = {};\n super.destroy();\n texture?.destroy(true); // canvas-backed source is per-sequence; safe to kill\n }\n}\n\nfunction resolveDim(v: PropValue | undefined, scope: Record<string, number>): number | undefined {\n if (v === undefined) return undefined;\n if (typeof v === 'number') return v;\n return evaluateExpr(v, scope);\n}\n","/**\n * pixi-effects/three — optional three.js integration.\n *\n * Import this entry only when you use `type: 'three'` sequences; the core\n * `pixi-effects` entry never touches three.js. Call `registerThree()` once\n * before Movie.init builds a composition containing a three sequence.\n */\nimport { registerSequenceType, type SequenceCtor } from '../core/Composition';\nimport { ThreeSequence } from './ThreeSequence';\nimport type { SequenceSpec } from '../types';\nimport type { ThreeSequenceSpec } from './types';\n\nexport { ThreeSequence } from './ThreeSequence';\nexport type { ThreeContext, ThreeSetupResult, ThreeSequenceSpec } from './types';\n\n/** Register the 'three' sequence type. Idempotent; explicit call so `sideEffects: false` bundlers can't drop it. */\nexport function registerThree(): void {\n registerSequenceType('three', ThreeSequence as unknown as SequenceCtor);\n}\n\n/**\n * Typing helper: accepts a strongly-typed three spec and returns it as a\n * core SequenceSpec, keeping three.js types out of the core union.\n */\nexport function three(spec: ThreeSequenceSpec): SequenceSpec {\n return spec as unknown as SequenceSpec;\n}\n"]}
package/dist/three.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { d as SequenceCommon, y as PropValue, S as SequenceSpec } from './types-YmUaViL1.cjs';
1
+ import { d as SequenceCommon, y as PropValue, S as SequenceSpec } from './types-DBbZVKGS.cjs';
2
2
  import { Scene, Camera, WebGLRenderer } from 'three';
3
- import { S as Sequence, P as PathRouters } from './Base-wYJQ2g5Q.cjs';
3
+ import { S as Sequence, P as PathRouters } from './Base-BzlPgd-D.cjs';
4
4
  import 'pixi.js';
5
5
  import 'gsap';
6
6
 
package/dist/three.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { d as SequenceCommon, y as PropValue, S as SequenceSpec } from './types-YmUaViL1.js';
1
+ import { d as SequenceCommon, y as PropValue, S as SequenceSpec } from './types-DBbZVKGS.js';
2
2
  import { Scene, Camera, WebGLRenderer } from 'three';
3
- import { S as Sequence, P as PathRouters } from './Base-CzfLGoDr.js';
3
+ import { S as Sequence, P as PathRouters } from './Base-gu-5X0Cv.js';
4
4
  import 'pixi.js';
5
5
  import 'gsap';
6
6
 
package/dist/three.js CHANGED
@@ -1,5 +1,6 @@
1
- import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-DQHXVNOI.js';
2
- import './chunk-MNM56B3X.js';
1
+ import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-DC4JPY6A.js';
2
+ import './chunk-E7RONUZ7.js';
3
+ import './chunk-NHICCDTC.js';
3
4
  import { Texture, Sprite } from 'pixi.js';
4
5
  import { WebGLRenderer, Scene, PerspectiveCamera } from 'three';
5
6
 
package/dist/three.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/three/ThreeSequence.ts","../src/three/index.ts"],"names":[],"mappings":"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","file":"three.js","sourcesContent":["import { Sprite, Texture } from 'pixi.js';\nimport { PerspectiveCamera, Scene, WebGLRenderer, type Camera } from 'three';\nimport { Sequence } from '../sequences/Base';\nimport { buildScope } from '../expr/Scope';\nimport { evaluateExpr } from '../expr/Parser';\nimport type { PathRouters } from '../core/Timeline';\nimport type { PropValue } from '../types';\nimport type { ThreeContext, ThreeSequenceSpec } from './types';\n\nexport class ThreeSequence extends Sequence {\n private _renderer: WebGLRenderer | null = null;\n private _scene: Scene | null = null;\n private _camera: Camera | null = null;\n private _ctx: ThreeContext | null = null;\n private _objects: Record<string, object> = {};\n private _warnedUpdate = false;\n private _warnedPaths = new Set<string>();\n\n private get _threeSpec(): ThreeSequenceSpec {\n return this.spec as unknown as ThreeSequenceSpec;\n }\n\n protected override pathRouters(): PathRouters {\n return { three: (path) => this._resolveThreePath(path) };\n }\n\n async build(): Promise<void> {\n const spec = this._threeSpec;\n if (this.duration === undefined) {\n this.duration = this.parent?.duration ?? this.root.duration;\n }\n\n // Resolve layer size. Expressions see the usual scope; intrinsic w/h are\n // still 0 here (same chicken-and-egg as shapes), so W/H/GW/GH carry it.\n const scope = buildScope(this, this.parent, this.root) as unknown as Record<string, number>;\n const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;\n const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;\n const resolution = spec.resolution ?? 1;\n\n // Offscreen canvas — never attached to the DOM. document.createElement\n // (not OffscreenCanvas) so PIXI's Texture.from and three both accept it.\n const canvas = document.createElement('canvas');\n const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: true });\n this._renderer = renderer;\n try {\n renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);\n renderer.setClearColor(0x000000, 0);\n\n const scene = new Scene();\n const camera: Camera = new PerspectiveCamera(50, width / height, 0.1, 2000);\n const ctx: ThreeContext = { scene, camera, renderer, width, height };\n\n const result = await spec.setup(ctx);\n if (result?.camera) ctx.camera = result.camera;\n this._scene = scene;\n this._camera = ctx.camera;\n this._ctx = ctx;\n this._objects = { ...(result?.objects ?? {}) };\n if (!('camera' in this._objects)) this._objects.camera = this._camera;\n\n // Frame 0 so the texture is never blank before the first tick.\n renderer.render(scene, this._camera);\n\n const texture = Texture.from(canvas);\n const sprite = new Sprite({ texture, label: spec.name });\n sprite.cullable = true;\n // Texture is canvas-sized (layer px × resolution); scale back to comp px.\n sprite.width = width;\n sprite.height = height;\n this.target = sprite;\n this.intrinsicWidth = width;\n this.intrinsicHeight = height;\n this.buildFilters();\n } catch (err) {\n this._disposeRenderer();\n throw err;\n }\n }\n\n /**\n * Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method\n * (same contract as VideoSequence) and awaits it inside gotoFrame — the\n * single frame path shared by playback and export, which is what makes\n * three layers deterministic in both.\n */\n async awaitFrameAt(local: number): Promise<void> {\n if (!this._renderer || !this._scene || !this._camera || !this._ctx) return;\n const spec = this._threeSpec;\n const t = Math.max(0, Math.min(local, this.duration ?? local));\n if (spec.update) {\n try {\n spec.update(t, this._ctx);\n } catch (err) {\n if (!this._warnedUpdate) {\n this._warnedUpdate = true;\n console.warn('pixi-effects: three update() threw (reported once) —', err);\n }\n }\n }\n this._renderer.render(this._scene, this._camera);\n (this.target as Sprite | null)?.texture.source.update();\n }\n\n private _resolveThreePath(path: string): { target: object; prop: string } | null {\n const segs = path.split('.');\n if (segs.length < 2) {\n this._warnPath(path, 'needs at least <object>.<prop>');\n return null;\n }\n let obj: unknown = this._objects[segs[0]!];\n if (obj == null) {\n this._warnPath(path, `unknown object \"${segs[0]}\" — expose it via setup's { objects }`);\n return null;\n }\n for (let i = 1; i < segs.length - 1; i++) {\n obj = (obj as Record<string, unknown>)[segs[i]!];\n if (obj == null) {\n this._warnPath(path, `\"${segs[i]}\" is undefined along the path`);\n return null;\n }\n }\n const prop = segs[segs.length - 1]!;\n if (typeof obj !== 'object' || !(prop in (obj as object))) {\n this._warnPath(path, `no property \"${prop}\"`);\n return null;\n }\n return { target: obj as object, prop };\n }\n\n private _warnPath(path: string, why: string): void {\n if (this._warnedPaths.has(path)) return;\n this._warnedPaths.add(path);\n console.warn(`pixi-effects: keyframe path three.${path} ${why}; skipped`);\n }\n\n private _disposeRenderer(): void {\n if (!this._renderer) return;\n try {\n this._renderer.dispose();\n this._renderer.forceContextLoss();\n } catch (err) {\n console.warn('pixi-effects: three renderer dispose threw —', err);\n }\n this._renderer = null;\n }\n\n override destroy(): void {\n const spec = this._threeSpec;\n if (this._ctx && spec.dispose) {\n try { spec.dispose(this._ctx); } catch (err) {\n console.warn('pixi-effects: three dispose() threw —', err);\n }\n }\n const texture = (this.target as Sprite | null)?.texture;\n this._disposeRenderer();\n this._scene = null;\n this._camera = null;\n this._ctx = null;\n this._objects = {};\n super.destroy();\n texture?.destroy(true); // canvas-backed source is per-sequence; safe to kill\n }\n}\n\nfunction resolveDim(v: PropValue | undefined, scope: Record<string, number>): number | undefined {\n if (v === undefined) return undefined;\n if (typeof v === 'number') return v;\n return evaluateExpr(v, scope);\n}\n","/**\n * pixi-effects/three — optional three.js integration.\n *\n * Import this entry only when you use `type: 'three'` sequences; the core\n * `pixi-effects` entry never touches three.js. Call `registerThree()` once\n * before Movie.init builds a composition containing a three sequence.\n */\nimport { registerSequenceType, type SequenceCtor } from '../core/Composition';\nimport { ThreeSequence } from './ThreeSequence';\nimport type { SequenceSpec } from '../types';\nimport type { ThreeSequenceSpec } from './types';\n\nexport { ThreeSequence } from './ThreeSequence';\nexport type { ThreeContext, ThreeSetupResult, ThreeSequenceSpec } from './types';\n\n/** Register the 'three' sequence type. Idempotent; explicit call so `sideEffects: false` bundlers can't drop it. */\nexport function registerThree(): void {\n registerSequenceType('three', ThreeSequence as unknown as SequenceCtor);\n}\n\n/**\n * Typing helper: accepts a strongly-typed three spec and returns it as a\n * core SequenceSpec, keeping three.js types out of the core union.\n */\nexport function three(spec: ThreeSequenceSpec): SequenceSpec {\n return spec as unknown as SequenceSpec;\n}\n"]}
1
+ {"version":3,"sources":["../src/three/ThreeSequence.ts","../src/three/index.ts"],"names":[],"mappings":"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","file":"three.js","sourcesContent":["import { Sprite, Texture } from 'pixi.js';\nimport { PerspectiveCamera, Scene, WebGLRenderer, type Camera } from 'three';\nimport { Sequence } from '../sequences/Base';\nimport { buildScope } from '../expr/Scope';\nimport { evaluateExpr } from '../expr/Parser';\nimport type { PathRouters } from '../core/Timeline';\nimport type { PropValue } from '../types';\nimport type { ThreeContext, ThreeSequenceSpec } from './types';\n\nexport class ThreeSequence extends Sequence {\n private _renderer: WebGLRenderer | null = null;\n private _scene: Scene | null = null;\n private _camera: Camera | null = null;\n private _ctx: ThreeContext | null = null;\n private _objects: Record<string, object> = {};\n private _warnedUpdate = false;\n private _warnedPaths = new Set<string>();\n\n private get _threeSpec(): ThreeSequenceSpec {\n return this.spec as unknown as ThreeSequenceSpec;\n }\n\n protected override pathRouters(): PathRouters {\n return { three: (path) => this._resolveThreePath(path) };\n }\n\n async build(): Promise<void> {\n const spec = this._threeSpec;\n if (this.duration === undefined) {\n this.duration = this.parent?.duration ?? this.root.duration;\n }\n\n // Resolve layer size. Expressions see the usual scope; intrinsic w/h are\n // still 0 here (same chicken-and-egg as shapes), so W/H/GW/GH carry it.\n const scope = buildScope(this, this.parent, this.root) as unknown as Record<string, number>;\n const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;\n const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;\n const resolution = spec.resolution ?? 1;\n\n // Offscreen canvas — never attached to the DOM. document.createElement\n // (not OffscreenCanvas) so PIXI's Texture.from and three both accept it.\n const canvas = document.createElement('canvas');\n const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: true });\n this._renderer = renderer;\n try {\n renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);\n renderer.setClearColor(0x000000, 0);\n\n const scene = new Scene();\n const camera: Camera = new PerspectiveCamera(50, width / height, 0.1, 2000);\n const ctx: ThreeContext = { scene, camera, renderer, width, height };\n\n const result = await spec.setup(ctx);\n if (result?.camera) ctx.camera = result.camera;\n this._scene = scene;\n this._camera = ctx.camera;\n this._ctx = ctx;\n this._objects = { ...(result?.objects ?? {}) };\n if (!('camera' in this._objects)) this._objects.camera = this._camera;\n\n // Frame 0 so the texture is never blank before the first tick.\n renderer.render(scene, this._camera);\n\n const texture = Texture.from(canvas);\n const sprite = new Sprite({ texture, label: spec.name });\n sprite.cullable = true;\n // Texture is canvas-sized (layer px × resolution); scale back to comp px.\n sprite.width = width;\n sprite.height = height;\n this.target = sprite;\n this.intrinsicWidth = width;\n this.intrinsicHeight = height;\n this.buildFilters();\n } catch (err) {\n this._disposeRenderer();\n throw err;\n }\n }\n\n /**\n * Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method\n * (same contract as VideoSequence) and awaits it inside gotoFrame — the\n * single frame path shared by playback and export, which is what makes\n * three layers deterministic in both.\n */\n async awaitFrameAt(local: number): Promise<void> {\n if (!this._renderer || !this._scene || !this._camera || !this._ctx) return;\n const spec = this._threeSpec;\n const t = Math.max(0, Math.min(local, this.duration ?? local));\n if (spec.update) {\n try {\n spec.update(t, this._ctx);\n } catch (err) {\n if (!this._warnedUpdate) {\n this._warnedUpdate = true;\n console.warn('pixi-effects: three update() threw (reported once) —', err);\n }\n }\n }\n this._renderer.render(this._scene, this._camera);\n (this.target as Sprite | null)?.texture.source.update();\n }\n\n private _resolveThreePath(path: string): { target: object; prop: string } | null {\n const segs = path.split('.');\n if (segs.length < 2) {\n this._warnPath(path, 'needs at least <object>.<prop>');\n return null;\n }\n let obj: unknown = this._objects[segs[0]!];\n if (obj == null) {\n this._warnPath(path, `unknown object \"${segs[0]}\" — expose it via setup's { objects }`);\n return null;\n }\n for (let i = 1; i < segs.length - 1; i++) {\n obj = (obj as Record<string, unknown>)[segs[i]!];\n if (obj == null) {\n this._warnPath(path, `\"${segs[i]}\" is undefined along the path`);\n return null;\n }\n }\n const prop = segs[segs.length - 1]!;\n if (typeof obj !== 'object' || !(prop in (obj as object))) {\n this._warnPath(path, `no property \"${prop}\"`);\n return null;\n }\n return { target: obj as object, prop };\n }\n\n private _warnPath(path: string, why: string): void {\n if (this._warnedPaths.has(path)) return;\n this._warnedPaths.add(path);\n console.warn(`pixi-effects: keyframe path three.${path} ${why}; skipped`);\n }\n\n private _disposeRenderer(): void {\n if (!this._renderer) return;\n try {\n this._renderer.dispose();\n this._renderer.forceContextLoss();\n } catch (err) {\n console.warn('pixi-effects: three renderer dispose threw —', err);\n }\n this._renderer = null;\n }\n\n override destroy(): void {\n const spec = this._threeSpec;\n if (this._ctx && spec.dispose) {\n try { spec.dispose(this._ctx); } catch (err) {\n console.warn('pixi-effects: three dispose() threw —', err);\n }\n }\n const texture = (this.target as Sprite | null)?.texture;\n this._disposeRenderer();\n this._scene = null;\n this._camera = null;\n this._ctx = null;\n this._objects = {};\n super.destroy();\n texture?.destroy(true); // canvas-backed source is per-sequence; safe to kill\n }\n}\n\nfunction resolveDim(v: PropValue | undefined, scope: Record<string, number>): number | undefined {\n if (v === undefined) return undefined;\n if (typeof v === 'number') return v;\n return evaluateExpr(v, scope);\n}\n","/**\n * pixi-effects/three — optional three.js integration.\n *\n * Import this entry only when you use `type: 'three'` sequences; the core\n * `pixi-effects` entry never touches three.js. Call `registerThree()` once\n * before Movie.init builds a composition containing a three sequence.\n */\nimport { registerSequenceType, type SequenceCtor } from '../core/Composition';\nimport { ThreeSequence } from './ThreeSequence';\nimport type { SequenceSpec } from '../types';\nimport type { ThreeSequenceSpec } from './types';\n\nexport { ThreeSequence } from './ThreeSequence';\nexport type { ThreeContext, ThreeSetupResult, ThreeSequenceSpec } from './types';\n\n/** Register the 'three' sequence type. Idempotent; explicit call so `sideEffects: false` bundlers can't drop it. */\nexport function registerThree(): void {\n registerSequenceType('three', ThreeSequence as unknown as SequenceCtor);\n}\n\n/**\n * Typing helper: accepts a strongly-typed three spec and returns it as a\n * core SequenceSpec, keeping three.js types out of the core union.\n */\nexport function three(spec: ThreeSequenceSpec): SequenceSpec {\n return spec as unknown as SequenceSpec;\n}\n"]}
@@ -197,6 +197,8 @@ interface DissolveTransition extends TransitionCommon {
197
197
  smoothing?: number;
198
198
  }
199
199
  type TransitionSpec = CrossfadeTransition | WipeTransition | IrisTransition | SlideTransition | DipTransition | ZoomTransition | DissolveTransition;
200
+ /** How a layer blends with what is behind it: the CSS `mix-blend-mode` names, plus `add` and `linear-burn`. */
201
+ type BlendModeName = 'normal' | 'add' | 'screen' | 'multiply' | 'overlay' | 'soft-light' | 'hard-light' | 'color-dodge' | 'color-burn' | 'darken' | 'lighten' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'linear-burn';
200
202
  interface SequenceCommon {
201
203
  name?: string;
202
204
  /**
@@ -248,11 +250,12 @@ interface SequenceCommon {
248
250
  */
249
251
  maskInverted?: boolean;
250
252
  /**
251
- * How this layer blends with what is behind it. `'add'` and `'screen'` brighten (glows, light leaks,
252
- * overlapping halos add up instead of covering each other), `'multiply'` darkens. Default `'normal'`.
253
+ * How this layer blends with what is behind it (everything drawn below it). `'add'` and `'screen'` brighten (glows, light
254
+ * leaks, overlapping halos add up instead of covering each other), `'multiply'` darkens; `'overlay'`, `'soft-light'`,
255
+ * `'color-dodge'`, `'hue'`, ... are the CSS `mix-blend-mode` modes. Default `'normal'`.
253
256
  * On a composition the mode is inherited by its children: each one blends with what is behind it.
254
257
  */
255
- blendMode?: 'normal' | 'add' | 'screen' | 'multiply';
258
+ blendMode?: BlendModeName;
256
259
  /**
257
260
  * Opt this layer into 2.5D: it can then use `z`, `rotationX`, `rotationY`
258
261
  * (in `initial` / keyframes) and is projected through the composition's
@@ -682,4 +685,4 @@ interface AudioDescriptor {
682
685
  sourceMap?: (u: number) => number;
683
686
  }
684
687
 
685
- export { pictureStops as $, type ArcShapeSpec as A, type SfxOptions as B, type CompositionShape as C, type DipTransition as D, type EllipseShapeSpec as E, type FilterSpec as F, type GradientSpec as G, type SfxPreset as H, type ImageSequenceSpec as I, type SfxVoice as J, type Keyframe as K, type LineShapeSpec as L, type MusicOptions as M, type NullSequenceSpec as N, type ShapeSequenceSpec as O, type Props as P, type SlideTransition as Q, type RectShapeSpec as R, type SequenceSpec as S, type TextSequenceSpec as T, type Stop as U, type StopSpec as V, type TransitionCommon as W, type VideoSequenceSpec as X, type WipeTransition as Y, type ZoomTransition as Z, normalizeStops as _, type CameraSequenceSpec as a, type AudioDescriptor as a0, type TransitionSpec as b, type CompositionSpec as c, type SequenceCommon as d, type AssetSpec as e, type AudioAssetSpec as f, type AudioMusicSpec as g, type AudioSequenceSpec as h, type AudioSfxSpec as i, type ChromaKeyFilterSpec as j, type CircleShapeSpec as k, type CompositionSequenceSpec as l, type CrossfadeTransition as m, type CustomFilterSpec as n, type DissolveTransition as o, type Expr as p, type IrisTransition as q, type MusicDrum as r, type MusicDrums as s, type MusicInstrument as t, type MusicLevel as u, type MusicTrack as v, type PathShapeSpec as w, type PolygonShapeSpec as x, type PropValue as y, type SfxKnobs as z };
688
+ export { normalizeStops as $, type ArcShapeSpec as A, type BlendModeName as B, type CompositionShape as C, type DipTransition as D, type EllipseShapeSpec as E, type FilterSpec as F, type GradientSpec as G, type SfxOptions as H, type ImageSequenceSpec as I, type SfxPreset as J, type Keyframe as K, type LineShapeSpec as L, type MusicOptions as M, type NullSequenceSpec as N, type SfxVoice as O, type Props as P, type ShapeSequenceSpec as Q, type RectShapeSpec as R, type SequenceSpec as S, type TextSequenceSpec as T, type SlideTransition as U, type Stop as V, type StopSpec as W, type TransitionCommon as X, type VideoSequenceSpec as Y, type WipeTransition as Z, type ZoomTransition as _, type CameraSequenceSpec as a, pictureStops as a0, type AudioDescriptor as a1, type TransitionSpec as b, type CompositionSpec as c, type SequenceCommon as d, type AssetSpec as e, type AudioAssetSpec as f, type AudioMusicSpec as g, type AudioSequenceSpec as h, type AudioSfxSpec as i, type ChromaKeyFilterSpec as j, type CircleShapeSpec as k, type CompositionSequenceSpec as l, type CrossfadeTransition as m, type CustomFilterSpec as n, type DissolveTransition as o, type Expr as p, type IrisTransition as q, type MusicDrum as r, type MusicDrums as s, type MusicInstrument as t, type MusicLevel as u, type MusicTrack as v, type PathShapeSpec as w, type PolygonShapeSpec as x, type PropValue as y, type SfxKnobs as z };
@@ -197,6 +197,8 @@ interface DissolveTransition extends TransitionCommon {
197
197
  smoothing?: number;
198
198
  }
199
199
  type TransitionSpec = CrossfadeTransition | WipeTransition | IrisTransition | SlideTransition | DipTransition | ZoomTransition | DissolveTransition;
200
+ /** How a layer blends with what is behind it: the CSS `mix-blend-mode` names, plus `add` and `linear-burn`. */
201
+ type BlendModeName = 'normal' | 'add' | 'screen' | 'multiply' | 'overlay' | 'soft-light' | 'hard-light' | 'color-dodge' | 'color-burn' | 'darken' | 'lighten' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity' | 'linear-burn';
200
202
  interface SequenceCommon {
201
203
  name?: string;
202
204
  /**
@@ -248,11 +250,12 @@ interface SequenceCommon {
248
250
  */
249
251
  maskInverted?: boolean;
250
252
  /**
251
- * How this layer blends with what is behind it. `'add'` and `'screen'` brighten (glows, light leaks,
252
- * overlapping halos add up instead of covering each other), `'multiply'` darkens. Default `'normal'`.
253
+ * How this layer blends with what is behind it (everything drawn below it). `'add'` and `'screen'` brighten (glows, light
254
+ * leaks, overlapping halos add up instead of covering each other), `'multiply'` darkens; `'overlay'`, `'soft-light'`,
255
+ * `'color-dodge'`, `'hue'`, ... are the CSS `mix-blend-mode` modes. Default `'normal'`.
253
256
  * On a composition the mode is inherited by its children: each one blends with what is behind it.
254
257
  */
255
- blendMode?: 'normal' | 'add' | 'screen' | 'multiply';
258
+ blendMode?: BlendModeName;
256
259
  /**
257
260
  * Opt this layer into 2.5D: it can then use `z`, `rotationX`, `rotationY`
258
261
  * (in `initial` / keyframes) and is projected through the composition's
@@ -682,4 +685,4 @@ interface AudioDescriptor {
682
685
  sourceMap?: (u: number) => number;
683
686
  }
684
687
 
685
- export { pictureStops as $, type ArcShapeSpec as A, type SfxOptions as B, type CompositionShape as C, type DipTransition as D, type EllipseShapeSpec as E, type FilterSpec as F, type GradientSpec as G, type SfxPreset as H, type ImageSequenceSpec as I, type SfxVoice as J, type Keyframe as K, type LineShapeSpec as L, type MusicOptions as M, type NullSequenceSpec as N, type ShapeSequenceSpec as O, type Props as P, type SlideTransition as Q, type RectShapeSpec as R, type SequenceSpec as S, type TextSequenceSpec as T, type Stop as U, type StopSpec as V, type TransitionCommon as W, type VideoSequenceSpec as X, type WipeTransition as Y, type ZoomTransition as Z, normalizeStops as _, type CameraSequenceSpec as a, type AudioDescriptor as a0, type TransitionSpec as b, type CompositionSpec as c, type SequenceCommon as d, type AssetSpec as e, type AudioAssetSpec as f, type AudioMusicSpec as g, type AudioSequenceSpec as h, type AudioSfxSpec as i, type ChromaKeyFilterSpec as j, type CircleShapeSpec as k, type CompositionSequenceSpec as l, type CrossfadeTransition as m, type CustomFilterSpec as n, type DissolveTransition as o, type Expr as p, type IrisTransition as q, type MusicDrum as r, type MusicDrums as s, type MusicInstrument as t, type MusicLevel as u, type MusicTrack as v, type PathShapeSpec as w, type PolygonShapeSpec as x, type PropValue as y, type SfxKnobs as z };
688
+ export { normalizeStops as $, type ArcShapeSpec as A, type BlendModeName as B, type CompositionShape as C, type DipTransition as D, type EllipseShapeSpec as E, type FilterSpec as F, type GradientSpec as G, type SfxOptions as H, type ImageSequenceSpec as I, type SfxPreset as J, type Keyframe as K, type LineShapeSpec as L, type MusicOptions as M, type NullSequenceSpec as N, type SfxVoice as O, type Props as P, type ShapeSequenceSpec as Q, type RectShapeSpec as R, type SequenceSpec as S, type TextSequenceSpec as T, type SlideTransition as U, type Stop as V, type StopSpec as W, type TransitionCommon as X, type VideoSequenceSpec as Y, type WipeTransition as Z, type ZoomTransition as _, type CameraSequenceSpec as a, pictureStops as a0, type AudioDescriptor as a1, type TransitionSpec as b, type CompositionSpec as c, type SequenceCommon as d, type AssetSpec as e, type AudioAssetSpec as f, type AudioMusicSpec as g, type AudioSequenceSpec as h, type AudioSfxSpec as i, type ChromaKeyFilterSpec as j, type CircleShapeSpec as k, type CompositionSequenceSpec as l, type CrossfadeTransition as m, type CustomFilterSpec as n, type DissolveTransition as o, type Expr as p, type IrisTransition as q, type MusicDrum as r, type MusicDrums as s, type MusicInstrument as t, type MusicLevel as u, type MusicTrack as v, type PathShapeSpec as w, type PolygonShapeSpec as x, type PropValue as y, type SfxKnobs as z };
package/docs/dsl.md CHANGED
@@ -254,7 +254,7 @@ A tune with no audio file: notes, chords and drum patterns written as strings, p
254
254
  } }
255
255
  ```
256
256
 
257
- **Layer.** `at` starts it, `volume` (and volume keyframes) scale it. `duration` defaults to the music's length plus its reverb tail (`tail`, 2.5 s), but never past the end of the composition (the music then ends with the movie, with a short fade). A shorter `duration` cuts it with a fade; a longer one is silent after the music unless **`loop: true`**, which repeats the score until the layer ends (default: the end of the composition). At `volume: 1` the music peaks at −6 dBFS (about −20 dB RMS), a bed that sits under speech and sound effects (an sfx peaks at −12 dBFS).
257
+ **Layer.** `at` starts it, `volume` (and volume keyframes) scale it. `duration` defaults to the music's length plus its reverb tail (`tail`, 2.5 s), but never past the end of the composition (the music then ends with the movie, with a short fade). A shorter `duration` cuts it with a fade; a longer one is silent after the music unless **`loop: true`**, which repeats the score until the layer ends (default: the end of the composition). At `volume: 1` the music peaks at −6 dBFS (about −20 dB RMS), a bed that sits under speech and sound effects (an sfx peaks at −12 dBFS). Measured: a 4-bar tune (bell + bass + kick, a pluck and a hat on the repeat) at `volume: 0.8` reads −22 LUFS and −7.7 dBTP (`piano-roll`); web video is usually −14 to −16 LUFS, so 0.8 is not a limit: raise `volume` and watch `inspectAudio().loudness.truePeakDb`. `inspectAudio()` lists a music layer as ONE source (its start); to line a picture up with a note, compute the onset yourself: `at + beat × 60 / bpm` (build the bars and the score from one array so they cannot drift).
258
258
 
259
259
  **Score** (`music`): `bpm` (a number, or `[beat, bpm]` points for a tempo change: `[[0, 96], [28, 96], [32, 60]]` slows down over beats 28–32, a ritardando), `tracks`, `drums`, `swing` (0–0.4: delays the off-beat eighths and sixteenths; 0.16 is a gentle lo-fi lilt), `reverb` (0–0.6, default 0.22), `humanize` (seconds of seeded timing jitter, default 0.012), `drumVol` (default 0.8), `grid` (drum steps per beat, default 4), `transpose` (semitones, all pitched tracks), `tail`, `seed`. Misspelt names warn with "did you mean". The music's length is its longest track (drums repeat up to it), so a track of rests (`'_:16'`) sets a length.
260
260
 
@@ -273,7 +273,7 @@ A tune with no audio file: notes, chords and drum patterns written as strings, p
273
273
 
274
274
  **Drums.** `drums` is an object of patterns, or a list of them with `from` / `to` (beats) so a groove can start late or stop (`[{ kick: 'x...' }, { from: 8, snare: '....x...' }]`). A pattern is a string of steps: `x` hit, `o` soft hit, `.` nothing (`|` and spaces are ignored); one step is 1/`grid` of a beat, so with the default grid 4 a 16-step string is one bar of 4/4, and a longer string (32 steps) is a longer figure that repeats. Drums: `kick snare hat openhat clap rim tom crash shaker sleigh` (`sleigh` is a jingle of small bells).
275
275
 
276
- **Other meters.** The notation counts beats (the quarter note is 1), so 3/4 is bars of 3 beats. 6/8 is bars of 3 beats too: a dotted quarter is `:1.5`, an eighth `:0.5`; set `grid: 2` so a drum step is an eighth note (a 6-step pattern is one bar), and leave `swing` at 0. `grid: 3` is for triplet eighths in 4/4 (a shuffle).
276
+ **Other meters.** The notation counts beats (the quarter note is 1), so 3/4 is bars of 3 beats. 6/8 is bars of 3 beats too: a dotted quarter is `:1.5`, an eighth `:0.5`; set `grid: 2` so a drum step is an eighth note (a 6-step pattern is one bar; the same `grid: 2` gives 6 eighth steps per bar in 3/4), and leave `swing` at 0. `grid: 3` is for triplet eighths in 4/4 (a shuffle).
277
277
 
278
278
  **Hear it without a movie.** [`musicBuffer(music)`](api.md#musicbuffer) returns a Web Audio buffer; [`examples/music-lab.html`](../examples/music-lab.html) plays eight finished scores and shows each one as source.
279
279
 
@@ -509,6 +509,8 @@ The camera is a layer: `{ "type": "camera" }`. It has no visuals. With nothing s
509
509
  | `z` | camera depth. **Auto:** if you never set it, it follows `fov` so the `z = 0` plane stays 1:1 | `(H/2) / tan(fov/2)` |
510
510
  | `lookAtX`, `lookAtY`, `lookAtZ` | the point it looks at | `W/2`, `H/2`, `0` |
511
511
  | `fov` | vertical field of view, degrees (clamped to 1–179) | 40 |
512
+ | `focus` | the plane that is **sharp**: a `threeD` layer's name (its first `z`) or a z number. Turns depth of field on (see [Depth of field](#depth-of-field)) | the `z = 0` plane |
513
+ | `aperture` | how shallow: the lens diameter in px. `0` = off. Written alone, or with `focus`, it turns depth of field on | `30` |
512
514
  | `offsetX`, `offsetY`, `offsetZ`, `lookOffsetX`, `lookOffsetY`, `lookOffsetZ` | **added** to the position and to the look-at point, on top of the camera's own move. Put a handheld shake (`wiggle()`) here and it never collides with a dolly or an orbit (two tweens on the same prop overwrite each other; these are separate props) | 0 |
513
515
 
514
516
  A flight through the scene is [`cameraPath()`](#camerapath) (a route as keyframes); a threeD layer the camera passes on purpose takes `hideBehindCamera: true` (hidden quietly when it is at or behind the camera, instead of a warning).
@@ -547,6 +549,45 @@ Moving the camera sideways makes the near rectangle slide faster than the far on
547
549
  - Several cameras may exist if their lifespans (`at` / `duration`) do not overlap — each is a camera cut. Overlapping cameras warn; the last-listed one wins.
548
550
  - With no camera layer the default camera is used.
549
551
 
552
+ ### Depth of field
553
+
554
+ Write `focus` (and, if you want, `aperture`) on the camera and the `threeD` layers blur by how far they are from the plane in focus; the layer in focus stays sharp. Nothing else changes: without `focus` and `aperture` there is no blur and no cost.
555
+
556
+ ```json
557
+ {
558
+ "sequences": [
559
+ { "type": "camera", "initial": { "focus": "title" } },
560
+ { "type": "text", "name": "title", "text": "Focus", "threeD": true, "style": { "fontSize": 96, "fill": "#ffffff" }, "initial": { "x": "GW/2", "y": "GH/2", "z": 0, "anchorX": 0.5, "anchorY": 0.5 } },
561
+ { "type": "shape", "shape": "circle", "radius": 140, "threeD": true, "initial": { "x": "GW/2 + 260", "y": "GH/2", "z": -500, "fillColor": "#3a6ea5" } }
562
+ ]
563
+ }
564
+ ```
565
+
566
+ A focus pull is a normal keyframe on `focus`; a layer name works there too:
567
+
568
+ ```json
569
+ {
570
+ "sequences": [
571
+ { "type": "camera", "initial": { "focus": "front", "aperture": 60 },
572
+ "keyframes": [{ "at": 1, "to": { "focus": "back" }, "duration": 1, "ease": "power2.inOut" }] },
573
+ { "type": "shape", "shape": "rect", "name": "front", "width": 300, "height": 200, "threeD": true, "initial": { "x": "GW/2 - 200", "y": "GH/2", "z": 100, "fillColor": "#d96a3a" } },
574
+ { "type": "shape", "shape": "rect", "name": "back", "width": 300, "height": 200, "threeD": true, "initial": { "x": "GW/2 + 200", "y": "GH/2", "z": -400, "fillColor": "#3a6ea5" } }
575
+ ]
576
+ }
577
+ ```
578
+
579
+ - `aperture` is the lens diameter in pixels; the blur radius of a layer is `aperture × focal × |1/depth − 1/focusDepth| / 2` (focal = `(H/2)/tan(fov/2)`), capped at 32 px. With the default camera at 720p and the focus on `z = 0`, a layer at `z = −400` blurs by: `aperture 10` → 1.4 px (a soft hint), `30` → 4.3 px (clearly shallow), `60` → 8.6 px (strong), `100` → 14.4 px (extreme: small bright objects show a faint speckle). A layer further away blurs more, up to the cap.
580
+ - A layer **nearer** than the focus blurs too, and for the same `z` distance a near layer blurs more than a far one: with `aperture: 58` and the focus on a sign at `z = −600`, a layer at `z = +250` blurs about 21 px; with the focus on a layer at `z = +250`, a layer at `z = −1100` blurs about 25 px (720p, default camera). Plan a scene with the formula above, or read `depthBlur` from `movie.inspect(frame)`.
581
+ - A layer name in `focus` means **the first `z`** of that layer; if its `z` moves later, animate `focus` itself with numbers (a warning says so). A name that no layer has, or a layer that is not `threeD`, warns and uses the `z = 0` plane.
582
+ - The blur is the same over the whole layer (decided by the depth of the layer's origin along the camera's view direction: with an orbiting camera a layer far off the look-at axis is a little deeper than its `z`). A tilted floor is one blur: split it into layers.
583
+ - It blurs `threeD` layers only. A nested `threeD` composition is blurred as one layer by its parent's camera; its own camera decides its content.
584
+ - The layer's own `blur` and its `filters` are separate and add to it.
585
+ - Many blurred layers cost one filter pass each (more on WebGPU): 20 or more at once warns. A field of bokeh lights is a few big `threeD` cards (a plain layer or a composition with a few dozen circles in it), not dozens of layers. To make a card at depth `z` fill the frame, size it `(W / s) × (H / s)` with `s = camZ / (camZ − z)` (`camZ` = the camera's z, about 989 at 720p, fov 40): at `z = −720` that is `s = 0.58`, so about 2210 × 1240 for a 1280 × 720 frame.
586
+ - A **dolly** needs no typed distance: leave the camera's `z` alone (it stays automatic) and animate `offsetZ` (negative = closer); the focus plane and the layers keep their meaning. Writing `z` yourself means typing the home distance, `H / 2 / tan(fov / 2)`, which as an expression is `H / 2 / tan(20 * PI / 180)` for the default fov 40.
587
+ - If two layers have the same `name`, `focus` takes the first `threeD` one (and warns that the name is not unique). `focus` and `aperture` are camera properties: on any other layer they only warn.
588
+ - A negative or non-numeric `aperture` warns once and turns depth of field off.
589
+ - `movie.inspect(frame)` reports each `threeD` layer's blur as `depthBlur` (px, 0 = sharp).
590
+
550
591
  ### Depth order and limits
551
592
 
552
593
  - Consecutive `threeD` layers are drawn farthest-first. A non-`threeD` layer between them splits the group (like After Effects).
@@ -694,13 +735,51 @@ Routed through PIXI v8's native `setMask({ inverse: true })`.
694
735
 
695
736
  #### `blendMode`
696
737
 
697
- How a layer blends with what is behind it: `'normal'` (default), `'add'`, `'screen'` or `'multiply'`. `add` and `screen` brighten, so overlapping glows, halos and light leaks add up instead of covering each other; `multiply` darkens. It works on every layer type, on `threeD` layers, and on a composition (its children inherit the mode, each blending with what is behind it). Any other value warns and is ignored.
738
+ How a layer blends with what is **behind it** (everything drawn below it in the stack): 18 modes, the CSS `mix-blend-mode` names (`add` and `linear-burn` are the two that CSS does not have; `linear-burn` is the After Effects / Photoshop name). Default `'normal'`. It works on every layer type, on `threeD` layers, and on a composition.
739
+
740
+ | mode | what it does |
741
+ |---|---|
742
+ | `normal` | the layer covers what is behind it |
743
+ | `add`, `screen` | brighten: overlapping glows, halos and light leaks add up instead of covering each other |
744
+ | `multiply` | darkens: shadows, vignettes, a tint over a photo |
745
+ | `overlay` | contrast: darks get darker, lights lighter, by what is behind |
746
+ | `soft-light` | a gentle `overlay`: colour casts, soft vignettes, a graded look |
747
+ | `hard-light` | `overlay` decided by the layer instead of the backdrop: strong punch |
748
+ | `color-dodge` | strong light: burns bright spots out toward white (light sources, lens flares) |
749
+ | `color-burn`, `linear-burn` | deep shadows and saturated darks |
750
+ | `darken`, `lighten` | keep the darker / the lighter of the two, channel by channel |
751
+ | `difference`, `exclusion` | the distance between the two colours (`exclusion` is softer): inversions, "film negative" looks |
752
+ | `hue`, `saturation`, `color`, `luminosity` | put only the hue, the saturation, the colour (hue + saturation) or the brightness of the layer onto the backdrop |
753
+
754
+ Rules:
755
+
756
+ 1. **The order of layers decides what is blended.** Put the backdrop first (earlier in the array) and the blended layer after it.
757
+ 2. **Names are CSS names, with the hyphen** (`soft-light`, not `softLight` / `soft_light`; a slip like that warns with the name you meant).
758
+ 3. **Colours are mixed as the sRGB values you see** (as CSS does), not in linear light.
759
+ 4. **`alpha` fades the blended result** (as CSS `opacity` does).
760
+ 5. **On a composition the mode is inherited by its children, each blending with what is behind it** (not as one picture). To blend a composition as a whole, give it `threeD: true` (at `z: 0` with the default camera nothing else changes) or a filter.
761
+ 6. **The 14 new modes are heavier** (each is a full-frame pass; about 1.5–2 ms a layer on WebGL at 1080p in the author's measurement, much less on WebGPU). 10 or more on screen at once warns (a composition with one counts each layer inside it, since its children blend one by one; one without counts the most that its own layers add at one time); a glow or a haze should be one layer (a gradient), not a pile.
762
+ 7. **Together with `filters`, `threeD` and depth of field they all work** (the blend is applied after the layer's own filters, and after the depth-of-field blur).
763
+ 8. **Some modes only act on some tones.** `overlay` and `soft-light` change almost nothing over a near-black or a near-white backdrop (their formulas leave 0 and 1 where they are), so a colour cast needs a **mid-tone** picture under it; `color-dodge` over a dark backdrop gives a saturated colour (each channel is lifted separately), over a bright one it burns out to white; `multiply` can only darken and `screen` / `add` only brighten.
764
+ 9. **`blendMode` is a setting of the layer, not an animatable property** (`initial` or a keyframe with it warns). To change the mode for a moment, put a second, short-lived layer (`at` / `duration`) on top, or fade a layer's `alpha`.
765
+ 10. **With `mask`:** an inverted mask (`maskInverted: true`) works with every mode, a mask with its own `filters` (a blurred, feathered hole) included. A **text, image or video layer as the mask** (not inverted) cannot carry a blend (it warns and draws the layer normal): put it on a layer of its own with the `blendMode`, or use `maskInverted`. A shape as a (not inverted) mask works as it is.
766
+
767
+ Checked against the W3C formulas on WebGPU and WebGL: every pixel within 2/255 (measured worst: 0.5/255 at alpha 1, 1.5/255 at alpha 0.5; over opaque backdrops and over nothing, as inside a `threeD` composition: a half-transparent layer over a half-transparent backdrop can differ more, because Pixi lays the blended result over the backdrop once more); on the same machine a frame is the same picture however it was reached. Another GPU can differ by a step or two.
698
768
 
699
769
  ```ts
700
770
  // A soft white glow that brightens whatever it overlaps
701
771
  { type: 'shape', shape: 'circle', radius: 120, blendMode: 'add',
702
772
  fillGradient: { type: 'radial', stops: [[0, 'rgba(255,255,255,0.9)'], [1, 'rgba(255,255,255,0)']] },
703
773
  initial: { x: 'W/2', y: 'H/2' } }
774
+
775
+ // A colour cast over everything below it: orange at the top, blue at the bottom
776
+ { type: 'shape', shape: 'rect', width: 'GW', height: 'GH', anchorX: 0, anchorY: 0, blendMode: 'soft-light',
777
+ fillGradient: { stops: [[0, '#ff9a3c'], [1, '#3c5bff']] } }
778
+
779
+ // A light leak: a strong source that burns out toward white where it meets the picture
780
+ { type: 'shape', shape: 'circle', radius: 380, blendMode: 'color-dodge',
781
+ fillGradient: { type: 'radial', stops: [[0, 'rgba(255,120,30,0.9)'], [1, 'rgba(255,120,30,0)']] },
782
+ initial: { x: 1000, y: 160 } }
704
783
  ```
705
784
 
706
785
  ---