pixi-effects 0.2.0 → 0.4.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.
- package/CHANGELOG.md +55 -0
- package/README.md +16 -6
- package/ai/SKILL.md +46 -0
- package/ai/reference/cheatsheet.md +121 -0
- package/ai/reference/pitfalls.md +75 -0
- package/ai/reference/recipes.md +375 -0
- package/ai/template.html +82 -0
- package/ai/tools/save-image.py +24 -0
- package/dist/{Base-Bh_VSusi.d.ts → Base-5R7C5pHR.d.cts} +7 -1
- package/dist/{Base-B1Tdn0Cv.d.cts → Base-DhY9oMxr.d.ts} +7 -1
- package/dist/Composition-D7RCAGEA.cjs +13 -0
- package/dist/{Composition-BI5HZJFL.cjs.map → Composition-D7RCAGEA.cjs.map} +1 -1
- package/dist/Composition-RGTRZ2JX.js +4 -0
- package/dist/{Composition-IO7ZN32J.js.map → Composition-RGTRZ2JX.js.map} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/Movie-CghFXprP.d.cts +179 -0
- package/dist/Movie-DRZtIGU7.d.ts +179 -0
- package/dist/{chunk-7OIWYXGV.cjs → chunk-6BQ6IEW2.cjs} +363 -91
- package/dist/chunk-6BQ6IEW2.cjs.map +1 -0
- package/dist/{chunk-H55V3U56.js → chunk-A574IA4F.js} +68 -13
- package/dist/chunk-A574IA4F.js.map +1 -0
- package/dist/{chunk-64IHCYYN.cjs → chunk-QGBOC5YL.cjs} +76 -21
- package/dist/chunk-QGBOC5YL.cjs.map +1 -0
- package/dist/{chunk-VJCDG6YG.js → chunk-ZQX7WIYL.js} +359 -93
- package/dist/chunk-ZQX7WIYL.js.map +1 -0
- package/dist/index.cjs +366 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -31
- package/dist/index.d.ts +61 -31
- package/dist/index.js +363 -22
- package/dist/index.js.map +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-CNBilhpz.d.cts → types-CRE9WKd4.d.cts} +59 -6
- package/dist/{types-CNBilhpz.d.ts → types-CRE9WKd4.d.ts} +59 -6
- package/docs/api.md +333 -0
- package/docs/dsl.md +1028 -0
- package/llms-full.txt +2001 -0
- package/llms.txt +30 -0
- package/package.json +5 -3
- package/dist/Composition-BI5HZJFL.cjs +0 -13
- package/dist/Composition-IO7ZN32J.js +0 -4
- package/dist/Movie-CcR6h2jO.d.cts +0 -82
- package/dist/Movie-D-n8glA6.d.ts +0 -82
- package/dist/chunk-64IHCYYN.cjs.map +0 -1
- package/dist/chunk-7OIWYXGV.cjs.map +0 -1
- package/dist/chunk-H55V3U56.js.map +0 -1
- package/dist/chunk-VJCDG6YG.js.map +0 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Application } from 'pixi.js';
|
|
2
|
+
import { gsap } from 'gsap';
|
|
3
|
+
import { A as AssetSpec, g as CompositionSpec } from './types-CRE9WKd4.cjs';
|
|
4
|
+
|
|
5
|
+
interface Rect {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
interface LayerInfo {
|
|
12
|
+
/** Names (or `type#index`) from the root, joined by `/`. */
|
|
13
|
+
path: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
type: string;
|
|
16
|
+
threeD: boolean;
|
|
17
|
+
/** Alive at this frame, not hidden by an ancestor, and alpha > 0. */
|
|
18
|
+
visible: boolean;
|
|
19
|
+
alpha: number;
|
|
20
|
+
/** Its `x` or `y` is animated: text that moves across the canvas on purpose (a ticker) is not reported as cut off. */
|
|
21
|
+
moving: boolean;
|
|
22
|
+
/** Where it is drawn, in canvas pixels. `null` inside a `threeD` layer (it is rendered into that layer's texture). */
|
|
23
|
+
bounds: Rect | null;
|
|
24
|
+
onCanvas: 'full' | 'partial' | 'none' | null;
|
|
25
|
+
}
|
|
26
|
+
interface InspectReport {
|
|
27
|
+
frame: number;
|
|
28
|
+
time: number;
|
|
29
|
+
canvas: {
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
};
|
|
33
|
+
/** Layer counts (of the whole tree) — present even when `layers` is filtered out. */
|
|
34
|
+
summary: {
|
|
35
|
+
layers: number;
|
|
36
|
+
visible: number;
|
|
37
|
+
};
|
|
38
|
+
/** Human-readable problems worth a look: text off-canvas / cut off / empty / overlapping text. Read this first. */
|
|
39
|
+
issues: string[];
|
|
40
|
+
layers: LayerInfo[];
|
|
41
|
+
}
|
|
42
|
+
interface InspectOptions {
|
|
43
|
+
/** Which layers to list: every layer, only those drawn at this frame, or none (just `issues` + `summary`). Default `'all'`. */
|
|
44
|
+
layers?: 'all' | 'visible' | 'none';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface MovieOptions {
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
duration?: number;
|
|
51
|
+
frameRate?: number;
|
|
52
|
+
background?: string;
|
|
53
|
+
canvas?: HTMLCanvasElement;
|
|
54
|
+
assets?: AssetSpec[];
|
|
55
|
+
composition?: CompositionSpec;
|
|
56
|
+
}
|
|
57
|
+
interface RenderOptions {
|
|
58
|
+
format?: 'mp4' | 'mov' | 'webm' | 'mkv';
|
|
59
|
+
video?: {
|
|
60
|
+
codec?: string;
|
|
61
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
62
|
+
};
|
|
63
|
+
audio?: {
|
|
64
|
+
codec?: string;
|
|
65
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
interface SnapshotOptions {
|
|
69
|
+
/** Output size relative to the canvas (default 1). */
|
|
70
|
+
scale?: number;
|
|
71
|
+
/** `'image/png'` (default) or `'image/jpeg'`. */
|
|
72
|
+
type?: 'image/png' | 'image/jpeg';
|
|
73
|
+
/** Return a `data:` URL string instead of a Blob (handy for scripts that can only return text). */
|
|
74
|
+
as?: 'blob' | 'dataURL';
|
|
75
|
+
}
|
|
76
|
+
interface ContactSheetOptions {
|
|
77
|
+
/** Frames to show. Default: `count` frames spread evenly over the movie. */
|
|
78
|
+
frames?: number[];
|
|
79
|
+
/** Times in seconds to show (used when `frames` is not given). */
|
|
80
|
+
times?: number[];
|
|
81
|
+
/** How many frames when neither `frames` nor `times` is given. Default 6. */
|
|
82
|
+
count?: number;
|
|
83
|
+
/** Columns in the grid. Default 3. */
|
|
84
|
+
columns?: number;
|
|
85
|
+
/** Width of each picture in pixels. Default 480. */
|
|
86
|
+
cellWidth?: number;
|
|
87
|
+
as?: 'blob' | 'dataURL';
|
|
88
|
+
}
|
|
89
|
+
interface FrameEvent {
|
|
90
|
+
frame: number;
|
|
91
|
+
totalFrames: number;
|
|
92
|
+
}
|
|
93
|
+
interface ProgressEvent {
|
|
94
|
+
progress: number;
|
|
95
|
+
frame: number;
|
|
96
|
+
totalFrames: number;
|
|
97
|
+
}
|
|
98
|
+
type Listener = (...args: any[]) => void;
|
|
99
|
+
declare class Movie {
|
|
100
|
+
private _events;
|
|
101
|
+
private _initState;
|
|
102
|
+
app: Application | null;
|
|
103
|
+
timeline: ReturnType<typeof gsap.timeline> | null;
|
|
104
|
+
audioBuffer: AudioBuffer | null;
|
|
105
|
+
audioSource: AudioBufferSourceNode | null;
|
|
106
|
+
gainNode: GainNode | null;
|
|
107
|
+
private _volume;
|
|
108
|
+
private _muted;
|
|
109
|
+
isPlaying: boolean;
|
|
110
|
+
currentFrame: number;
|
|
111
|
+
totalFrames: number;
|
|
112
|
+
width: number;
|
|
113
|
+
height: number;
|
|
114
|
+
duration: number;
|
|
115
|
+
frameRate: number;
|
|
116
|
+
background: string;
|
|
117
|
+
private _audioContext;
|
|
118
|
+
private _rootSequence;
|
|
119
|
+
private _rootContainer;
|
|
120
|
+
private _raf;
|
|
121
|
+
on(event: 'ready', fn: () => void): this;
|
|
122
|
+
on(event: 'frame', fn: (e: FrameEvent) => void): this;
|
|
123
|
+
on(event: 'progress', fn: (e: ProgressEvent) => void): this;
|
|
124
|
+
on(event: 'pause', fn: () => void): this;
|
|
125
|
+
off(event: string, fn: Listener): this;
|
|
126
|
+
emit(event: string, ...args: unknown[]): void;
|
|
127
|
+
get isReady(): boolean;
|
|
128
|
+
private _ensureAudioContext;
|
|
129
|
+
init(options?: MovieOptions): Promise<void>;
|
|
130
|
+
gotoFrame(frame: number, force?: boolean): Promise<void>;
|
|
131
|
+
private _awaitVideoFrames;
|
|
132
|
+
/**
|
|
133
|
+
* A picture of one frame (the canvas only: the player bar is not included). Seeks there first and
|
|
134
|
+
* stays there. Use it to LOOK at your composition.
|
|
135
|
+
*/
|
|
136
|
+
snapshot(frame?: number, opts?: SnapshotOptions & {
|
|
137
|
+
as?: 'blob';
|
|
138
|
+
}): Promise<Blob>;
|
|
139
|
+
snapshot(frame: number | undefined, opts: SnapshotOptions & {
|
|
140
|
+
as: 'dataURL';
|
|
141
|
+
}): Promise<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
|
|
144
|
+
* check a whole animation by eye. Restores the current frame afterwards.
|
|
145
|
+
*/
|
|
146
|
+
contactSheet(opts?: ContactSheetOptions & {
|
|
147
|
+
as?: 'blob';
|
|
148
|
+
}): Promise<Blob>;
|
|
149
|
+
contactSheet(opts: ContactSheetOptions & {
|
|
150
|
+
as: 'dataURL';
|
|
151
|
+
}): Promise<string>;
|
|
152
|
+
/**
|
|
153
|
+
* Where every layer is drawn at `frame` (canvas pixels, visibility) plus `issues` — text that is off
|
|
154
|
+
* the canvas, cut by an edge, empty, or overlapping other text. Seeks there and stays there.
|
|
155
|
+
*/
|
|
156
|
+
inspect(frame?: number, opts?: InspectOptions): Promise<InspectReport>;
|
|
157
|
+
/**
|
|
158
|
+
* Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
|
|
159
|
+
* by hand — while seeking and especially during `render()`, which stops the ticker — so without this the
|
|
160
|
+
* `culled` flags are whatever the last tick left: a layer that is now on screen can stay culled and be
|
|
161
|
+
* missing from the frame or from the exported video. Cull again (updating transforms: the timeline just
|
|
162
|
+
* moved things) right before drawing.
|
|
163
|
+
*/
|
|
164
|
+
private _renderNow;
|
|
165
|
+
private _requireReady;
|
|
166
|
+
/** Projects every `threeD` layer for the current frame (see src/space). */
|
|
167
|
+
private _updateSpace;
|
|
168
|
+
play(): void;
|
|
169
|
+
pause(): void;
|
|
170
|
+
set volume(v: number);
|
|
171
|
+
get volume(): number;
|
|
172
|
+
set muted(v: boolean);
|
|
173
|
+
get muted(): boolean;
|
|
174
|
+
toggleMute(): boolean;
|
|
175
|
+
render(options?: RenderOptions): Promise<Blob>;
|
|
176
|
+
destroy(): Promise<void>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type InspectReport as a, type MovieOptions as b };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Application } from 'pixi.js';
|
|
2
|
+
import { gsap } from 'gsap';
|
|
3
|
+
import { A as AssetSpec, g as CompositionSpec } from './types-CRE9WKd4.js';
|
|
4
|
+
|
|
5
|
+
interface Rect {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
interface LayerInfo {
|
|
12
|
+
/** Names (or `type#index`) from the root, joined by `/`. */
|
|
13
|
+
path: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
type: string;
|
|
16
|
+
threeD: boolean;
|
|
17
|
+
/** Alive at this frame, not hidden by an ancestor, and alpha > 0. */
|
|
18
|
+
visible: boolean;
|
|
19
|
+
alpha: number;
|
|
20
|
+
/** Its `x` or `y` is animated: text that moves across the canvas on purpose (a ticker) is not reported as cut off. */
|
|
21
|
+
moving: boolean;
|
|
22
|
+
/** Where it is drawn, in canvas pixels. `null` inside a `threeD` layer (it is rendered into that layer's texture). */
|
|
23
|
+
bounds: Rect | null;
|
|
24
|
+
onCanvas: 'full' | 'partial' | 'none' | null;
|
|
25
|
+
}
|
|
26
|
+
interface InspectReport {
|
|
27
|
+
frame: number;
|
|
28
|
+
time: number;
|
|
29
|
+
canvas: {
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
};
|
|
33
|
+
/** Layer counts (of the whole tree) — present even when `layers` is filtered out. */
|
|
34
|
+
summary: {
|
|
35
|
+
layers: number;
|
|
36
|
+
visible: number;
|
|
37
|
+
};
|
|
38
|
+
/** Human-readable problems worth a look: text off-canvas / cut off / empty / overlapping text. Read this first. */
|
|
39
|
+
issues: string[];
|
|
40
|
+
layers: LayerInfo[];
|
|
41
|
+
}
|
|
42
|
+
interface InspectOptions {
|
|
43
|
+
/** Which layers to list: every layer, only those drawn at this frame, or none (just `issues` + `summary`). Default `'all'`. */
|
|
44
|
+
layers?: 'all' | 'visible' | 'none';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface MovieOptions {
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
duration?: number;
|
|
51
|
+
frameRate?: number;
|
|
52
|
+
background?: string;
|
|
53
|
+
canvas?: HTMLCanvasElement;
|
|
54
|
+
assets?: AssetSpec[];
|
|
55
|
+
composition?: CompositionSpec;
|
|
56
|
+
}
|
|
57
|
+
interface RenderOptions {
|
|
58
|
+
format?: 'mp4' | 'mov' | 'webm' | 'mkv';
|
|
59
|
+
video?: {
|
|
60
|
+
codec?: string;
|
|
61
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
62
|
+
};
|
|
63
|
+
audio?: {
|
|
64
|
+
codec?: string;
|
|
65
|
+
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
interface SnapshotOptions {
|
|
69
|
+
/** Output size relative to the canvas (default 1). */
|
|
70
|
+
scale?: number;
|
|
71
|
+
/** `'image/png'` (default) or `'image/jpeg'`. */
|
|
72
|
+
type?: 'image/png' | 'image/jpeg';
|
|
73
|
+
/** Return a `data:` URL string instead of a Blob (handy for scripts that can only return text). */
|
|
74
|
+
as?: 'blob' | 'dataURL';
|
|
75
|
+
}
|
|
76
|
+
interface ContactSheetOptions {
|
|
77
|
+
/** Frames to show. Default: `count` frames spread evenly over the movie. */
|
|
78
|
+
frames?: number[];
|
|
79
|
+
/** Times in seconds to show (used when `frames` is not given). */
|
|
80
|
+
times?: number[];
|
|
81
|
+
/** How many frames when neither `frames` nor `times` is given. Default 6. */
|
|
82
|
+
count?: number;
|
|
83
|
+
/** Columns in the grid. Default 3. */
|
|
84
|
+
columns?: number;
|
|
85
|
+
/** Width of each picture in pixels. Default 480. */
|
|
86
|
+
cellWidth?: number;
|
|
87
|
+
as?: 'blob' | 'dataURL';
|
|
88
|
+
}
|
|
89
|
+
interface FrameEvent {
|
|
90
|
+
frame: number;
|
|
91
|
+
totalFrames: number;
|
|
92
|
+
}
|
|
93
|
+
interface ProgressEvent {
|
|
94
|
+
progress: number;
|
|
95
|
+
frame: number;
|
|
96
|
+
totalFrames: number;
|
|
97
|
+
}
|
|
98
|
+
type Listener = (...args: any[]) => void;
|
|
99
|
+
declare class Movie {
|
|
100
|
+
private _events;
|
|
101
|
+
private _initState;
|
|
102
|
+
app: Application | null;
|
|
103
|
+
timeline: ReturnType<typeof gsap.timeline> | null;
|
|
104
|
+
audioBuffer: AudioBuffer | null;
|
|
105
|
+
audioSource: AudioBufferSourceNode | null;
|
|
106
|
+
gainNode: GainNode | null;
|
|
107
|
+
private _volume;
|
|
108
|
+
private _muted;
|
|
109
|
+
isPlaying: boolean;
|
|
110
|
+
currentFrame: number;
|
|
111
|
+
totalFrames: number;
|
|
112
|
+
width: number;
|
|
113
|
+
height: number;
|
|
114
|
+
duration: number;
|
|
115
|
+
frameRate: number;
|
|
116
|
+
background: string;
|
|
117
|
+
private _audioContext;
|
|
118
|
+
private _rootSequence;
|
|
119
|
+
private _rootContainer;
|
|
120
|
+
private _raf;
|
|
121
|
+
on(event: 'ready', fn: () => void): this;
|
|
122
|
+
on(event: 'frame', fn: (e: FrameEvent) => void): this;
|
|
123
|
+
on(event: 'progress', fn: (e: ProgressEvent) => void): this;
|
|
124
|
+
on(event: 'pause', fn: () => void): this;
|
|
125
|
+
off(event: string, fn: Listener): this;
|
|
126
|
+
emit(event: string, ...args: unknown[]): void;
|
|
127
|
+
get isReady(): boolean;
|
|
128
|
+
private _ensureAudioContext;
|
|
129
|
+
init(options?: MovieOptions): Promise<void>;
|
|
130
|
+
gotoFrame(frame: number, force?: boolean): Promise<void>;
|
|
131
|
+
private _awaitVideoFrames;
|
|
132
|
+
/**
|
|
133
|
+
* A picture of one frame (the canvas only: the player bar is not included). Seeks there first and
|
|
134
|
+
* stays there. Use it to LOOK at your composition.
|
|
135
|
+
*/
|
|
136
|
+
snapshot(frame?: number, opts?: SnapshotOptions & {
|
|
137
|
+
as?: 'blob';
|
|
138
|
+
}): Promise<Blob>;
|
|
139
|
+
snapshot(frame: number | undefined, opts: SnapshotOptions & {
|
|
140
|
+
as: 'dataURL';
|
|
141
|
+
}): Promise<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
|
|
144
|
+
* check a whole animation by eye. Restores the current frame afterwards.
|
|
145
|
+
*/
|
|
146
|
+
contactSheet(opts?: ContactSheetOptions & {
|
|
147
|
+
as?: 'blob';
|
|
148
|
+
}): Promise<Blob>;
|
|
149
|
+
contactSheet(opts: ContactSheetOptions & {
|
|
150
|
+
as: 'dataURL';
|
|
151
|
+
}): Promise<string>;
|
|
152
|
+
/**
|
|
153
|
+
* Where every layer is drawn at `frame` (canvas pixels, visibility) plus `issues` — text that is off
|
|
154
|
+
* the canvas, cut by an edge, empty, or overlapping other text. Seeks there and stays there.
|
|
155
|
+
*/
|
|
156
|
+
inspect(frame?: number, opts?: InspectOptions): Promise<InspectReport>;
|
|
157
|
+
/**
|
|
158
|
+
* Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
|
|
159
|
+
* by hand — while seeking and especially during `render()`, which stops the ticker — so without this the
|
|
160
|
+
* `culled` flags are whatever the last tick left: a layer that is now on screen can stay culled and be
|
|
161
|
+
* missing from the frame or from the exported video. Cull again (updating transforms: the timeline just
|
|
162
|
+
* moved things) right before drawing.
|
|
163
|
+
*/
|
|
164
|
+
private _renderNow;
|
|
165
|
+
private _requireReady;
|
|
166
|
+
/** Projects every `threeD` layer for the current frame (see src/space). */
|
|
167
|
+
private _updateSpace;
|
|
168
|
+
play(): void;
|
|
169
|
+
pause(): void;
|
|
170
|
+
set volume(v: number);
|
|
171
|
+
get volume(): number;
|
|
172
|
+
set muted(v: boolean);
|
|
173
|
+
get muted(): boolean;
|
|
174
|
+
toggleMute(): boolean;
|
|
175
|
+
render(options?: RenderOptions): Promise<Blob>;
|
|
176
|
+
destroy(): Promise<void>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type InspectReport as a, type MovieOptions as b };
|