@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.
Files changed (93) hide show
  1. package/LICENSE +47 -0
  2. package/NOTICE.md +20 -0
  3. package/README.md +6 -2
  4. package/dist/animation/block-reveal-animation.d.ts +33 -0
  5. package/dist/animation/easings.d.ts +4 -0
  6. package/dist/animation/gsap-animation.d.ts +32 -0
  7. package/dist/animation/index.d.ts +9 -0
  8. package/dist/animation/keyframe-animation.d.ts +11 -0
  9. package/dist/animation/mask-animation.d.ts +170 -0
  10. package/dist/animation/pixi-animation-utils.d.ts +10 -0
  11. package/dist/animation/registry.d.ts +11 -0
  12. package/dist/animation/types.d.ts +211 -0
  13. package/dist/animation/wipe-animation.d.ts +53 -0
  14. package/dist/clips/audio-clip.d.ts +122 -0
  15. package/dist/clips/backdrop-clip.d.ts +56 -0
  16. package/dist/clips/base-clip.d.ts +150 -0
  17. package/dist/clips/base-text-clip.d.ts +228 -0
  18. package/dist/clips/caption-clip.d.ts +129 -0
  19. package/dist/clips/clip-registry.d.ts +56 -0
  20. package/dist/clips/effect-clip.d.ts +37 -0
  21. package/dist/clips/iclip.d.ts +235 -0
  22. package/dist/clips/image-clip.d.ts +116 -0
  23. package/dist/clips/index.d.ts +20 -0
  24. package/dist/clips/placeholder-clip.d.ts +22 -0
  25. package/dist/clips/shape-clip.d.ts +59 -0
  26. package/dist/clips/text-clip.d.ts +148 -0
  27. package/dist/clips/transition-clip.d.ts +45 -0
  28. package/dist/clips/video-clip.d.ts +216 -0
  29. package/dist/compositor/audio-mixer.d.ts +8 -0
  30. package/dist/compositor/av-encoder.d.ts +17 -0
  31. package/dist/compositor/clip-style-renderer.d.ts +23 -0
  32. package/dist/compositor/compositor-renderer.d.ts +29 -0
  33. package/dist/compositor/effect-manager.d.ts +30 -0
  34. package/dist/compositor/scheduler.d.ts +8 -0
  35. package/dist/compositor/transition-manager.d.ts +45 -0
  36. package/dist/compositor.d.ts +157 -0
  37. package/dist/effect/constant/index.d.ts +566 -0
  38. package/dist/effect/effect.d.ts +9 -0
  39. package/dist/effect/glsl/custom-glsl.d.ts +1043 -0
  40. package/dist/effect/glsl/gl-effect.d.ts +38 -0
  41. package/dist/effect/interface/index.d.ts +25 -0
  42. package/dist/effect/types.d.ts +26 -0
  43. package/dist/effect/vertex.d.ts +1 -0
  44. package/dist/event-emitter.d.ts +55 -0
  45. package/dist/filters/outline-filter.d.ts +28 -0
  46. package/dist/index.d.ts +27 -0
  47. package/dist/index.es.js +16144 -0
  48. package/dist/index.es.js.map +1 -0
  49. package/dist/index.umd.cjs +3335 -0
  50. package/dist/index.umd.cjs.map +1 -0
  51. package/dist/json-serialization.d.ts +312 -0
  52. package/dist/mp4-utils/index.d.ts +31 -0
  53. package/dist/mp4-utils/mp4box-utils.d.ts +44 -0
  54. package/dist/mp4-utils/sample-transform.d.ts +26 -0
  55. package/dist/sprite/base-sprite.d.ts +273 -0
  56. package/dist/sprite/pixi-sprite-renderer.d.ts +69 -0
  57. package/dist/standalone/index.es.js +94191 -0
  58. package/dist/standalone/index.es.js.map +1 -0
  59. package/dist/studio/history-manager.d.ts +46 -0
  60. package/dist/studio/resource-manager.d.ts +53 -0
  61. package/dist/studio/selection-manager.d.ts +66 -0
  62. package/dist/studio/timeline-model.d.ts +117 -0
  63. package/dist/studio/transport.d.ts +44 -0
  64. package/dist/studio-bridge.d.ts +50 -0
  65. package/dist/studio.d.ts +529 -0
  66. package/dist/transformer/handle.d.ts +17 -0
  67. package/dist/transformer/snapping.d.ts +45 -0
  68. package/dist/transformer/transformer.d.ts +38 -0
  69. package/dist/transformer/wireframe.d.ts +5 -0
  70. package/dist/transition/fragment.d.ts +1 -0
  71. package/dist/transition/glsl/custom-glsl.d.ts +231 -0
  72. package/dist/transition/glsl/gl-transition.d.ts +42 -0
  73. package/dist/transition/transition.d.ts +6 -0
  74. package/dist/transition/types.d.ts +31 -0
  75. package/dist/transition/uniforms.d.ts +35 -0
  76. package/dist/transition/vertex.d.ts +1 -0
  77. package/dist/utils/asset-manager.d.ts +15 -0
  78. package/dist/utils/audio-codec-detector.d.ts +39 -0
  79. package/dist/utils/audio.d.ts +81 -0
  80. package/dist/utils/chromakey.d.ts +24 -0
  81. package/dist/utils/color-adjustment.d.ts +53 -0
  82. package/dist/utils/color.d.ts +17 -0
  83. package/dist/utils/common.d.ts +7 -0
  84. package/dist/utils/dom.d.ts +48 -0
  85. package/dist/utils/effect.d.ts +1 -0
  86. package/dist/utils/fonts.d.ts +21 -0
  87. package/dist/utils/index.d.ts +6 -0
  88. package/dist/utils/log.d.ts +27 -0
  89. package/dist/utils/media-cache.d.ts +45 -0
  90. package/dist/utils/stream-utils.d.ts +4 -0
  91. package/dist/utils/video.d.ts +16 -0
  92. package/dist/utils/worker-timer.d.ts +1 -0
  93. package/package.json +63 -3
@@ -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,5 @@
1
+ import { Graphics, Rectangle } from 'pixi.js';
2
+ export declare class Wireframe extends Graphics {
3
+ constructor();
4
+ draw(bounds: Rectangle, scale?: number): void;
5
+ }
@@ -0,0 +1 @@
1
+ export declare const fragment: (glsl: string) => string;