pixi-effects 0.2.0 → 0.3.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 (51) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +15 -5
  3. package/ai/SKILL.md +44 -0
  4. package/ai/reference/cheatsheet.md +120 -0
  5. package/ai/reference/pitfalls.md +54 -0
  6. package/ai/reference/recipes.md +375 -0
  7. package/ai/template.html +82 -0
  8. package/ai/tools/save-image.py +24 -0
  9. package/dist/{Base-B1Tdn0Cv.d.cts → Base-BDw6dKRB.d.cts} +1 -1
  10. package/dist/{Base-Bh_VSusi.d.ts → Base-Ba4Ta4ap.d.ts} +1 -1
  11. package/dist/Composition-6FDH5OPM.cjs +13 -0
  12. package/dist/{Composition-BI5HZJFL.cjs.map → Composition-6FDH5OPM.cjs.map} +1 -1
  13. package/dist/Composition-FEYAUMFI.js +4 -0
  14. package/dist/{Composition-IO7ZN32J.js.map → Composition-FEYAUMFI.js.map} +1 -1
  15. package/dist/Controller.d.cts +2 -2
  16. package/dist/Controller.d.ts +2 -2
  17. package/dist/Movie-DMpaT67V.d.ts +179 -0
  18. package/dist/Movie-W8ISiEBB.d.cts +179 -0
  19. package/dist/{chunk-H55V3U56.js → chunk-DIJG2RSF.js} +28 -11
  20. package/dist/chunk-DIJG2RSF.js.map +1 -0
  21. package/dist/{chunk-VJCDG6YG.js → chunk-PN5A6QA7.js} +248 -64
  22. package/dist/chunk-PN5A6QA7.js.map +1 -0
  23. package/dist/{chunk-7OIWYXGV.cjs → chunk-SIRVULFF.cjs} +251 -62
  24. package/dist/chunk-SIRVULFF.cjs.map +1 -0
  25. package/dist/{chunk-64IHCYYN.cjs → chunk-ZL262ZRM.cjs} +37 -20
  26. package/dist/chunk-ZL262ZRM.cjs.map +1 -0
  27. package/dist/index.cjs +324 -24
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +61 -31
  30. package/dist/index.d.ts +61 -31
  31. package/dist/index.js +321 -22
  32. package/dist/index.js.map +1 -1
  33. package/dist/three.cjs +5 -5
  34. package/dist/three.d.cts +2 -2
  35. package/dist/three.d.ts +2 -2
  36. package/dist/three.js +1 -1
  37. package/dist/{types-CNBilhpz.d.cts → types-3c8Vymgw.d.cts} +53 -6
  38. package/dist/{types-CNBilhpz.d.ts → types-3c8Vymgw.d.ts} +53 -6
  39. package/docs/api.md +333 -0
  40. package/docs/dsl.md +1017 -0
  41. package/llms-full.txt +1966 -0
  42. package/llms.txt +30 -0
  43. package/package.json +4 -3
  44. package/dist/Composition-BI5HZJFL.cjs +0 -13
  45. package/dist/Composition-IO7ZN32J.js +0 -4
  46. package/dist/Movie-CcR6h2jO.d.cts +0 -82
  47. package/dist/Movie-D-n8glA6.d.ts +0 -82
  48. package/dist/chunk-64IHCYYN.cjs.map +0 -1
  49. package/dist/chunk-7OIWYXGV.cjs.map +0 -1
  50. package/dist/chunk-H55V3U56.js.map +0 -1
  51. package/dist/chunk-VJCDG6YG.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/space/camera.ts","../src/space/depth.ts","../src/space/Layer3D.ts","../src/space/lint.ts","../src/sequences/Composition.ts"],"names":["i","DEG","frameOf","PerspectiveMesh","Texture","projectLayer","describeLayer","Matrix","RenderTexture","collectPropKeys","Sequence","Container","Rectangle","lintTiming","lintText","buildSequenceTree","CameraSequence","cameraBasis","homeCamera"],"mappings":"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","file":"chunk-ZL262ZRM.cjs","sourcesContent":["/** A camera layer's lifespan on the global timeline, seconds. */\nexport interface CameraWindow { start: number; end: number }\n\n/**\n * The active camera at time `t`: the last-listed (top-most) camera whose\n * lifespan covers `t`. Windows are [start, end), except that a camera running\n * to the end of its composition also covers the final instant `t === compEnd`.\n */\nexport function pickActiveCamera<T extends CameraWindow>(\n cams: readonly T[],\n t: number,\n compEnd: number,\n): T | null {\n for (let i = cams.length - 1; i >= 0; i--) {\n const c = cams[i]!;\n const inside = t >= c.start && (t < c.end || (c.end >= compEnd && t <= compEnd));\n if (inside) return c;\n }\n return null;\n}\n\n/** First pair of camera indices whose lifespans strictly overlap, or null. */\nexport function findOverlap(cams: readonly CameraWindow[]): [number, number] | null {\n for (let i = 0; i < cams.length; i++) {\n for (let j = i + 1; j < cams.length; j++) {\n const a = cams[i]!;\n const b = cams[j]!;\n if (a.start < b.end && b.start < a.end) return [i, j];\n }\n }\n return null;\n}\n","export interface DepthItem {\n /** Position in the composition's stack (monotonic; gaps allowed). */\n stackIndex: number;\n threeD: boolean;\n /** Camera-space depth (larger = farther). Only read for threeD items. */\n depth: number;\n}\n\nconst finite = (n: number): number => (Number.isFinite(n) ? n : 0);\n\n/**\n * zIndex per item. Non-3D items keep their stack index. Each run of\n * consecutive threeD items is redistributed over the same index slots,\n * farthest first (drawn first), ties in stack order.\n */\nexport function assignDepthOrder(items: readonly DepthItem[]): number[] {\n const out = items.map(i => i.stackIndex);\n let i = 0;\n while (i < items.length) {\n if (!items[i]!.threeD) { i++; continue; }\n let j = i;\n while (j + 1 < items.length && items[j + 1]!.threeD) j++;\n const run = items.slice(i, j + 1).map((it, k) => ({ it, pos: i + k }));\n const slots = run.map(r => r.it.stackIndex);\n const farthestFirst = [...run].sort((a, b) => finite(b.it.depth) - finite(a.it.depth));\n farthestFirst.forEach((r, k) => { out[r.pos] = slots[k]!; });\n i = j + 1;\n }\n return out;\n}\n","import { Container, Matrix, PerspectiveMesh, RenderTexture, Texture } from 'pixi.js';\nimport type { Sequence } from '../sequences/Base';\nimport { describeLayer } from '../core/lint';\nimport { DEG, projectLayer, type CameraBasis, type LayerTransform, type Rect } from './math';\n\n/** Render textures are capped at this many pixels on the long side; larger layers are downscaled. */\nexport const MAX_TEXTURE_SIZE = 4096;\n/**\n * Render textures are drawn at this multiple of the layer size (until the caps),\n * so a layer enlarged by perspective (z > 0) stays sharp instead of showing\n * jagged edges and soft text.\n */\nexport const SUPERSAMPLE = 2;\n/** Total texture pixels per layer are capped here (≈ one 2048² target); resolution drops to fit. */\nexport const MAX_TEXTURE_PIXELS = 2048 * 2048;\n/** MSAA multiplies target memory ~4x, so only small textures get it (supersampling covers the rest). */\nexport const ANTIALIAS_MAX_PIXELS = 1024 * 1024;\n/** Mesh grid per side. 20 keeps steeply tilted planes free of visible affine warping. */\nexport const MESH_GRID = 20;\n\n/** The slice of a Pixi renderer Layer3D needs (also what tests fake). */\nexport interface SpaceHost {\n render(options: {\n container: Container;\n target: RenderTexture;\n transform: Matrix;\n clear: boolean;\n clearColor: number[];\n }): void;\n}\n\ntype Carrier = Container & { z?: number; rotationX?: number; rotationY?: number };\n\ninterface TextureSize { w: number; h: number; resolution: number; antialias: boolean }\n\n/** Sum of the target's filter paddings: the texture must be this much larger on every side or filter output is clipped. */\nfunction filterPadding(target: Container): number {\n const filters = (target as unknown as { filters?: ReadonlyArray<{ padding?: number }> | null }).filters;\n if (!Array.isArray(filters)) return 0;\n let pad = 0;\n for (const f of filters) pad += f?.padding ?? 0;\n return Number.isFinite(pad) && pad > 0 ? Math.ceil(pad) : 0;\n}\n\nexport function readLayerTransform(target: Container): LayerTransform {\n const c = target as Carrier;\n return {\n x: c.x, y: c.y, z: c.z ?? 0,\n rotationX: (c.rotationX ?? 0) * DEG,\n rotationY: (c.rotationY ?? 0) * DEG,\n rotationZ: c.rotation,\n scaleX: c.scale.x, scaleY: c.scale.y,\n pivotX: c.pivot.x, pivotY: c.pivot.y,\n };\n}\n\n/**\n * Draws one `threeD` sequence: its display object is rendered into a\n * RenderTexture (with its own 2D transform replaced, so layer-local content\n * lands at the texture origin) and shown on a PerspectiveMesh whose four\n * corners come from projecting the layer through the active camera.\n *\n * The sequence's `target` is never in the scene graph; the composition adds\n * `display` instead. `z`, `rotationX`, `rotationY` live on `target` as plain\n * numeric props so GSAP tweens them like any other prop.\n */\nexport class Layer3D {\n readonly display: PerspectiveMesh;\n /** Camera-space depth from the last update (larger = farther). */\n depth = 0;\n private rt: RenderTexture | null = null;\n private size: TextureSize | null = null;\n private warnedBehind = false;\n\n constructor(\n private readonly seq: Sequence,\n private readonly frameOf: () => Rect,\n ) {\n const target = seq.target as Carrier;\n target.z ??= 0;\n target.rotationX ??= 0;\n target.rotationY ??= 0;\n this.display = new PerspectiveMesh({ texture: Texture.WHITE, verticesX: MESH_GRID, verticesY: MESH_GRID });\n if (seq.spec.name) this.display.label = seq.spec.name;\n this.display.visible = false;\n }\n\n update(host: SpaceHost, basis: CameraBasis): void {\n const target = this.seq.target as Carrier | null;\n // Pixi skips rendering (and clearing) a container that is not `visible`\n // (e.g. PixiPlugin autoAlpha at alpha 0), which would leave a stale texture.\n if (!target || !target.renderable || !target.visible) return this.hide();\n\n const bounds = this.frameOf();\n const pad = filterPadding(target);\n const needW = Math.ceil(bounds.width + 2 * pad);\n const needH = Math.ceil(bounds.height + 2 * pad);\n if (!(needW >= 1 && needH >= 1) || !Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) return this.hide();\n\n const size = this.sizeFor(needW, needH);\n // The quad covers exactly the texture's pixel rect in layer space.\n const frame: Rect = { x: bounds.x - pad, y: bounds.y - pad, width: size.w, height: size.h };\n const projected = projectLayer(readLayerTransform(target), frame, basis);\n this.depth = projected.depth;\n if (!projected.visible) {\n if (!this.warnedBehind) {\n this.warnedBehind = true;\n console.warn(\n `pixi-effects: ${describeLayer(this.seq.spec)} is at or behind the camera plane (z = ${(target.z ?? 0).toFixed(0)}) and is hidden. ` +\n `If that is unintended, lower its z or move the camera back (the default camera sits at z = (height/2)/tan(fov/2), about 989 for 720p at fov 40).`,\n );\n }\n return this.hide();\n }\n\n this.ensureTexture(size);\n // `transform` replaces the container's own local transform for this render\n // (Pixi RenderGroupSystem), while `container.alpha` still applies — so the\n // texture carries the layer's alpha and the mesh alpha stays at 1.\n host.render({\n container: target,\n target: this.rt!,\n transform: new Matrix().translate(-frame.x, -frame.y),\n clear: true,\n clearColor: [0, 0, 0, 0],\n });\n this.display.geometry.setCorners(...projected.corners);\n this.display.visible = true;\n }\n\n destroy(): void {\n this.display.destroy();\n this.rt?.destroy(true);\n this.rt = null;\n }\n\n private hide(): void {\n this.display.visible = false;\n }\n\n /**\n * Texture size for content of w×h. An existing texture is kept while it is at\n * least that big and at most 2x too big, so content whose bounds change every\n * frame (typewriter text, growing shapes) does not reallocate each frame.\n */\n private sizeFor(w: number, h: number): TextureSize {\n const cur = this.size;\n if (cur && cur.w >= w && cur.h >= h && cur.w <= 2 * w && cur.h <= 2 * h) return cur;\n const resolution = Math.min(\n SUPERSAMPLE,\n MAX_TEXTURE_SIZE / Math.max(w, h),\n Math.sqrt(MAX_TEXTURE_PIXELS / (w * h)),\n );\n const antialias = w * h * resolution * resolution <= ANTIALIAS_MAX_PIXELS;\n return { w, h, resolution, antialias };\n }\n\n private ensureTexture(size: TextureSize): void {\n if (this.rt && this.size === size) return;\n const next = RenderTexture.create({\n width: size.w, height: size.h, resolution: size.resolution, antialias: size.antialias,\n });\n this.display.texture = next;\n this.rt?.destroy(true);\n this.rt = next;\n this.size = size;\n }\n}\n","import { collectPropKeys } from './specKeys';\nimport { describeLayer } from '../core/lint';\nimport type { SequenceSpec } from '../types';\n\ntype Warn = (message: string) => void;\nconst defaultWarn: Warn = m => console.warn(m);\n\nconst FOV_HINT = 'perspective is the camera\\'s \"fov\" — add a { type: \"camera\" } layer and set fov in its initial / keyframes';\n\n/** Keys that are never valid for any layer, with a hint at what the author probably meant. */\nconst LAYER_ALIASES: Record<string, string> = {\n rotateX: 'did you mean \"rotationX\"?',\n rotateY: 'did you mean \"rotationY\"?',\n rotateZ: 'did you mean \"rotation\"?',\n rotationZ: 'did you mean \"rotation\" (it is the Z rotation)?',\n translateZ: 'did you mean \"z\"?',\n depth: 'did you mean \"z\"?',\n posZ: 'did you mean \"z\"?',\n perspective: FOV_HINT,\n zoom: FOV_HINT,\n};\n\n/** Camera-only mistakes. */\nconst CAMERA_ALIASES: Record<string, string> = {\n pointOfInterest: 'did you mean \"lookAtX / lookAtY / lookAtZ\"?',\n lookAt: 'did you mean \"lookAtX / lookAtY / lookAtZ\"?',\n};\n\nconst CAMERA_PROPS = ['x', 'y', 'z', 'fov', 'lookAtX', 'lookAtY', 'lookAtZ'];\nconst NEEDS_THREE_D = ['z', 'rotationX', 'rotationY'];\nconst SKEW_KEYS = ['skew', 'skewX', 'skewY'];\n\n/**\n * Warn (never throw) about the inputs an AI author is most likely to get wrong,\n * with a message that says what to change. One call per layer, at build time.\n */\nexport function lintSequence(spec: SequenceSpec, warn: Warn = defaultWarn): void {\n const who = describeLayer(spec);\n const keys = collectPropKeys(spec);\n const explained = new Set<string>();\n\n for (const k of keys) {\n const hint = LAYER_ALIASES[k] ?? (spec.type === 'camera' ? CAMERA_ALIASES[k] : undefined);\n if (hint) {\n explained.add(k);\n warn(`pixi-effects: ${who}: \"${k}\" is not a property — ${hint}`);\n }\n }\n\n if (spec.type === 'camera') {\n const raw = spec as unknown as Record<string, unknown>;\n for (const p of CAMERA_PROPS) {\n if (p in raw) warn(`pixi-effects: ${who}: \"${p}\" must go inside initial / keyframes, not on the camera itself`);\n }\n for (const k of Object.keys(raw)) {\n const hint = CAMERA_ALIASES[k] ?? LAYER_ALIASES[k];\n if (hint) warn(`pixi-effects: ${who}: \"${k}\" is not a property — ${hint} (inside initial)`);\n }\n for (const k of keys) {\n if (!explained.has(k) && !CAMERA_PROPS.includes(k)) {\n warn(`pixi-effects: ${who}: \"${k}\" has no effect on a camera (use ${CAMERA_PROPS.join(', ')})`);\n }\n }\n return;\n }\n\n if (spec.type === 'audio') {\n if (spec.threeD) warn(`pixi-effects: ${who}: threeD has no effect on audio`);\n return;\n }\n\n if (!spec.threeD) {\n for (const k of NEEDS_THREE_D) {\n if (keys.has(k)) warn(`pixi-effects: ${who}: \"${k}\" needs threeD: true (it is ignored otherwise)`);\n }\n } else {\n for (const k of SKEW_KEYS) {\n if (keys.has(k)) warn(`pixi-effects: ${who}: \"${k}\" is ignored on threeD layers`);\n }\n }\n}\n","import { Container, Rectangle } from 'pixi.js';\nimport { Sequence } from './Base';\nimport { buildSequenceTree } from '../core/Composition';\nimport { CameraSequence } from '../space/CameraSequence';\nimport { findOverlap, pickActiveCamera } from '../space/camera';\nimport { assignDepthOrder } from '../space/depth';\nimport { Layer3D, type SpaceHost } from '../space/Layer3D';\nimport { lintSequence } from '../space/lint';\nimport { describeLayer, lintText, lintTiming } from '../core/lint';\nimport { cameraBasis, homeCamera } from '../space/math';\nimport type { CompositionSequenceSpec, AudioDescriptor, CompositionShape, SequenceSpec } from '../types';\n\nimport type { gsap } from 'gsap';\ntype Timeline = ReturnType<typeof gsap.timeline>;\n\nexport class CompositionSequence extends Sequence {\n declare spec: CompositionSequenceSpec;\n private _innerContainer: Container | null = null;\n private _compositionShape: CompositionShape | null = null;\n _children: Sequence[] = [];\n private _cameras: CameraSequence[] = [];\n private _layers3d: Layer3D[] = [];\n /** Drawn children in stack order (cameras and target-less sequences excluded). */\n private _visual: Array<{ seq: Sequence; layer: Layer3D | null }> = [];\n\n async build(): Promise<void> {\n const width = this.spec.width ?? this.parent?.width ?? this.root.width;\n const height = this.spec.height ?? this.parent?.height ?? this.root.height;\n if (this.duration === undefined) {\n this.duration = this.spec.duration ?? this.parent?.duration ?? this.root.duration;\n }\n const wrapper = new Container();\n wrapper.cullable = true;\n wrapper.cullableChildren = true;\n wrapper.cullArea = new Rectangle(0, 0, width, height);\n\n const inner = new Container();\n inner.cullable = true;\n inner.cullableChildren = true;\n wrapper.addChild(inner);\n\n this.target = wrapper;\n this.intrinsicWidth = width;\n this.intrinsicHeight = height;\n this._innerContainer = inner;\n this._compositionShape = { width, height, duration: this.duration };\n\n for (const s of this.spec.sequences ?? []) {\n lintSequence(s);\n lintTiming(s, this.duration);\n lintText(s);\n }\n\n this._children = await buildSequenceTree(\n this.spec.sequences ?? [],\n this._compositionShape,\n this.root,\n );\n for (const child of this._children) {\n // Cameras are display-less: they only feed the projection pass.\n if (child instanceof CameraSequence) {\n this._cameras.push(child);\n continue;\n }\n if (!child.target) continue;\n\n const maskSpec = (child.spec as { mask?: SequenceSpec }).mask;\n\n // threeD layers never enter the scene graph themselves: their display\n // object is rendered into a texture and a perspective mesh stands in.\n if (child.spec.threeD) {\n const layer = new Layer3D(child, frameOf(child));\n inner.addChild(layer.display);\n this._layers3d.push(layer);\n this._visual.push({ seq: child, layer });\n if (maskSpec) {\n console.warn(`pixi-effects: ${describeLayer(child.spec)}: mask is not supported on threeD layers yet; ignored`);\n }\n continue;\n }\n\n inner.addChild(child.target);\n this._visual.push({ seq: child, layer: null });\n // If this child has a `mask` spec, build the mask sequence in the same\n // composition shape, add its target to the same parent (so its\n // transforms resolve in the same coord space), and wire PIXI's\n // mask channel. PIXI v8 renders mask containers into the stencil /\n // alpha buffer; they don't render as normal children.\n if (maskSpec) {\n const built = await buildSequenceTree([maskSpec], this._compositionShape, this.root);\n const maskSeq = built[0];\n if (maskSeq?.target) {\n inner.addChild(maskSeq.target);\n // PIXI v8 `setMask` accepts an `inverse` flag — that's how we\n // expose `maskInverted` from the spec. Falls back to plain\n // `target.mask = …` for runtimes that don't have setMask\n // (older PIXI builds).\n const inverse = (child.spec as { maskInverted?: boolean }).maskInverted ?? false;\n const t = child.target as Container & {\n setMask?: (opts: { mask: Container | null; inverse?: boolean }) => void;\n mask: Container | null;\n };\n if (typeof t.setMask === 'function') {\n t.setMask({ mask: maskSeq.target, inverse });\n } else {\n t.mask = maskSeq.target;\n }\n child.maskSequence = maskSeq;\n }\n }\n }\n\n if (this._layers3d.length > 0) {\n // Stack order becomes explicit zIndex so threeD layers can be re-sorted\n // by depth each frame without reparenting.\n inner.sortableChildren = true;\n this._visual.forEach((v, i) => {\n (v.layer?.display ?? v.seq.target!).zIndex = i;\n });\n } else if (this._cameras.length > 0) {\n console.warn('pixi-effects: camera has no effect: this composition has no threeD layers');\n }\n\n this.buildFilters();\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n // Children's `at` is relative to this composition's start, so push them\n // forward by our absolute start time on the global timeline.\n const childOffset = offset + this.at;\n for (const child of this._children) {\n child.bindTimeline(timeline, childOffset);\n // The mask shares the maskee's offset — its `at` is interpreted\n // relative to the composition's start, just like the child itself,\n // so a reveal-from-zero animation lines up naturally.\n child.maskSequence?.bindTimeline(timeline, childOffset);\n }\n const overlap = findOverlap(this._cameras.map(c => c.window()));\n if (overlap) {\n console.warn(`pixi-effects: cameras #${overlap[0] + 1} and #${overlap[1] + 1} overlap in time; the top-most one wins`);\n }\n }\n\n /** Drawn children in stack order, with the display object that stands in for each (the mesh for a threeD layer). */\n layers(): Array<{ seq: Sequence; display: Container; threeD: boolean }> {\n return this._visual.map(v => ({\n seq: v.seq,\n display: (v.layer?.display ?? v.seq.target!) as unknown as Container,\n threeD: v.layer !== null,\n }));\n }\n\n override updateSpace(t: number, host: SpaceHost): void {\n // Inner compositions first: a threeD composition is rendered into its own\n // texture by this level, so its content must already be projected.\n for (const child of this._children) child.updateSpace(t, host);\n if (this._layers3d.length === 0 || !this._compositionShape) return;\n\n const { width, height } = this._compositionShape;\n const compEnd = (this.absoluteStart ?? 0) + (this.duration ?? 0);\n const active = pickActiveCamera(\n this._cameras.map(cam => ({ cam, ...cam.window() })),\n t,\n compEnd,\n );\n const basis = cameraBasis(active ? active.cam.state() : homeCamera(width, height), width, height);\n\n for (const layer of this._layers3d) layer.update(host, basis);\n\n const order = assignDepthOrder(\n this._visual.map((v, i) => ({ stackIndex: i, threeD: v.layer !== null, depth: v.layer?.depth ?? 0 })),\n );\n this._visual.forEach((v, i) => {\n if (v.layer) v.layer.display.zIndex = order[i]!;\n });\n }\n\n override collectAudio(out: AudioDescriptor[], baseTime: number): void {\n super.collectAudio(out, baseTime);\n const childBase = baseTime + this.at;\n for (const child of this._children) child.collectAudio(out, childBase);\n }\n\n override destroy(): void {\n for (const l of this._layers3d) l.destroy();\n this._layers3d = [];\n for (const c of this._children) c.destroy();\n super.destroy();\n }\n}\n\n/** Layer-space rectangle a threeD child projects: a composition's frame, otherwise its content bounds. */\nfunction frameOf(child: Sequence): () => { x: number; y: number; width: number; height: number } {\n if (child instanceof CompositionSequence) {\n return () => ({ x: 0, y: 0, width: child.intrinsicWidth, height: child.intrinsicHeight });\n }\n return () => child.target!.getLocalBounds();\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk64IHCYYN_cjs = require('./chunk-64IHCYYN.cjs');
4
- var chunk7OIWYXGV_cjs = require('./chunk-7OIWYXGV.cjs');
3
+ var chunkZL262ZRM_cjs = require('./chunk-ZL262ZRM.cjs');
4
+ var chunkSIRVULFF_cjs = require('./chunk-SIRVULFF.cjs');
5
5
  var PIXI = require('pixi.js');
6
6
  var gsap = require('gsap');
7
7
  var PixiPlugin = require('gsap/PixiPlugin');
@@ -617,43 +617,48 @@ function expandTransitions(spec) {
617
617
  if (toUses > 1) {
618
618
  throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
619
619
  }
620
- const tStart = chunk7OIWYXGV_cjs.resolveAt(t.at, parentDuration);
620
+ const tStart = chunkSIRVULFF_cjs.resolveAt(t.at, parentDuration);
621
621
  const tEnd = tStart + t.duration;
622
622
  const fromSeq = fromEntry.seq;
623
- const fromStart = chunk7OIWYXGV_cjs.resolveAt(fromSeq.at, parentDuration);
623
+ const fromStart = chunkSIRVULFF_cjs.resolveAt(fromSeq.at, parentDuration);
624
624
  const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
625
625
  if (tStart < fromStart || tEnd > fromEnd) {
626
626
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
627
627
  }
628
628
  const toSeq = toEntry.seq;
629
- const toStart = chunk7OIWYXGV_cjs.resolveAt(toSeq.at, parentDuration);
629
+ const toStart = chunkSIRVULFF_cjs.resolveAt(toSeq.at, parentDuration);
630
630
  const toEnd = toStart + (toSeq.duration ?? parentDuration);
631
631
  if (tStart < toStart || tEnd > toEnd) {
632
632
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
633
633
  }
634
- switch (t.kind) {
634
+ const abs = { ...t, at: tStart };
635
+ const nFrom = keyframeCount(fromEntry.seq);
636
+ const nTo = keyframeCount(toEntry.seq);
637
+ switch (abs.kind) {
635
638
  case "crossfade":
636
- expandCrossfade(out, t, fromEntry.seq, toEntry.seq);
639
+ expandCrossfade(out, abs, fromEntry.seq, toEntry.seq);
637
640
  break;
638
641
  case "wipe":
639
- expandMask(out, t, fromEntry.seq, toEntry.seq, i, wipeMode(t.direction), t.smoothing);
642
+ expandMask(out, abs, fromEntry.seq, toEntry.seq, i, wipeMode(abs.direction), abs.smoothing);
640
643
  break;
641
644
  case "iris":
642
- expandMask(out, t, fromEntry.seq, toEntry.seq, i, t.mode === "out" ? "iris-out" : "iris-in", t.smoothing);
645
+ expandMask(out, abs, fromEntry.seq, toEntry.seq, i, abs.mode === "out" ? "iris-out" : "iris-in", abs.smoothing);
643
646
  break;
644
647
  case "slide":
645
- expandSlide(out, t, fromEntry.seq, toEntry.seq);
648
+ expandSlide(out, abs, fromEntry.seq, toEntry.seq);
646
649
  break;
647
650
  case "dip":
648
- expandDip(out, t, fromEntry.seq, toEntry.seq);
651
+ expandDip(out, abs, fromEntry.seq, toEntry.seq);
649
652
  break;
650
653
  case "zoom":
651
- expandZoom(out, t, fromEntry.seq, toEntry.seq);
654
+ expandZoom(out, abs, fromEntry.seq, toEntry.seq);
652
655
  break;
653
656
  case "dissolve":
654
- expandDissolve(out, t, fromEntry.seq, toEntry.seq, i);
657
+ expandDissolve(out, abs, fromEntry.seq, toEntry.seq, i);
655
658
  break;
656
659
  }
660
+ rebaseNewKeyframes(fromEntry.seq, nFrom, fromStart);
661
+ rebaseNewKeyframes(toEntry.seq, nTo, toStart);
657
662
  }
658
663
  delete out.transitions;
659
664
  return out;
@@ -685,6 +690,17 @@ function wrapAsFullComposition(seq, compW, compH) {
685
690
  sequences: [inner]
686
691
  };
687
692
  }
693
+ function keyframeCount(seq) {
694
+ return seq.keyframes?.length ?? 0;
695
+ }
696
+ function rebaseNewKeyframes(seq, from, seqStart) {
697
+ const kfs = seq.keyframes;
698
+ if (!kfs) return;
699
+ for (let i = from; i < kfs.length; i++) {
700
+ const kf = kfs[i];
701
+ if (typeof kf.at === "number") kfs[i] = { ...kf, at: kf.at - seqStart };
702
+ }
703
+ }
688
704
  function ensureKeyframes(seq) {
689
705
  const s = seq;
690
706
  if (!s.keyframes) s.keyframes = [];
@@ -901,6 +917,153 @@ function rejectReservedNameCollision(filters, seqName) {
901
917
  }
902
918
  }
903
919
 
920
+ // src/core/inspect.ts
921
+ var FAINT = 0.3;
922
+ var intersection = (a, b) => {
923
+ const w = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);
924
+ const h = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);
925
+ return w > 0 && h > 0 ? w * h : 0;
926
+ };
927
+ function inspectScene(root, frame, time, canvas, opts = {}) {
928
+ const layers = [];
929
+ const view = { x: 0, y: 0, width: canvas.width, height: canvas.height };
930
+ const walk = (comp, prefix, insideThreeD, parentVisible) => {
931
+ comp.layers().forEach(({ seq, display, threeD }, i) => {
932
+ const t = seq.target;
933
+ const name = seq.spec.name;
934
+ const label = name ?? `${seq.spec.type}#${i}`;
935
+ const alpha = t?.alpha ?? 1;
936
+ const alive = threeD ? display.visible : t?.renderable ?? true;
937
+ const visible = parentVisible && alive && alpha > 0;
938
+ let bounds = null;
939
+ if (!insideThreeD) {
940
+ const b = display.getBounds();
941
+ bounds = { x: b.x, y: b.y, width: b.width, height: b.height };
942
+ }
943
+ let onCanvas = null;
944
+ if (bounds) {
945
+ const inter = intersection(bounds, view);
946
+ const area = bounds.width * bounds.height;
947
+ onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
948
+ if (area === 0) onCanvas = "none";
949
+ }
950
+ const keys = chunkSIRVULFF_cjs.collectPropKeys(seq.spec);
951
+ const moving = (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
952
+ layers.push({ path: prefix + label, name, type: seq.spec.type, threeD, visible, alpha, moving, bounds, onCanvas });
953
+ if (seq instanceof chunkZL262ZRM_cjs.CompositionSequence) walk(seq, prefix + label + "/", insideThreeD || threeD, visible);
954
+ });
955
+ };
956
+ walk(root, "", false, true);
957
+ const issues = [];
958
+ const texts = layers.filter((l) => l.type === "text" && l.visible && l.alpha >= FAINT && l.bounds);
959
+ for (const l of texts) {
960
+ const b = l.bounds;
961
+ const who = `text layer "${l.path}"`;
962
+ if (b.width < 1 || b.height < 1) {
963
+ issues.push(`${who} has no size (empty text, or not drawn yet)`);
964
+ } else if (l.moving) ; else if (l.onCanvas === "none") {
965
+ issues.push(`${who} is entirely outside the canvas (at ${Math.round(b.x)},${Math.round(b.y)}, ${Math.round(b.width)}\xD7${Math.round(b.height)})`);
966
+ } else if (l.onCanvas === "partial") {
967
+ const over = [];
968
+ if (b.x < 0) over.push(`${Math.round(-b.x)}px beyond the left edge`);
969
+ if (b.x + b.width > canvas.width) over.push(`${Math.round(b.x + b.width - canvas.width)}px beyond the right edge`);
970
+ if (b.y < 0) over.push(`${Math.round(-b.y)}px beyond the top edge`);
971
+ if (b.y + b.height > canvas.height) over.push(`${Math.round(b.y + b.height - canvas.height)}px beyond the bottom edge`);
972
+ issues.push(`${who} is cut off by the canvas edge: ${over.join(", ")}`);
973
+ }
974
+ }
975
+ for (let i = 0; i < texts.length; i++) {
976
+ for (let j = i + 1; j < texts.length; j++) {
977
+ const a = texts[i].bounds, b = texts[j].bounds;
978
+ const smaller = Math.min(a.width * a.height, b.width * b.height);
979
+ if (smaller <= 0) continue;
980
+ const share = intersection(a, b) / smaller;
981
+ if (share > 0.25) issues.push(`text layers "${texts[i].path}" and "${texts[j].path}" overlap by ${Math.round(share * 100)}% of the smaller one`);
982
+ }
983
+ }
984
+ const mode = opts.layers ?? "all";
985
+ const listed = mode === "none" ? [] : mode === "visible" ? layers.filter((l) => l.visible) : layers;
986
+ return { frame, time, canvas, summary: { layers: layers.length, visible: layers.filter((l) => l.visible).length }, issues, layers: listed };
987
+ }
988
+
989
+ // src/core/frames.ts
990
+ function pickFrames(lastFrame, count) {
991
+ const last = Math.max(0, Math.floor(lastFrame));
992
+ const n = Math.max(1, Math.floor(count));
993
+ if (n === 1) return [0];
994
+ const out = [];
995
+ for (let i = 0; i < n; i++) {
996
+ const f = Math.round(last * i / (n - 1));
997
+ if (out[out.length - 1] !== f) out.push(f);
998
+ }
999
+ return out;
1000
+ }
1001
+ function sheetLayout(n, columns, cellW, srcW, srcH, labelH) {
1002
+ const cols = Math.max(1, Math.min(Math.floor(columns), n));
1003
+ const rows = Math.ceil(n / cols);
1004
+ const cellH = Math.round(cellW * srcH / srcW);
1005
+ const positions = Array.from({ length: n }, (_, i) => ({ x: i % cols * cellW, y: Math.floor(i / cols) * (cellH + labelH) }));
1006
+ return { cols, rows, cellW, cellH, width: cols * cellW, height: rows * (cellH + labelH), positions };
1007
+ }
1008
+
1009
+ // src/core/options.ts
1010
+ function distance(a, b) {
1011
+ const dp = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]);
1012
+ for (let j = 1; j <= b.length; j++) dp[0][j] = j;
1013
+ for (let i = 1; i <= a.length; i++) {
1014
+ for (let j = 1; j <= b.length; j++) {
1015
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
1016
+ if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + 1);
1017
+ }
1018
+ }
1019
+ return dp[a.length][b.length];
1020
+ }
1021
+ var isSubsequence = (small, big) => {
1022
+ let i = 0;
1023
+ for (const ch of big) if (i < small.length && ch === small[i]) i++;
1024
+ return i === small.length;
1025
+ };
1026
+ var COMMON_ALIASES = {
1027
+ fps: "frameRate",
1028
+ framerate: "frameRate",
1029
+ frame_rate: "frameRate",
1030
+ bg: "background",
1031
+ backgroundcolor: "background",
1032
+ bgcolor: "background",
1033
+ seconds: "duration",
1034
+ length: "duration",
1035
+ time: "duration",
1036
+ w: "width",
1037
+ h: "height",
1038
+ cols: "columns",
1039
+ sweep: "degrees",
1040
+ angle: "degrees"
1041
+ };
1042
+ function suggestName(name, valid) {
1043
+ const n = name.toLowerCase();
1044
+ const alias = COMMON_ALIASES[n];
1045
+ if (alias && valid.includes(alias)) return alias;
1046
+ let best = null;
1047
+ for (const v of valid) {
1048
+ const lv = v.toLowerCase();
1049
+ const d = distance(n, lv);
1050
+ const close = d <= Math.max(1, Math.floor(Math.min(n.length, lv.length) / 3));
1051
+ const abbreviation = n.length >= 3 && isSubsequence(n, lv) || lv.length >= 2 && n.length > lv.length && n.includes(lv);
1052
+ if (!close && !abbreviation) continue;
1053
+ const score = close ? d : 3 + (lv.length - n.length) / 100;
1054
+ if (!best || score < best.score) best = { v, score };
1055
+ }
1056
+ return best ? best.v : null;
1057
+ }
1058
+ function warnUnknownOptions(where, opts, valid) {
1059
+ if (!opts || typeof opts !== "object") return;
1060
+ for (const key of Object.keys(opts)) {
1061
+ if (valid.includes(key)) continue;
1062
+ const guess = suggestName(key, valid);
1063
+ console.warn(`pixi-effects: ${where}: unknown option "${key}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${valid.join(", ")})`);
1064
+ }
1065
+ }
1066
+
904
1067
  // src/core/Movie.ts
