@agrhub/engine-pixi 0.0.0-stage → 1.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/LICENSE +47 -0
- package/NOTICE.md +20 -0
- package/README.md +6 -2
- package/dist/animation/block-reveal-animation.d.ts +33 -0
- package/dist/animation/easings.d.ts +4 -0
- package/dist/animation/gsap-animation.d.ts +32 -0
- package/dist/animation/index.d.ts +9 -0
- package/dist/animation/keyframe-animation.d.ts +11 -0
- package/dist/animation/mask-animation.d.ts +170 -0
- package/dist/animation/pixi-animation-utils.d.ts +10 -0
- package/dist/animation/registry.d.ts +11 -0
- package/dist/animation/types.d.ts +211 -0
- package/dist/animation/wipe-animation.d.ts +53 -0
- package/dist/clips/audio-clip.d.ts +122 -0
- package/dist/clips/backdrop-clip.d.ts +56 -0
- package/dist/clips/base-clip.d.ts +150 -0
- package/dist/clips/base-text-clip.d.ts +228 -0
- package/dist/clips/caption-clip.d.ts +129 -0
- package/dist/clips/clip-registry.d.ts +56 -0
- package/dist/clips/effect-clip.d.ts +37 -0
- package/dist/clips/iclip.d.ts +235 -0
- package/dist/clips/image-clip.d.ts +116 -0
- package/dist/clips/index.d.ts +20 -0
- package/dist/clips/placeholder-clip.d.ts +22 -0
- package/dist/clips/shape-clip.d.ts +59 -0
- package/dist/clips/text-clip.d.ts +148 -0
- package/dist/clips/transition-clip.d.ts +45 -0
- package/dist/clips/video-clip.d.ts +216 -0
- package/dist/compositor/audio-mixer.d.ts +8 -0
- package/dist/compositor/av-encoder.d.ts +17 -0
- package/dist/compositor/clip-style-renderer.d.ts +23 -0
- package/dist/compositor/compositor-renderer.d.ts +29 -0
- package/dist/compositor/effect-manager.d.ts +30 -0
- package/dist/compositor/scheduler.d.ts +8 -0
- package/dist/compositor/transition-manager.d.ts +45 -0
- package/dist/compositor.d.ts +157 -0
- package/dist/effect/constant/index.d.ts +566 -0
- package/dist/effect/effect.d.ts +9 -0
- package/dist/effect/glsl/custom-glsl.d.ts +1043 -0
- package/dist/effect/glsl/gl-effect.d.ts +38 -0
- package/dist/effect/interface/index.d.ts +25 -0
- package/dist/effect/types.d.ts +26 -0
- package/dist/effect/vertex.d.ts +1 -0
- package/dist/event-emitter.d.ts +55 -0
- package/dist/filters/outline-filter.d.ts +28 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.es.js +16144 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.cjs +3335 -0
- package/dist/index.umd.cjs.map +1 -0
- package/dist/json-serialization.d.ts +312 -0
- package/dist/mp4-utils/index.d.ts +31 -0
- package/dist/mp4-utils/mp4box-utils.d.ts +44 -0
- package/dist/mp4-utils/sample-transform.d.ts +26 -0
- package/dist/sprite/base-sprite.d.ts +273 -0
- package/dist/sprite/pixi-sprite-renderer.d.ts +69 -0
- package/dist/standalone/index.es.js +94191 -0
- package/dist/standalone/index.es.js.map +1 -0
- package/dist/studio/history-manager.d.ts +46 -0
- package/dist/studio/resource-manager.d.ts +53 -0
- package/dist/studio/selection-manager.d.ts +66 -0
- package/dist/studio/timeline-model.d.ts +117 -0
- package/dist/studio/transport.d.ts +44 -0
- package/dist/studio-bridge.d.ts +50 -0
- package/dist/studio.d.ts +529 -0
- package/dist/transformer/handle.d.ts +17 -0
- package/dist/transformer/snapping.d.ts +45 -0
- package/dist/transformer/transformer.d.ts +38 -0
- package/dist/transformer/wireframe.d.ts +5 -0
- package/dist/transition/fragment.d.ts +1 -0
- package/dist/transition/glsl/custom-glsl.d.ts +231 -0
- package/dist/transition/glsl/gl-transition.d.ts +42 -0
- package/dist/transition/transition.d.ts +6 -0
- package/dist/transition/types.d.ts +31 -0
- package/dist/transition/uniforms.d.ts +35 -0
- package/dist/transition/vertex.d.ts +1 -0
- package/dist/utils/asset-manager.d.ts +15 -0
- package/dist/utils/audio-codec-detector.d.ts +39 -0
- package/dist/utils/audio.d.ts +81 -0
- package/dist/utils/chromakey.d.ts +24 -0
- package/dist/utils/color-adjustment.d.ts +53 -0
- package/dist/utils/color.d.ts +17 -0
- package/dist/utils/common.d.ts +7 -0
- package/dist/utils/dom.d.ts +48 -0
- package/dist/utils/effect.d.ts +1 -0
- package/dist/utils/fonts.d.ts +21 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/log.d.ts +27 -0
- package/dist/utils/media-cache.d.ts +45 -0
- package/dist/utils/stream-utils.d.ts +4 -0
- package/dist/utils/video.d.ts +16 -0
- package/dist/utils/worker-timer.d.ts +1 -0
- package/package.json +63 -3
package/dist/studio.d.ts
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
import { Application, Sprite, Texture, Container, Graphics, RenderTexture } from 'pixi.js';
|
|
2
|
+
import { IClip } from './clips/iclip';
|
|
3
|
+
import { PixiSpriteRenderer } from './sprite/pixi-sprite-renderer';
|
|
4
|
+
import { ProjectJSON } from './json-serialization';
|
|
5
|
+
import { Transformer } from './transformer/transformer';
|
|
6
|
+
import { EffectKey } from './effect/glsl/gl-effect';
|
|
7
|
+
import { default as EventEmitter } from './event-emitter';
|
|
8
|
+
import { Core } from '@agrhub/core';
|
|
9
|
+
import { SelectionManager } from './studio/selection-manager';
|
|
10
|
+
import { Transport } from './studio/transport';
|
|
11
|
+
import { TimelineModel } from './studio/timeline-model';
|
|
12
|
+
import { HistoryManager } from './studio/history-manager';
|
|
13
|
+
import { ResourceManager } from './studio/resource-manager';
|
|
14
|
+
export interface IStudioOpts {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
fps?: number;
|
|
18
|
+
backgroundColor?: string;
|
|
19
|
+
artboardColor?: string;
|
|
20
|
+
canvas?: HTMLCanvasElement;
|
|
21
|
+
interactivity?: boolean;
|
|
22
|
+
spacing?: number;
|
|
23
|
+
core?: Core;
|
|
24
|
+
allowZoom?: boolean;
|
|
25
|
+
allowPan?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Internal rendering resolution multiplier for preview (0-1).
|
|
28
|
+
* e.g., 0.5 renders at half-resolution, improving playback performance.
|
|
29
|
+
* Default is 1.
|
|
30
|
+
*/
|
|
31
|
+
previewScale?: number;
|
|
32
|
+
}
|
|
33
|
+
interface ActiveGlobalEffect {
|
|
34
|
+
id: string;
|
|
35
|
+
key: EffectKey;
|
|
36
|
+
startTime: number;
|
|
37
|
+
duration: number;
|
|
38
|
+
trackIndex?: number;
|
|
39
|
+
values?: Record<string, any>;
|
|
40
|
+
}
|
|
41
|
+
interface GlobalEffectInfo {
|
|
42
|
+
id: string;
|
|
43
|
+
key: EffectKey;
|
|
44
|
+
startTime: number;
|
|
45
|
+
duration: number;
|
|
46
|
+
}
|
|
47
|
+
export interface StudioEvents {
|
|
48
|
+
"selection:created": {
|
|
49
|
+
selected: IClip[];
|
|
50
|
+
};
|
|
51
|
+
"selection:updated": {
|
|
52
|
+
selected: IClip[];
|
|
53
|
+
};
|
|
54
|
+
"selection:cleared": {
|
|
55
|
+
deselected: IClip[];
|
|
56
|
+
};
|
|
57
|
+
"track:added": {
|
|
58
|
+
track: StudioTrack;
|
|
59
|
+
index?: number;
|
|
60
|
+
};
|
|
61
|
+
"track:order-changed": {
|
|
62
|
+
tracks: StudioTrack[];
|
|
63
|
+
};
|
|
64
|
+
"track:removed": {
|
|
65
|
+
trackId: string;
|
|
66
|
+
};
|
|
67
|
+
"clip:added": {
|
|
68
|
+
clip: IClip;
|
|
69
|
+
trackId: string;
|
|
70
|
+
};
|
|
71
|
+
"clips:added": {
|
|
72
|
+
clips: IClip[];
|
|
73
|
+
trackId?: string;
|
|
74
|
+
};
|
|
75
|
+
"clip:removed": {
|
|
76
|
+
clipId: string;
|
|
77
|
+
};
|
|
78
|
+
"clip:updated": {
|
|
79
|
+
clip: IClip;
|
|
80
|
+
};
|
|
81
|
+
"clip:lock-changed": {
|
|
82
|
+
clip: IClip;
|
|
83
|
+
locked: boolean;
|
|
84
|
+
};
|
|
85
|
+
"clip:replaced": {
|
|
86
|
+
oldClip: IClip;
|
|
87
|
+
newClip: IClip;
|
|
88
|
+
trackId: string;
|
|
89
|
+
};
|
|
90
|
+
"studio:restored": {
|
|
91
|
+
clips: IClip[];
|
|
92
|
+
tracks: StudioTrack[];
|
|
93
|
+
settings: IStudioOpts;
|
|
94
|
+
};
|
|
95
|
+
currentTime: {
|
|
96
|
+
currentTime: number;
|
|
97
|
+
};
|
|
98
|
+
play: {
|
|
99
|
+
isPlaying: boolean;
|
|
100
|
+
};
|
|
101
|
+
pause: {
|
|
102
|
+
isPlaying: boolean;
|
|
103
|
+
};
|
|
104
|
+
"history:changed": {
|
|
105
|
+
canUndo: boolean;
|
|
106
|
+
canRedo: boolean;
|
|
107
|
+
};
|
|
108
|
+
"transform:start": {
|
|
109
|
+
transformer: Transformer;
|
|
110
|
+
};
|
|
111
|
+
"transform:end": {
|
|
112
|
+
transformer: Transformer;
|
|
113
|
+
};
|
|
114
|
+
"clip:dblclick": {
|
|
115
|
+
clip: IClip;
|
|
116
|
+
};
|
|
117
|
+
"viewport:changed": {
|
|
118
|
+
zoomLevel: number;
|
|
119
|
+
panOffset: {
|
|
120
|
+
x: number;
|
|
121
|
+
y: number;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
[key: string]: any;
|
|
125
|
+
[key: symbol]: any;
|
|
126
|
+
}
|
|
127
|
+
export interface StudioTrack {
|
|
128
|
+
id: string;
|
|
129
|
+
name: string;
|
|
130
|
+
type: string;
|
|
131
|
+
clipIds: string[];
|
|
132
|
+
/** Silences every clip on the track without changing their own volume/muted */
|
|
133
|
+
muted?: boolean;
|
|
134
|
+
}
|
|
135
|
+
export declare class Studio extends EventEmitter<StudioEvents> {
|
|
136
|
+
selection: SelectionManager;
|
|
137
|
+
transport: Transport;
|
|
138
|
+
timeline: TimelineModel;
|
|
139
|
+
history: HistoryManager;
|
|
140
|
+
resourceManager: ResourceManager;
|
|
141
|
+
pixiApp: Application | null;
|
|
142
|
+
get tracks(): StudioTrack[];
|
|
143
|
+
get clips(): IClip<import('./sprite/base-sprite').BaseSpriteEvents>[];
|
|
144
|
+
spriteRenderers: Map<IClip<import('./sprite/base-sprite').BaseSpriteEvents>, PixiSpriteRenderer>;
|
|
145
|
+
artboard: Container | null;
|
|
146
|
+
clipContainer: Container | null;
|
|
147
|
+
artboardMask: Graphics | null;
|
|
148
|
+
artboardBg: Graphics | null;
|
|
149
|
+
get activeTransformer(): Transformer | null;
|
|
150
|
+
set activeTransformer(val: Transformer | null);
|
|
151
|
+
get selectedClips(): Set<IClip>;
|
|
152
|
+
set selectedClips(val: Set<IClip>);
|
|
153
|
+
get interactiveClips(): Set<IClip>;
|
|
154
|
+
set interactiveClips(val: Set<IClip>);
|
|
155
|
+
get playbackElements(): Map<IClip<import('./sprite/base-sprite').BaseSpriteEvents>, import('./studio/transport').PlaybackElementInfo>;
|
|
156
|
+
videoSprites: Map<IClip<import('./sprite/base-sprite').BaseSpriteEvents>, Sprite>;
|
|
157
|
+
clipListeners: Map<IClip<import('./sprite/base-sprite').BaseSpriteEvents>, () => void>;
|
|
158
|
+
get isPlaying(): boolean;
|
|
159
|
+
set isPlaying(val: boolean);
|
|
160
|
+
get currentTime(): number;
|
|
161
|
+
set currentTime(val: number);
|
|
162
|
+
get maxDuration(): number;
|
|
163
|
+
set maxDuration(val: number);
|
|
164
|
+
opts: Required<Omit<IStudioOpts, "canvas" | "core">> & {
|
|
165
|
+
canvas?: HTMLCanvasElement;
|
|
166
|
+
core?: Core;
|
|
167
|
+
};
|
|
168
|
+
destroyed: boolean;
|
|
169
|
+
private renderingSuspended;
|
|
170
|
+
/** Incremented per updateFrame call; only the latest call may apply decoded video frames */
|
|
171
|
+
private frameToken;
|
|
172
|
+
private historyPaused;
|
|
173
|
+
private processingHistory;
|
|
174
|
+
/**
|
|
175
|
+
* Indicates if the studio is currently restoring state from history (undo/redo)
|
|
176
|
+
*/
|
|
177
|
+
isRestoring: boolean;
|
|
178
|
+
private historyGroupDepth;
|
|
179
|
+
private clipCache;
|
|
180
|
+
private _isUpdatingLayout;
|
|
181
|
+
private bridge;
|
|
182
|
+
/** User-controlled zoom multiplier on top of the fit-to-screen base scale.
|
|
183
|
+
* 1.0 = 100 % (no extra zoom beyond fit). */
|
|
184
|
+
private _zoomLevel;
|
|
185
|
+
/** Pan offset in canvas/screen pixels, applied after base centering. */
|
|
186
|
+
private _panOffset;
|
|
187
|
+
/** The base fit-to-screen scale last computed by updateArtboardLayout. */
|
|
188
|
+
private _baseScale;
|
|
189
|
+
private _allowZoom;
|
|
190
|
+
private _allowPan;
|
|
191
|
+
private _isPanning;
|
|
192
|
+
private _isSpaceDown;
|
|
193
|
+
private _lastPointerPos;
|
|
194
|
+
private _boundOnWheel;
|
|
195
|
+
private _boundOnPointerDown;
|
|
196
|
+
private _boundOnPointerMove;
|
|
197
|
+
private _boundOnPointerUp;
|
|
198
|
+
private _boundOnKeyDown;
|
|
199
|
+
private _boundOnKeyUp;
|
|
200
|
+
globalEffects: Map<string, GlobalEffectInfo>;
|
|
201
|
+
activeGlobalEffects: ActiveGlobalEffect[];
|
|
202
|
+
currentGlobalEffectSprite: Sprite | null;
|
|
203
|
+
effectFilters: Map<string, {
|
|
204
|
+
filter: null;
|
|
205
|
+
render(_opts: import('./effect/types').EffectRendererOptions): RenderTexture | null;
|
|
206
|
+
} | {
|
|
207
|
+
filter: any;
|
|
208
|
+
render({ width, height, canvasTexture, progress, values: runtimeValues, }: import('./effect/types').EffectRendererOptions): RenderTexture;
|
|
209
|
+
}>;
|
|
210
|
+
transitionRenderers: Map<string, {
|
|
211
|
+
render({ width, height, from, to, progress, values }: import('./transition/types').TransitionRendererOptions): RenderTexture;
|
|
212
|
+
destroy(): void;
|
|
213
|
+
}>;
|
|
214
|
+
transitionSprites: Map<string, Sprite>;
|
|
215
|
+
transFromTexture: RenderTexture | null;
|
|
216
|
+
transToTexture: RenderTexture | null;
|
|
217
|
+
transBgGraphics: Graphics | null;
|
|
218
|
+
clipsNormalContainer: Container | null;
|
|
219
|
+
clipsEffectContainer: Container | null;
|
|
220
|
+
videoTextureCache: WeakMap<HTMLVideoElement, Texture<import('pixi.js').TextureSource<any>>>;
|
|
221
|
+
lastFromFrame: Texture | ImageBitmap | VideoFrame | null;
|
|
222
|
+
lastToFrame: Texture | ImageBitmap | VideoFrame | null;
|
|
223
|
+
/**
|
|
224
|
+
* Convert hex color string to number
|
|
225
|
+
*/
|
|
226
|
+
private hexToNumber;
|
|
227
|
+
ready: Promise<void>;
|
|
228
|
+
/**
|
|
229
|
+
* Create a new Studio instance
|
|
230
|
+
*/
|
|
231
|
+
constructor(opts: IStudioOpts);
|
|
232
|
+
private attachClipEvents;
|
|
233
|
+
private handleTimelineChange;
|
|
234
|
+
private saveHistory;
|
|
235
|
+
beginHistoryGroup(): void;
|
|
236
|
+
endHistoryGroup(): void;
|
|
237
|
+
private setPath;
|
|
238
|
+
private applyHistoryPatches;
|
|
239
|
+
undo(): Promise<void>;
|
|
240
|
+
redo(): Promise<void>;
|
|
241
|
+
private cleanupClipVisuals;
|
|
242
|
+
private handleClipRemoved;
|
|
243
|
+
private handleClipsRemoved;
|
|
244
|
+
private initPixiApp;
|
|
245
|
+
/**
|
|
246
|
+
* Get studio options
|
|
247
|
+
*/
|
|
248
|
+
getOptions(): IStudioOpts;
|
|
249
|
+
/**
|
|
250
|
+
* Update studio dimensions
|
|
251
|
+
*/
|
|
252
|
+
setSize(width: number, height: number): void;
|
|
253
|
+
/**
|
|
254
|
+
* Set the preview resolution scale dynamically
|
|
255
|
+
* @param scale A multiplier between 0.1 and 1
|
|
256
|
+
*/
|
|
257
|
+
setPreviewScale(scale: number): void;
|
|
258
|
+
private recreateTransitionTextures;
|
|
259
|
+
/**
|
|
260
|
+
* Update the background color of the studio (applies to the outside area)
|
|
261
|
+
*/
|
|
262
|
+
setBackgroundColor(color: string): void;
|
|
263
|
+
/**
|
|
264
|
+
* Update the artboard background color of the studio (applies to the video frame itself)
|
|
265
|
+
*/
|
|
266
|
+
setArtboardColor(color: string): void;
|
|
267
|
+
updateDimensions(width: number, height: number): void;
|
|
268
|
+
private handleResize;
|
|
269
|
+
updateArtboardLayout(options?: {
|
|
270
|
+
skipResize?: boolean;
|
|
271
|
+
}): void;
|
|
272
|
+
/** Current user zoom level (1 = fit-to-screen, 2 = 200 %, etc.). */
|
|
273
|
+
get zoomLevel(): number;
|
|
274
|
+
/** Base fit-to-screen scale (read-only, recomputed on every layout update). */
|
|
275
|
+
get baseScale(): number;
|
|
276
|
+
/**
|
|
277
|
+
* Set the user zoom level.
|
|
278
|
+
* @param level Desired zoom (1 = fit-to-screen). Clamped to [0.1, 10].
|
|
279
|
+
* @param originX Optional canvas-space X to zoom toward (defaults to center).
|
|
280
|
+
* @param originY Optional canvas-space Y to zoom toward (defaults to center).
|
|
281
|
+
*/
|
|
282
|
+
setZoom(level: number, originX?: number, originY?: number): void;
|
|
283
|
+
/**
|
|
284
|
+
* Apply a relative pan (delta in screen pixels).
|
|
285
|
+
*/
|
|
286
|
+
pan(dx: number, dy: number): void;
|
|
287
|
+
/**
|
|
288
|
+
* Reset zoom to 1× (fit-to-screen) and clear pan offset.
|
|
289
|
+
*/
|
|
290
|
+
resetView(): void;
|
|
291
|
+
setAllowZoom(enabled: boolean): void;
|
|
292
|
+
setAllowPan(enabled: boolean): void;
|
|
293
|
+
private _initViewportEvents;
|
|
294
|
+
private _destroyViewportEvents;
|
|
295
|
+
/**
|
|
296
|
+
* Get the canvas element (creates one if not provided)
|
|
297
|
+
*/
|
|
298
|
+
getCanvas(): HTMLCanvasElement;
|
|
299
|
+
addTransition(transitionKey: string, duration?: number, fromClipId?: string | null, toClipId?: string | null, id?: string): Promise<void>;
|
|
300
|
+
findTrackIdByClipId(clipId: string): string | undefined;
|
|
301
|
+
/**
|
|
302
|
+
* Add a clip (or clips) to the studio
|
|
303
|
+
* @param clipOrClips The clip or array of clips to add
|
|
304
|
+
* @param options Options for addition (trackId, etc.)
|
|
305
|
+
*/
|
|
306
|
+
addClip(clipOrClips: IClip | IClip[], options?: {
|
|
307
|
+
trackId?: string;
|
|
308
|
+
audioSource?: string | File | Blob;
|
|
309
|
+
} | string | File | Blob): Promise<void>;
|
|
310
|
+
/**
|
|
311
|
+
* Add a new track to the studio
|
|
312
|
+
*/
|
|
313
|
+
addTrack(track: {
|
|
314
|
+
name: string;
|
|
315
|
+
type: string;
|
|
316
|
+
id?: string;
|
|
317
|
+
}, index?: number): StudioTrack;
|
|
318
|
+
setTracks(tracks: StudioTrack[]): Promise<void>;
|
|
319
|
+
/**
|
|
320
|
+
* Move a track to a new index
|
|
321
|
+
*/
|
|
322
|
+
moveTrack(trackId: string, newIndex: number): Promise<void>;
|
|
323
|
+
/**
|
|
324
|
+
* Set the order of tracks by ID
|
|
325
|
+
*/
|
|
326
|
+
setTrackOrder(trackIds: string[]): Promise<void>;
|
|
327
|
+
removeTrack(trackId: string): Promise<void>;
|
|
328
|
+
/**
|
|
329
|
+
* Get a clip by its ID
|
|
330
|
+
*/
|
|
331
|
+
getClipById(id: string): IClip | undefined;
|
|
332
|
+
updateClip(id: string, updates: Partial<IClip>): Promise<void>;
|
|
333
|
+
/**
|
|
334
|
+
* Centers object vertically and horizontally in the studio
|
|
335
|
+
*/
|
|
336
|
+
centerClip(clipOrId: IClip | string): Promise<void>;
|
|
337
|
+
/**
|
|
338
|
+
* Centers object horizontally in the studio
|
|
339
|
+
*/
|
|
340
|
+
centerClipH(clipOrId: IClip | string): Promise<void>;
|
|
341
|
+
/**
|
|
342
|
+
* Centers object vertically in the studio
|
|
343
|
+
*/
|
|
344
|
+
centerClipV(clipOrId: IClip | string): Promise<void>;
|
|
345
|
+
/**
|
|
346
|
+
* Scale clip to fit within the studio dimensions while maintaining aspect ratio
|
|
347
|
+
*/
|
|
348
|
+
scaleToFit(clipOrId: IClip | string): Promise<void>;
|
|
349
|
+
/**
|
|
350
|
+
* Scale clip to fill the studio dimensions while maintaining aspect ratio
|
|
351
|
+
*/
|
|
352
|
+
scaleToCover(clipOrId: IClip | string): Promise<void>;
|
|
353
|
+
updateClips(updates: {
|
|
354
|
+
id: string;
|
|
355
|
+
updates: Partial<IClip>;
|
|
356
|
+
}[]): Promise<void>;
|
|
357
|
+
suspendRendering(): void;
|
|
358
|
+
resumeRendering(): void;
|
|
359
|
+
getTracks(): StudioTrack[];
|
|
360
|
+
getClip(id: string): IClip | undefined;
|
|
361
|
+
findClip(id: string): IClip | undefined;
|
|
362
|
+
/**
|
|
363
|
+
* Setup sprite interactivity for click selection
|
|
364
|
+
* Delegated to SelectionManager
|
|
365
|
+
*/
|
|
366
|
+
setupSpriteInteractivity(clip: IClip): void;
|
|
367
|
+
/**
|
|
368
|
+
* Setup playback element for a clip (if it supports playback)
|
|
369
|
+
*/
|
|
370
|
+
/**
|
|
371
|
+
* Remove a clip from the studio
|
|
372
|
+
*/
|
|
373
|
+
removeClip(clipOrId: IClip | string): Promise<void>;
|
|
374
|
+
removeClips(clips: IClip[]): Promise<void>;
|
|
375
|
+
removeClipById(clipId: string): Promise<void>;
|
|
376
|
+
removeClipsById(clipIds: string[]): Promise<void>;
|
|
377
|
+
/**
|
|
378
|
+
* Delete all currently selected clips
|
|
379
|
+
*/
|
|
380
|
+
deleteSelected(): Promise<void>;
|
|
381
|
+
duplicateSelected(): Promise<void>;
|
|
382
|
+
splitSelected(splitTime?: number): Promise<void>;
|
|
383
|
+
trimSelected(trimFromSeconds: number): Promise<void>;
|
|
384
|
+
updateSelected(updates: Partial<IClip>): Promise<void>;
|
|
385
|
+
/**
|
|
386
|
+
* Clear all clips from the studio
|
|
387
|
+
*/
|
|
388
|
+
clear(): Promise<void>;
|
|
389
|
+
/**
|
|
390
|
+
* Start playback
|
|
391
|
+
*/
|
|
392
|
+
play(): Promise<void>;
|
|
393
|
+
/**
|
|
394
|
+
* Pause playback
|
|
395
|
+
*/
|
|
396
|
+
pause(): void;
|
|
397
|
+
/**
|
|
398
|
+
* Stop playback and reset to start
|
|
399
|
+
*/
|
|
400
|
+
stop(): Promise<void>;
|
|
401
|
+
/**
|
|
402
|
+
* Seek to a specific time (in microseconds)
|
|
403
|
+
*/
|
|
404
|
+
seek(time: number): Promise<void>;
|
|
405
|
+
/**
|
|
406
|
+
* Move to the next frame
|
|
407
|
+
*/
|
|
408
|
+
frameNext(): Promise<void>;
|
|
409
|
+
/**
|
|
410
|
+
* Move to the previous frame
|
|
411
|
+
*/
|
|
412
|
+
framePrev(): Promise<void>;
|
|
413
|
+
/**
|
|
414
|
+
* Renders the frame at the given time and returns it as a base64-encoded PNG.
|
|
415
|
+
*
|
|
416
|
+
* The artboard is temporarily reset to 1:1 scale during extraction so the
|
|
417
|
+
* output image always matches the project's configured width × height,
|
|
418
|
+
* regardless of the current viewport zoom.
|
|
419
|
+
*
|
|
420
|
+
* @param timeMs Time in milliseconds
|
|
421
|
+
* @param options.transparent If true, the artboard background fill is
|
|
422
|
+
* hidden so the resulting PNG has a transparent background.
|
|
423
|
+
* @returns Base64 data-URL string (e.g. "data:image/png;base64,...")
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* await studio.ready;
|
|
427
|
+
* const frame = await studio.renderFrame(1500); // frame at 1.5 s
|
|
428
|
+
* const transparent = await studio.renderFrame(1500, { transparent: true });
|
|
429
|
+
* const img = document.createElement('img');
|
|
430
|
+
* img.src = frame;
|
|
431
|
+
*/
|
|
432
|
+
renderFrame(timeMs: number, options?: {
|
|
433
|
+
transparent?: boolean;
|
|
434
|
+
}): Promise<string>;
|
|
435
|
+
/**
|
|
436
|
+
* Alias for {@link renderFrame} with support for the current playhead.
|
|
437
|
+
* Captures a single frame as a base64-encoded PNG.
|
|
438
|
+
*
|
|
439
|
+
* @param timeMs Optional time in milliseconds, or an options object. If
|
|
440
|
+
* omitted, the current playhead position is used.
|
|
441
|
+
* @param options.transparent If true, the artboard background fill is
|
|
442
|
+
* hidden so the resulting PNG has a transparent background.
|
|
443
|
+
* @returns Base64 data-URL string (e.g. "data:image/png;base64,...")
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* await studio.ready;
|
|
447
|
+
* const currentFrame = await studio.snapshot(); // current playhead
|
|
448
|
+
* const frameAt2s = await studio.snapshot(2000); // explicit timestamp
|
|
449
|
+
* const transparent = await studio.snapshot({ transparent: true }); // current frame, transparent
|
|
450
|
+
* const transparent2s = await studio.snapshot(2000, { transparent: true });
|
|
451
|
+
*/
|
|
452
|
+
snapshot(timeMs?: number | {
|
|
453
|
+
transparent?: boolean;
|
|
454
|
+
}): Promise<string>;
|
|
455
|
+
/**
|
|
456
|
+
* Get current playback time (in microseconds)
|
|
457
|
+
*/
|
|
458
|
+
getCurrentTime(): number;
|
|
459
|
+
/**
|
|
460
|
+
* Get maximum duration (in microseconds)
|
|
461
|
+
*/
|
|
462
|
+
getMaxDuration(): number;
|
|
463
|
+
/**
|
|
464
|
+
* Check if currently playing
|
|
465
|
+
*/
|
|
466
|
+
getIsPlaying(): boolean;
|
|
467
|
+
/**
|
|
468
|
+
* Get currently selected clips
|
|
469
|
+
*/
|
|
470
|
+
getSelectedClips(): IClip[];
|
|
471
|
+
private getVideoTexture;
|
|
472
|
+
private isPlaybackCapable;
|
|
473
|
+
updateFrame(timestamp: number): Promise<void>;
|
|
474
|
+
/**
|
|
475
|
+
* Apply global effect to the current scene
|
|
476
|
+
*/
|
|
477
|
+
moveClipToEffectContainer(clip: IClip, toEffect?: boolean): void;
|
|
478
|
+
applyGlobalEffect(key: EffectKey, options: {
|
|
479
|
+
startTime: number;
|
|
480
|
+
duration?: number;
|
|
481
|
+
id?: string;
|
|
482
|
+
}, clips: IClip[]): string;
|
|
483
|
+
getTrackIndex(clipId: string): number;
|
|
484
|
+
/**
|
|
485
|
+
* Get the frame from the previous clip on the same track for transition
|
|
486
|
+
*/
|
|
487
|
+
getTransitionFromFrame(clip: IClip, timestamp: number): Promise<VideoFrame | ImageBitmap | null | Texture>;
|
|
488
|
+
private getPreviousClipOnTrack;
|
|
489
|
+
/**
|
|
490
|
+
* Renders a clip frame onto a transition texture with red background
|
|
491
|
+
*/
|
|
492
|
+
private renderClipToTransitionTexture;
|
|
493
|
+
removeGlobalEffect(id: string): void;
|
|
494
|
+
clearGlobalEffects(): void;
|
|
495
|
+
private updateActiveGlobalEffect;
|
|
496
|
+
private applyGlobalEffects;
|
|
497
|
+
/**
|
|
498
|
+
* Destroy the studio and clean up resources
|
|
499
|
+
*/
|
|
500
|
+
destroy(): void;
|
|
501
|
+
/**
|
|
502
|
+
* Select a clip and show transform controls
|
|
503
|
+
* Delegated to InteractionManager
|
|
504
|
+
*/
|
|
505
|
+
selectClip(clip: IClip, addToSelection?: boolean): void;
|
|
506
|
+
/**
|
|
507
|
+
* Set the selection to a specific list of clips
|
|
508
|
+
*/
|
|
509
|
+
setSelection(clips: IClip[]): void;
|
|
510
|
+
/**
|
|
511
|
+
* Select clips by their IDs
|
|
512
|
+
*/
|
|
513
|
+
selectClipsByIds(ids: string[]): void;
|
|
514
|
+
/**
|
|
515
|
+
* Deselect the current clip and hide transform controls
|
|
516
|
+
*/
|
|
517
|
+
deselectClip(): void;
|
|
518
|
+
/**
|
|
519
|
+
* Toggle lock state of a clip
|
|
520
|
+
*/
|
|
521
|
+
lockClip(clipId: string, locked: boolean): Promise<void>;
|
|
522
|
+
/**
|
|
523
|
+
* Export current studio state to JSON
|
|
524
|
+
* @param sourceUrlMap Optional map of clips to their source URLs (required for proper serialization)
|
|
525
|
+
*/
|
|
526
|
+
exportToJSON(): ProjectJSON;
|
|
527
|
+
loadFromJSON(json: ProjectJSON): Promise<void>;
|
|
528
|
+
}
|
|
529
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Graphics, Point } from 'pixi.js';
|
|
2
|
+
export type Side = "ml" | "mr" | "mt" | "mb";
|
|
3
|
+
type Corner = "tl" | "tr" | "bl" | "br" | "rot" | "rot_tl" | "rot_tr" | "rot_bl" | "rot_br";
|
|
4
|
+
export type HandleKind = Corner | Side;
|
|
5
|
+
interface Callbacks {
|
|
6
|
+
beginDrag: (handle: HandleKind, start: Point) => void;
|
|
7
|
+
updateDrag: (handle: HandleKind, pos: Point) => void;
|
|
8
|
+
endDrag: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare class Handle extends Graphics {
|
|
11
|
+
#private;
|
|
12
|
+
private handle;
|
|
13
|
+
cursor: string;
|
|
14
|
+
private callbacks;
|
|
15
|
+
constructor(handle: HandleKind, cursor: string, callbacks: Callbacks);
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Point, Rectangle } from 'pixi.js';
|
|
2
|
+
export interface SnapGuide {
|
|
3
|
+
type: "vertical" | "horizontal";
|
|
4
|
+
position: number;
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SnapResult {
|
|
9
|
+
x: number | null;
|
|
10
|
+
y: number | null;
|
|
11
|
+
guides: SnapGuide[];
|
|
12
|
+
}
|
|
13
|
+
export declare class SnappingManager {
|
|
14
|
+
private artboardWidth;
|
|
15
|
+
private artboardHeight;
|
|
16
|
+
private scale;
|
|
17
|
+
static SNAP_THRESHOLD: number;
|
|
18
|
+
constructor(artboardWidth: number, artboardHeight: number, scale?: number);
|
|
19
|
+
updateContext(width: number, height: number, scale: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* Snap a rectangle (bounds of the object) to artboard edges and center, as well as other objects.
|
|
22
|
+
* returns delta (adjustment) needed for x and y
|
|
23
|
+
*/
|
|
24
|
+
snapMove(current: Rectangle, otherBounds?: Rectangle[]): {
|
|
25
|
+
dx: number;
|
|
26
|
+
dy: number;
|
|
27
|
+
guides: SnapGuide[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Snap during scaling - only snaps the moving edges based on the handle.
|
|
31
|
+
* This prevents false triggers when stationary edges align with artboard edges.
|
|
32
|
+
* @param proposed - The proposed rectangle in local coordinates
|
|
33
|
+
* @param proposedWorld - The world position of the proposed rect's origin (top-left)
|
|
34
|
+
* @param handle - Which resize handle is being dragged
|
|
35
|
+
* @param otherBounds - Optional other clip bounds in parent space to snap to
|
|
36
|
+
*/
|
|
37
|
+
snapResize(proposed: Rectangle, proposedWorld: Point, handle: "tl" | "tr" | "bl" | "br" | "ml" | "mr" | "mt" | "mb", otherBounds?: Rectangle[]): {
|
|
38
|
+
corrected: Rectangle;
|
|
39
|
+
guides: SnapGuide[];
|
|
40
|
+
};
|
|
41
|
+
snapPoint(point: Point): {
|
|
42
|
+
p: Point;
|
|
43
|
+
guides: SnapGuide[];
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Container, Point, Graphics } from 'pixi.js';
|
|
2
|
+
import { Wireframe } from './wireframe';
|
|
3
|
+
import { HandleKind } from './handle';
|
|
4
|
+
export declare class Transformer extends Container {
|
|
5
|
+
#private;
|
|
6
|
+
group: Container[];
|
|
7
|
+
wireframe: Wireframe;
|
|
8
|
+
selectionOutlines: Graphics;
|
|
9
|
+
isDragging: boolean;
|
|
10
|
+
lastPointer: Point;
|
|
11
|
+
activeHandle: HandleKind | null;
|
|
12
|
+
opts: {
|
|
13
|
+
group: Container[];
|
|
14
|
+
centeredScaling?: boolean;
|
|
15
|
+
clip?: any;
|
|
16
|
+
artboardWidth?: number;
|
|
17
|
+
artboardHeight?: number;
|
|
18
|
+
locked?: boolean;
|
|
19
|
+
};
|
|
20
|
+
constructor(opts: {
|
|
21
|
+
group: Container[];
|
|
22
|
+
centeredScaling?: boolean;
|
|
23
|
+
clip?: any;
|
|
24
|
+
artboardWidth?: number;
|
|
25
|
+
artboardHeight?: number;
|
|
26
|
+
locked?: boolean;
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Immediately initialize bounds and show transformer.
|
|
30
|
+
* Useful when we want to show it without waiting for the next tick.
|
|
31
|
+
*/
|
|
32
|
+
showImmediate(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Public method to update transformer bounds without recreating it
|
|
35
|
+
* Useful for updating bounds after clip dimensions change
|
|
36
|
+
*/
|
|
37
|
+
updateBounds(): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fragment: (glsl: string) => string;
|