905
1068
  PIXI.extensions.add(PIXI.CullerPlugin);
906
1069
  gsap.gsap.registerPlugin(PixiPlugin.PixiPlugin);
@@ -959,6 +1122,7 @@ var Movie = class {
959
1122
  return this._audioContext;
960
1123
  }
961
1124
  async init(options = {}) {
1125
+ warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition"]);
962
1126
  this._initState = "pending";
963
1127
  try {
964
1128
  this.width = options.width ?? 1920;
@@ -1010,7 +1174,7 @@ var Movie = class {
1010
1174
  duration: this.duration,
1011
1175
  ...userComposition
1012
1176
  };
1013
- const composition = new chunk64IHCYYN_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
1177
+ const composition = new chunkZL262ZRM_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
1014
1178
  await composition.build();
1015
1179
  this._rootSequence = composition;
1016
1180
  if (composition.target) root.addChild(composition.target);
@@ -1023,7 +1187,7 @@ var Movie = class {
1023
1187
  this.timeline.progress(1).progress(0);
1024
1188
  await this._awaitVideoFrames();
1025
1189
  this._updateSpace();
1026
- this.app.renderer.render({ container: this.app.stage });
1190
+ this._renderNow();
1027
1191
  this._initState = "ready";
1028
1192
  this.emit("ready");
1029
1193
  } catch (err) {
@@ -1042,7 +1206,7 @@ var Movie = class {
1042
1206
  this.timeline.time(this.currentFrame / this.frameRate);
1043
1207
  await this._awaitVideoFrames();
1044
1208
  this._updateSpace();
1045
- this.app?.renderer?.render({ container: this.app.stage });
1209
+ this._renderNow();
1046
1210
  this.emit("frame", { frame: this.currentFrame, totalFrames: this.totalFrames });
1047
1211
  }
1048
1212
  async _awaitVideoFrames() {
@@ -1056,6 +1220,75 @@ var Movie = class {
1056
1220
  return v.awaitFrameAt(local);
1057
1221
  }));
1058
1222
  }
1223
+ async snapshot(frame = this.currentFrame, opts = {}) {
1224
+ warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as"]);
1225
+ this._requireReady("snapshot");
1226
+ await this.gotoFrame(clampFrame(frame, this.totalFrames), true);
1227
+ const scale = opts.scale ?? 1;
1228
+ const out = document.createElement("canvas");
1229
+ out.width = Math.max(1, Math.round(this.width * scale));
1230
+ out.height = Math.max(1, Math.round(this.height * scale));
1231
+ out.getContext("2d").drawImage(this.app.canvas, 0, 0, out.width, out.height);
1232
+ return encodeCanvas(out, opts.type ?? "image/png", opts.as ?? "blob");
1233
+ }
1234
+ async contactSheet(opts = {}) {
1235
+ warnUnknownOptions("movie.contactSheet()", opts, ["frames", "times", "count", "columns", "cellWidth", "as"]);
1236
+ this._requireReady("contactSheet");
1237
+ const frames = (opts.frames ?? opts.times?.map((t) => Math.round(t * this.frameRate)) ?? pickFrames(this.totalFrames, opts.count ?? 6)).map((f) => clampFrame(f, this.totalFrames));
1238
+ const LABEL_H = 26;
1239
+ const L = sheetLayout(frames.length, opts.columns ?? 3, opts.cellWidth ?? 480, this.width, this.height, LABEL_H);
1240
+ const sheet = document.createElement("canvas");
1241
+ sheet.width = L.width;
1242
+ sheet.height = L.height;
1243
+ const g = sheet.getContext("2d");
1244
+ g.fillStyle = "#10131c";
1245
+ g.fillRect(0, 0, L.width, L.height);
1246
+ const back = this.currentFrame;
1247
+ try {
1248
+ for (let i = 0; i < frames.length; i++) {
1249
+ const f = frames[i];
1250
+ await this.gotoFrame(f, true);
1251
+ const { x, y } = L.positions[i];
1252
+ g.drawImage(this.app.canvas, x, y + LABEL_H, L.cellW, L.cellH);
1253
+ g.fillStyle = "#e8ecf8";
1254
+ g.font = "600 15px system-ui, sans-serif";
1255
+ g.textBaseline = "middle";
1256
+ g.fillText(`frame ${f} \xB7 ${(f / this.frameRate).toFixed(2)}s`, x + 8, y + LABEL_H / 2);
1257
+ }
1258
+ } finally {
1259
+ await this.gotoFrame(back, true);
1260
+ }
1261
+ return encodeCanvas(sheet, "image/png", opts.as ?? "blob");
1262
+ }
1263
+ /**
1264
+ * Where every layer is drawn at `frame` (canvas pixels, visibility) plus `issues` — text that is off
1265
+ * the canvas, cut by an edge, empty, or overlapping other text. Seeks there and stays there.
1266
+ */
1267
+ async inspect(frame = this.currentFrame, opts = { layers: "visible" }) {
1268
+ warnUnknownOptions("movie.inspect()", opts, ["layers"]);
1269
+ this._requireReady("inspect");
1270
+ const f = clampFrame(frame, this.totalFrames);
1271
+ await this.gotoFrame(f, true);
1272
+ return inspectScene(this._rootSequence, f, f / this.frameRate, { width: this.width, height: this.height }, opts);
1273
+ }
1274
+ /**
1275
+ * Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
1276
+ * by hand — while seeking and especially during `render()`, which stops the ticker — so without this the
1277
+ * `culled` flags are whatever the last tick left: a layer that is now on screen can stay culled and be
1278
+ * missing from the frame or from the exported video. Cull again (updating transforms: the timeline just
1279
+ * moved things) right before drawing.
1280
+ */
1281
+ _renderNow() {
1282
+ const app = this.app;
1283
+ if (!app?.renderer) return;
1284
+ PIXI.Culler.shared.cull(app.stage, app.renderer.screen, false);
1285
+ app.renderer.render({ container: app.stage });
1286
+ }
1287
+ _requireReady(what) {
1288
+ if (this._initState !== "ready" || !this._rootSequence || !this.app) {
1289
+ throw new Error(`pixi-effects: movie.${what}() needs a ready movie \u2014 await movie.init(...) first`);
1290
+ }
1291
+ }
1059
1292
  /** Projects every `threeD` layer for the current frame (see src/space). */
1060
1293
  _updateSpace() {
1061
1294
  if (!this._rootSequence || !this.app) return;
@@ -1141,6 +1374,7 @@ var Movie = class {
1141
1374
  return this.muted;
1142
1375
  }
1143
1376
  async render(options) {
1377
+ warnUnknownOptions("movie.render()", options, ["format", "video", "audio"]);
1144
1378
  return await exportFrames(this, options);
1145
1379
  }
1146
1380
  async destroy() {
@@ -1158,6 +1392,11 @@ var Movie = class {
1158
1392
  this._initState = "destroyed";
1159
1393
  }
1160
1394
  };
1395
+ var clampFrame = (f, last) => Math.max(0, Math.min(Math.round(f), last));
1396
+ function encodeCanvas(canvas, type, as) {
1397
+ if (as === "dataURL") return Promise.resolve(canvas.toDataURL(type));
1398
+ return new Promise((resolve, reject) => canvas.toBlob((b) => b ? resolve(b) : reject(new Error("pixi-effects: could not encode the image")), type));
1399
+ }
1161
1400
  function safeRun(fn) {
1162
1401
  try {
1163
1402
  fn();
@@ -1176,7 +1415,9 @@ function collectVideoSequences(seq, out) {
1176
1415
  }
1177
1416
 
1178
1417
  // src/presets/kenBurns.ts
1418
+ var KEN_BURNS_KEYS = ["asset", "name", "at", "duration", "fit", "ease", "motion", "origin", "zoom", "direction", "angle", "from", "to"];
1179
1419
  function kenBurns(opts) {
1420
+ warnUnknownOptions("kenBurns()", opts, KEN_BURNS_KEYS);
1180
1421
  const {
1181
1422
  asset,
1182
1423
  name,
@@ -1186,7 +1427,6 @@ function kenBurns(opts) {
1186
1427
  ease = "sine.inOut"
1187
1428
  } = opts;
1188
1429
  const baseScale = fit;
1189
- const baseAt = at ?? 0;
1190
1430
  let initial;
1191
1431
  let keyframes;
1192
1432
  if (opts.motion === "still") {
@@ -1217,7 +1457,7 @@ function kenBurns(opts) {
1217
1457
  scale: initialScale
1218
1458
  };
1219
1459
  keyframes = [
1220
- { at: baseAt, to: { scale: `${baseScale} * ${toZ}` }, duration, ease }
1460
+ { at: 0, to: { scale: `${baseScale} * ${toZ}` }, duration, ease }
1221
1461
  ];
1222
1462
  } else if (opts.motion === "rotation") {
1223
1463
  const angle = clamp(opts.angle ?? 8, 0, 30);
@@ -1248,7 +1488,7 @@ function kenBurns(opts) {
1248
1488
  const tHere = duration * tFrac;
1249
1489
  const tPrev = duration * ((i - 1) / (sampleCount - 1));
1250
1490
  keyframes.push({
1251
- at: baseAt + tPrev,
1491
+ at: tPrev,
1252
1492
  to: { rotation: angleHere, scale: scaleAt(angleHere) },
1253
1493
  duration: tHere - tPrev,
1254
1494
  ease: i === 1 ? ease : "none"
@@ -1269,7 +1509,7 @@ function kenBurns(opts) {
1269
1509
  scale: scaleExpr
1270
1510
  };
1271
1511
  keyframes = [
1272
- { at: baseAt, to: { x: xExpr(to[0]), y: yExpr(to[1]) }, duration, ease }
1512
+ { at: 0, to: { x: xExpr(to[0]), y: yExpr(to[1]) }, duration, ease }
1273
1513
  ];
1274
1514
  }
1275
1515
  const spec = {
@@ -1286,13 +1526,72 @@ function kenBurns(opts) {
1286
1526
  function clamp(v, lo, hi) {
1287
1527
  return Math.max(lo, Math.min(hi, v));
1288
1528
  }
1529
+ function parseEase(name) {
1530
+ return gsap.gsap.parseEase(name);
1531
+ }
1532
+
1533
+ // src/presets/orbit.ts
1534
+ var ORBIT_KEYS = ["duration", "degrees", "start", "radius", "center", "width", "height", "fov", "ease", "dollyZoom", "at", "name", "stepsPerSecond"];
1535
+ function orbit(opts) {
1536
+ warnUnknownOptions("orbit()", opts, ORBIT_KEYS);
1537
+ const {
1538
+ duration,
1539
+ degrees,
1540
+ width = 1280,
1541
+ height = 720,
1542
+ fov,
1543
+ ease = "sine.inOut",
1544
+ stepsPerSecond = 10
1545
+ } = opts;
1546
+ if (!(duration > 0)) throw new Error(`pixi-effects: orbit duration must be > 0 (got ${duration})`);
1547
+ const dolly = opts.dollyZoom;
1548
+ if (dolly && opts.radius !== void 0) {
1549
+ throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
1550
+ }
1551
+ const [cx, cy] = opts.center ?? [width / 2, height / 2];
1552
+ const fixedR = opts.radius ?? chunkSIRVULFF_cjs.homeDistance(height, fov ?? chunkSIRVULFF_cjs.DEFAULT_FOV);
1553
+ const start = opts.start ?? -degrees / 2;
1554
+ const steps = Math.max(1, Math.round(duration * stepsPerSecond));
1555
+ const easeFn = parseEase(ease);
1556
+ const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
1557
+ const pos = (i) => {
1558
+ const p = i / steps;
1559
+ const a = (start + degrees * easeFn(p)) * chunkSIRVULFF_cjs.DEG;
1560
+ if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
1561
+ const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
1562
+ const R = chunkSIRVULFF_cjs.homeDistance(height, f);
1563
+ return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
1564
+ };
1565
+ const keyframes = [];
1566
+ for (let i = 0; i < steps; i++) {
1567
+ keyframes.push({ at: duration * i / steps, to: pos(i + 1), duration: duration / steps, ease: "none" });
1568
+ }
1569
+ const p0 = pos(0);
1570
+ const spec = {
1571
+ type: "camera",
1572
+ duration,
1573
+ initial: {
1574
+ x: p0.x,
1575
+ y: cy,
1576
+ z: p0.z,
1577
+ lookAtX: cx,
1578
+ lookAtY: cy,
1579
+ lookAtZ: 0,
1580
+ ...p0.fov !== void 0 ? { fov: p0.fov } : fov !== void 0 ? { fov } : {}
1581
+ },
1582
+ keyframes
1583
+ };
1584
+ if (opts.at !== void 0) spec.at = opts.at;
1585
+ if (opts.name !== void 0) spec.name = opts.name;
1586
+ return spec;
1587
+ }
1289
1588
 
1290
1589
  // src/transforms/withFade.ts
1291
1590
  function withFade(spec, opts) {
1292
- const at = spec.at ?? 0;
1591
+ warnUnknownOptions("withFade()", opts, ["in", "out"]);
1293
1592
  if (opts.in != null && opts.in > 0) {
1294
1593
  spec.initial = { ...spec.initial ?? {}, alpha: 0 };
1295
- const kf = { at, to: { alpha: 1 }, duration: opts.in };
1594
+ const kf = { at: 0, to: { alpha: 1 }, duration: opts.in };
1296
1595
  spec.keyframes = [...spec.keyframes ?? [], kf];
1297
1596
  }
1298
1597
  if (opts.out != null && opts.out > 0) {
@@ -1301,7 +1600,7 @@ function withFade(spec, opts) {
1301
1600
  "withFade(spec, { out }) requires spec.duration to be set so the fade-out can be anchored to the sequence end. Set spec.duration before passing the spec in."
1302
1601
  );
1303
1602
  }
1304
- const kf = { at: at + spec.duration - opts.out, to: { alpha: 0 }, duration: opts.out };
1603
+ const kf = { at: spec.duration - opts.out, to: { alpha: 0 }, duration: opts.out };
1305
1604
  spec.keyframes = [...spec.keyframes ?? [], kf];
1306
1605
  }
1307
1606
  return spec;
@@ -1309,10 +1608,11 @@ function withFade(spec, opts) {
1309
1608
 
1310
1609
  Object.defineProperty(exports, "registerSequenceType", {
1311
1610
  enumerable: true,
1312
- get: function () { return chunk7OIWYXGV_cjs.registerSequenceType; }
1611
+ get: function () { return chunkSIRVULFF_cjs.registerSequenceType; }
1313
1612
  });
1314
1613
  exports.Movie = Movie;
1315
1614
  exports.kenBurns = kenBurns;
1615
+ exports.orbit = orbit;
1316
1616
  exports.withFade = withFade;
1317
1617
  //# sourceMappingURL=index.cjs.map
1318
1618
  //# sourceMappingURL=index.cjs.map