@pixerate/editor 0.231.1 → 0.233.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/dist/animation-editor/compile.d.cts +3 -0
- package/dist/animation-editor/compile.d.ts +3 -0
- package/dist/animation-editor/controller.d.cts +67 -2
- package/dist/animation-editor/controller.d.ts +67 -2
- package/dist/animation-editor/edit.d.cts +1 -1
- package/dist/animation-editor/edit.d.ts +1 -1
- package/dist/animation-editor/evaluate.d.cts +8 -1
- package/dist/animation-editor/evaluate.d.ts +8 -1
- package/dist/animation-editor/index.cjs +1202 -371
- package/dist/animation-editor/index.d.cts +3 -0
- package/dist/animation-editor/index.d.ts +3 -0
- package/dist/animation-editor/index.js +1032 -201
- package/dist/animation-editor/issues.d.cts +28 -0
- package/dist/animation-editor/issues.d.ts +28 -0
- package/dist/animation-editor/layer-edit.d.cts +55 -0
- package/dist/animation-editor/layer-edit.d.ts +55 -0
- package/dist/animation-editor/layer-tools.d.cts +11 -0
- package/dist/animation-editor/layer-tools.d.ts +11 -0
- package/dist/animation-editor/layers.d.cts +166 -0
- package/dist/animation-editor/layers.d.ts +166 -0
- package/dist/animation-editor/parse.d.cts +2 -0
- package/dist/animation-editor/parse.d.ts +2 -0
- package/dist/animation-editor/types.d.cts +44 -1
- package/dist/animation-editor/types.d.ts +44 -1
- package/dist/canvas/index.cjs +10 -10
- package/dist/canvas/index.js +4 -4
- package/dist/chunk-6RZVFYGJ.cjs +255 -0
- package/dist/{chunk-C73U5UI3.cjs → chunk-A7PQNIBX.cjs} +14 -14
- package/dist/{chunk-ERJA5CGT.cjs → chunk-DGWOGQJ5.cjs} +8 -1
- package/dist/{chunk-TYCJGFCF.js → chunk-EUKY4KFX.js} +8 -1
- package/dist/chunk-I277KJLQ.js +255 -0
- package/dist/{chunk-OPSK22DL.cjs → chunk-JAOSL334.cjs} +24 -7
- package/dist/{chunk-TCZ2J7PR.js → chunk-SIK3LT6M.js} +26 -9
- package/dist/{chunk-SBPGIZQN.js → chunk-TEFQISBY.js} +1 -1
- package/dist/{chunk-CSM5T6SE.js → chunk-WDDUPWVG.js} +1 -1
- package/dist/{chunk-5T3H7CGG.cjs → chunk-ZQIWBJGH.cjs} +7 -7
- package/dist/effects/conformance.d.cts +4 -1
- package/dist/effects/conformance.d.ts +4 -1
- package/dist/effects/errors.d.cts +6 -1
- package/dist/effects/errors.d.ts +6 -1
- package/dist/effects/fake-templates.d.cts +17 -0
- package/dist/effects/fake-templates.d.ts +17 -0
- package/dist/effects/fake.d.cts +6 -1
- package/dist/effects/fake.d.ts +6 -1
- package/dist/effects/index.cjs +322 -67
- package/dist/effects/index.d.cts +1 -0
- package/dist/effects/index.d.ts +1 -0
- package/dist/effects/index.js +258 -3
- package/dist/effects/templates.d.cts +56 -0
- package/dist/effects/templates.d.ts +56 -0
- package/dist/effects/types.d.cts +212 -0
- package/dist/effects/types.d.ts +212 -0
- package/dist/image-editor/index.cjs +16 -16
- package/dist/image-editor/index.js +4 -4
- package/dist/paint-editor/index.cjs +10 -10
- package/dist/paint-editor/index.js +5 -5
- package/dist/vector/index.cjs +6 -6
- package/dist/vector/index.js +1 -1
- package/dist/video-editor/index.cjs +339 -339
- package/dist/video-editor/index.js +5 -5
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +37 -0
|
@@ -159,6 +159,34 @@ export declare const MOTION_ISSUE_CODES: {
|
|
|
159
159
|
readonly severity: "error";
|
|
160
160
|
readonly wording: "A camera move's preset or values do not fit its controls.";
|
|
161
161
|
};
|
|
162
|
+
readonly 'layer-effect-unknown': {
|
|
163
|
+
readonly severity: "error";
|
|
164
|
+
readonly wording: "A shot layer names an effect the provider does not have, one that cannot be a layer, or a subject its effect cannot take.";
|
|
165
|
+
};
|
|
166
|
+
readonly 'layer-effect-values': {
|
|
167
|
+
readonly severity: "error";
|
|
168
|
+
readonly wording: "A shot layer's preset or values do not fit its effect's controls.";
|
|
169
|
+
};
|
|
170
|
+
readonly 'layer-not-drawn': {
|
|
171
|
+
readonly severity: "note";
|
|
172
|
+
readonly wording: "Shot layers name provider effects, but there is no effects provider to draw them, so they are left out of frames.";
|
|
173
|
+
};
|
|
174
|
+
readonly 'layer-slot-empty': {
|
|
175
|
+
readonly severity: "warning";
|
|
176
|
+
readonly wording: "A shot layer's subject is a slot nobody has filled, so it draws nothing.";
|
|
177
|
+
};
|
|
178
|
+
readonly 'transition-unknown': {
|
|
179
|
+
readonly severity: "error";
|
|
180
|
+
readonly wording: "A shot names a transition the provider does not have, or an effect that is not a transition.";
|
|
181
|
+
};
|
|
182
|
+
readonly 'transition-first-shot': {
|
|
183
|
+
readonly severity: "note";
|
|
184
|
+
readonly wording: "The first shot has a transition, but there is no shot before it, so it does not play.";
|
|
185
|
+
};
|
|
186
|
+
readonly 'transition-not-played': {
|
|
187
|
+
readonly severity: "note";
|
|
188
|
+
readonly wording: "Shots name transitions, but there is no effects provider to play them, so they crossfade.";
|
|
189
|
+
};
|
|
162
190
|
};
|
|
163
191
|
export type MotionIssueCode = keyof typeof MOTION_ISSUE_CODES;
|
|
164
192
|
export interface MotionIssue {
|
|
@@ -159,6 +159,34 @@ export declare const MOTION_ISSUE_CODES: {
|
|
|
159
159
|
readonly severity: "error";
|
|
160
160
|
readonly wording: "A camera move's preset or values do not fit its controls.";
|
|
161
161
|
};
|
|
162
|
+
readonly 'layer-effect-unknown': {
|
|
163
|
+
readonly severity: "error";
|
|
164
|
+
readonly wording: "A shot layer names an effect the provider does not have, one that cannot be a layer, or a subject its effect cannot take.";
|
|
165
|
+
};
|
|
166
|
+
readonly 'layer-effect-values': {
|
|
167
|
+
readonly severity: "error";
|
|
168
|
+
readonly wording: "A shot layer's preset or values do not fit its effect's controls.";
|
|
169
|
+
};
|
|
170
|
+
readonly 'layer-not-drawn': {
|
|
171
|
+
readonly severity: "note";
|
|
172
|
+
readonly wording: "Shot layers name provider effects, but there is no effects provider to draw them, so they are left out of frames.";
|
|
173
|
+
};
|
|
174
|
+
readonly 'layer-slot-empty': {
|
|
175
|
+
readonly severity: "warning";
|
|
176
|
+
readonly wording: "A shot layer's subject is a slot nobody has filled, so it draws nothing.";
|
|
177
|
+
};
|
|
178
|
+
readonly 'transition-unknown': {
|
|
179
|
+
readonly severity: "error";
|
|
180
|
+
readonly wording: "A shot names a transition the provider does not have, or an effect that is not a transition.";
|
|
181
|
+
};
|
|
182
|
+
readonly 'transition-first-shot': {
|
|
183
|
+
readonly severity: "note";
|
|
184
|
+
readonly wording: "The first shot has a transition, but there is no shot before it, so it does not play.";
|
|
185
|
+
};
|
|
186
|
+
readonly 'transition-not-played': {
|
|
187
|
+
readonly severity: "note";
|
|
188
|
+
readonly wording: "Shots name transitions, but there is no effects provider to play them, so they crossfade.";
|
|
189
|
+
};
|
|
162
190
|
};
|
|
163
191
|
export type MotionIssueCode = keyof typeof MOTION_ISSUE_CODES;
|
|
164
192
|
export interface MotionIssue {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checking shot layers and transitions against an effects provider before they are saved, and
|
|
3
|
+
* describing them for tools and panels. A layer's effect must be one a layer can show (a
|
|
4
|
+
* generator, filter, overlay or title), take the subject it is given (or need none), and have
|
|
5
|
+
* values and a preset that fit; a transition's effect must have the use `transition`. A preset's
|
|
6
|
+
* values are written out, so the scene plays the same without the provider's presets.
|
|
7
|
+
*/
|
|
8
|
+
import { type EffectProvider } from '../effects/types.cjs';
|
|
9
|
+
import { type MotionIssue } from './issues.cjs';
|
|
10
|
+
import type { MotionScene, MotionShotLayer, MotionShotTransition } from './types.cjs';
|
|
11
|
+
/** A layer as tools and panels report it: its fields, its shot and when it shows (ms). */
|
|
12
|
+
export interface MotionShotLayerInfo extends MotionShotLayer {
|
|
13
|
+
shot: string;
|
|
14
|
+
/** Its place in the shot (0 = bottom). */
|
|
15
|
+
index: number;
|
|
16
|
+
role: NonNullable<MotionShotLayer['role']>;
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
}
|
|
20
|
+
/** A shot's layers and transition. */
|
|
21
|
+
export interface MotionShotLayersInfo {
|
|
22
|
+
shot: string;
|
|
23
|
+
layers: MotionShotLayerInfo[];
|
|
24
|
+
/** Its transition with when it plays, or null (the first shot never has one). */
|
|
25
|
+
transition: (MotionShotTransition & {
|
|
26
|
+
start: number;
|
|
27
|
+
end: number;
|
|
28
|
+
}) | null;
|
|
29
|
+
}
|
|
30
|
+
/** Every shot's layers and transition (or one shot's). */
|
|
31
|
+
export declare function motionShotLayersInfo(scene: MotionScene, shot?: string): MotionShotLayersInfo[];
|
|
32
|
+
/** The shot holding a layer, and its index there. */
|
|
33
|
+
export declare function findMotionShotLayer(scene: MotionScene, id: string): {
|
|
34
|
+
shot: number;
|
|
35
|
+
index: number;
|
|
36
|
+
} | null;
|
|
37
|
+
/** Every layer id in the scene. */
|
|
38
|
+
export declare const motionLayerIds: (scene: MotionScene) => string[];
|
|
39
|
+
/** A free layer id: `layer1`, `layer2`… */
|
|
40
|
+
export declare function freshMotionLayerId(scene: MotionScene, base?: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Checks a layer against the provider and returns it as it is saved (with the effect's provider
|
|
43
|
+
* and name, a preset's values written out). Throws a sentence saying what to do for an effect
|
|
44
|
+
* that cannot be a layer, a subject it cannot take (or a picture it needs and lacks), and values
|
|
45
|
+
* or a preset that do not fit. A bare subject (no `effect`) needs no provider.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveMotionShotLayer(provider: EffectProvider | null, layer: MotionShotLayer): Promise<MotionShotLayer>;
|
|
48
|
+
/** Checks a transition against the provider and returns it as it is saved (its length written out). */
|
|
49
|
+
export declare function resolveMotionShotTransition(provider: EffectProvider | null, transition: MotionShotTransition): Promise<MotionShotTransition>;
|
|
50
|
+
/**
|
|
51
|
+
* Problems with the scene's shot layers and transitions against a provider: effects it does not
|
|
52
|
+
* have or that do not fit (errors), empty slots (warnings), and, without a provider, notes that
|
|
53
|
+
* effect layers are not drawn and transitions crossfade.
|
|
54
|
+
*/
|
|
55
|
+
export declare function checkMotionShotLayers(scene: MotionScene, provider: EffectProvider | null | undefined): Promise<MotionIssue[]>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checking shot layers and transitions against an effects provider before they are saved, and
|
|
3
|
+
* describing them for tools and panels. A layer's effect must be one a layer can show (a
|
|
4
|
+
* generator, filter, overlay or title), take the subject it is given (or need none), and have
|
|
5
|
+
* values and a preset that fit; a transition's effect must have the use `transition`. A preset's
|
|
6
|
+
* values are written out, so the scene plays the same without the provider's presets.
|
|
7
|
+
*/
|
|
8
|
+
import { type EffectProvider } from '../effects/types.js';
|
|
9
|
+
import { type MotionIssue } from './issues.js';
|
|
10
|
+
import type { MotionScene, MotionShotLayer, MotionShotTransition } from './types.js';
|
|
11
|
+
/** A layer as tools and panels report it: its fields, its shot and when it shows (ms). */
|
|
12
|
+
export interface MotionShotLayerInfo extends MotionShotLayer {
|
|
13
|
+
shot: string;
|
|
14
|
+
/** Its place in the shot (0 = bottom). */
|
|
15
|
+
index: number;
|
|
16
|
+
role: NonNullable<MotionShotLayer['role']>;
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
}
|
|
20
|
+
/** A shot's layers and transition. */
|
|
21
|
+
export interface MotionShotLayersInfo {
|
|
22
|
+
shot: string;
|
|
23
|
+
layers: MotionShotLayerInfo[];
|
|
24
|
+
/** Its transition with when it plays, or null (the first shot never has one). */
|
|
25
|
+
transition: (MotionShotTransition & {
|
|
26
|
+
start: number;
|
|
27
|
+
end: number;
|
|
28
|
+
}) | null;
|
|
29
|
+
}
|
|
30
|
+
/** Every shot's layers and transition (or one shot's). */
|
|
31
|
+
export declare function motionShotLayersInfo(scene: MotionScene, shot?: string): MotionShotLayersInfo[];
|
|
32
|
+
/** The shot holding a layer, and its index there. */
|
|
33
|
+
export declare function findMotionShotLayer(scene: MotionScene, id: string): {
|
|
34
|
+
shot: number;
|
|
35
|
+
index: number;
|
|
36
|
+
} | null;
|
|
37
|
+
/** Every layer id in the scene. */
|
|
38
|
+
export declare const motionLayerIds: (scene: MotionScene) => string[];
|
|
39
|
+
/** A free layer id: `layer1`, `layer2`… */
|
|
40
|
+
export declare function freshMotionLayerId(scene: MotionScene, base?: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Checks a layer against the provider and returns it as it is saved (with the effect's provider
|
|
43
|
+
* and name, a preset's values written out). Throws a sentence saying what to do for an effect
|
|
44
|
+
* that cannot be a layer, a subject it cannot take (or a picture it needs and lacks), and values
|
|
45
|
+
* or a preset that do not fit. A bare subject (no `effect`) needs no provider.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveMotionShotLayer(provider: EffectProvider | null, layer: MotionShotLayer): Promise<MotionShotLayer>;
|
|
48
|
+
/** Checks a transition against the provider and returns it as it is saved (its length written out). */
|
|
49
|
+
export declare function resolveMotionShotTransition(provider: EffectProvider | null, transition: MotionShotTransition): Promise<MotionShotTransition>;
|
|
50
|
+
/**
|
|
51
|
+
* Problems with the scene's shot layers and transitions against a provider: effects it does not
|
|
52
|
+
* have or that do not fit (errors), empty slots (warnings), and, without a provider, notes that
|
|
53
|
+
* effect layers are not drawn and transitions crossfade.
|
|
54
|
+
*/
|
|
55
|
+
export declare function checkMotionShotLayers(scene: MotionScene, provider: EffectProvider | null | undefined): Promise<MotionIssue[]>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for shot layers and transitions in the animation editor (`MotionShot.layers` /
|
|
3
|
+
* `transition`): list them, add, change, restack and remove layers, and set or clear the
|
|
4
|
+
* transition into a shot. They ride on the animation effects tool provider
|
|
5
|
+
* (`createAnimationEffectsToolProvider`), next to the other provider effects.
|
|
6
|
+
*/
|
|
7
|
+
import type { EffectToolContext } from '../effects/tools.cjs';
|
|
8
|
+
import type { AgentTool } from '../tools/registry.cjs';
|
|
9
|
+
import type { AnimationEditorController } from './controller.cjs';
|
|
10
|
+
/** The shot layer and transition tools (see the module comment). */
|
|
11
|
+
export declare function animationShotLayerTools(controller: AnimationEditorController, ctx: EffectToolContext): AgentTool[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for shot layers and transitions in the animation editor (`MotionShot.layers` /
|
|
3
|
+
* `transition`): list them, add, change, restack and remove layers, and set or clear the
|
|
4
|
+
* transition into a shot. They ride on the animation effects tool provider
|
|
5
|
+
* (`createAnimationEffectsToolProvider`), next to the other provider effects.
|
|
6
|
+
*/
|
|
7
|
+
import type { EffectToolContext } from '../effects/tools.js';
|
|
8
|
+
import type { AgentTool } from '../tools/registry.js';
|
|
9
|
+
import type { AnimationEditorController } from './controller.js';
|
|
10
|
+
/** The shot layer and transition tools (see the module comment). */
|
|
11
|
+
export declare function animationShotLayerTools(controller: AnimationEditorController, ctx: EffectToolContext): AgentTool[];
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shot layers and transitions (see `MotionShotLayer`, `MotionShotTransition`): when each layer
|
|
3
|
+
* shows, how it is drawn into a frame's SVG, and `MotionLayersEngine`, which renders provider
|
|
4
|
+
* effect layers and transitions to pictures.
|
|
5
|
+
*
|
|
6
|
+
* Frames stay SVG and stay a pure function of time: a layer's pixels go into the frame as an
|
|
7
|
+
* `<image>` (`background` layers under the artwork, `subject` and `overlay` layers over it), taken
|
|
8
|
+
* from the engine's cache. A picture that is not rendered yet is left out and the engine renders it
|
|
9
|
+
* in the background, then tells the editor to draw again; `idle()` waits for every picture asked
|
|
10
|
+
* for, so `AnimationEditorController.toSvgExact` draws exact frames.
|
|
11
|
+
*
|
|
12
|
+
* A transition replaces the frame for its length with the provider's blend of the last frame of the
|
|
13
|
+
* shot before (`from`) and the live frame of its own shot (`to`). Both are drawn as SVG and turned
|
|
14
|
+
* into pixels by the host (`MotionLayerHost.rasterize`). Until it is rendered (or with no provider
|
|
15
|
+
* or host) the two frames crossfade.
|
|
16
|
+
*/
|
|
17
|
+
import { EffectsSlot } from '../effects/helpers.cjs';
|
|
18
|
+
import type { EffectDescription, EffectLayerRole, EffectPixels, EffectProvider } from '../effects/types.cjs';
|
|
19
|
+
import type { MotionLayerSubject, MotionRect, MotionScene, MotionShotLayer } from './types.cjs';
|
|
20
|
+
/** When a layer shows. */
|
|
21
|
+
export interface MotionLayerSpan {
|
|
22
|
+
layer: MotionShotLayer;
|
|
23
|
+
shot: string;
|
|
24
|
+
shotIndex: number;
|
|
25
|
+
/** Its place in its shot's `layers`. */
|
|
26
|
+
index: number;
|
|
27
|
+
role: EffectLayerRole;
|
|
28
|
+
start: number;
|
|
29
|
+
end: number;
|
|
30
|
+
}
|
|
31
|
+
/** A layer showing at a moment. */
|
|
32
|
+
export interface MotionActiveLayer extends MotionLayerSpan {
|
|
33
|
+
/** Ms since the layer started: the time its effect is drawn at. */
|
|
34
|
+
time: number;
|
|
35
|
+
/** Its opacity now, with its fade. */
|
|
36
|
+
opacity: number;
|
|
37
|
+
}
|
|
38
|
+
/** A transition at a moment. */
|
|
39
|
+
export interface MotionActiveTransition {
|
|
40
|
+
/** The shot it plays into. */
|
|
41
|
+
shot: string;
|
|
42
|
+
shotIndex: number;
|
|
43
|
+
effect: string;
|
|
44
|
+
start: number;
|
|
45
|
+
end: number;
|
|
46
|
+
/** 0 → 1 through it. */
|
|
47
|
+
progress: number;
|
|
48
|
+
}
|
|
49
|
+
/** Every layer of the scene with when it shows, in drawing order (shot by shot, bottom to top). Pure and cached per scene. */
|
|
50
|
+
export declare function motionLayerSpans(scene: MotionScene): MotionLayerSpan[];
|
|
51
|
+
/** The layers showing at `time`, in drawing order, with their effect time and faded opacity. */
|
|
52
|
+
export declare function motionLayersAt(scene: MotionScene, time: number): MotionActiveLayer[];
|
|
53
|
+
/** The transition playing at `time`, if any. */
|
|
54
|
+
export declare function motionTransitionAt(scene: MotionScene, time: number): MotionActiveTransition | null;
|
|
55
|
+
/** True when the scene has shot layers or transitions, so frames need `MotionLayerPictures`. */
|
|
56
|
+
export declare const motionSceneHasLayers: (scene: MotionScene) => boolean;
|
|
57
|
+
/** Where frames get layer pictures from (`MotionLayersEngine`). Each returns an image URL, or undefined while it is not ready. */
|
|
58
|
+
export interface MotionLayerPictures {
|
|
59
|
+
/** The picture of an effect layer at its time (the size of its box). */
|
|
60
|
+
layer(scene: MotionScene, active: MotionActiveLayer, box: MotionRect): string | undefined;
|
|
61
|
+
/** A subject picture as a URL usable inside an SVG image (a `data:` URL). */
|
|
62
|
+
subject(subject: Extract<MotionLayerSubject, {
|
|
63
|
+
image: string;
|
|
64
|
+
}>): string | undefined;
|
|
65
|
+
/** The whole frame during a transition. */
|
|
66
|
+
transition(scene: MotionScene, time: number, active: MotionActiveTransition): string | undefined;
|
|
67
|
+
}
|
|
68
|
+
/** An SVG string as a `data:` URL. */
|
|
69
|
+
export declare const svgDataUrl: (svg: string) => string;
|
|
70
|
+
/**
|
|
71
|
+
* Adds a frame's layers to its SVG (made with the artwork's background left out): the background
|
|
72
|
+
* colour, then `background` layers, the artwork, then `subject` and `overlay` layers. Layers with
|
|
73
|
+
* no `rect` fill the camera's view.
|
|
74
|
+
*/
|
|
75
|
+
export declare function withMotionShotLayers(svg: string, scene: MotionScene, time: number, camera: MotionRect, pictures: MotionLayerPictures | undefined, background: boolean): string;
|
|
76
|
+
/**
|
|
77
|
+
* A frame during a transition: the provider's picture filling the view, or until it is ready a
|
|
78
|
+
* crossfade of the last frame of the shot before (`from`, a whole frame SVG, nested with its own
|
|
79
|
+
* framing) and this frame.
|
|
80
|
+
*/
|
|
81
|
+
export declare function motionTransitionSvg(svg: string, from: string, active: MotionActiveTransition, camera: MotionRect, picture: string | undefined): string;
|
|
82
|
+
/**
|
|
83
|
+
* What the engine needs from its host to make pictures: a browser host is
|
|
84
|
+
* `browserMotionLayerHost()`. Outside a browser, give one that rasterizes SVG (e.g. resvg).
|
|
85
|
+
*/
|
|
86
|
+
export interface MotionLayerHost {
|
|
87
|
+
/** Draws a standalone SVG into pixels of this size (straight alpha). */
|
|
88
|
+
rasterize(svg: string, width: number, height: number): Promise<EffectPixels>;
|
|
89
|
+
/** Pixels as an image URL for an SVG `<image>` (a `data:` URL). */
|
|
90
|
+
encode(pixels: EffectPixels): Promise<string> | string;
|
|
91
|
+
/** A picture URL as a `data:` URL, so it draws inside a rasterized SVG (where outside URLs do not load). */
|
|
92
|
+
loadImage(url: string): Promise<string>;
|
|
93
|
+
}
|
|
94
|
+
export interface MotionLayersEngineOptions {
|
|
95
|
+
slot?: EffectsSlot;
|
|
96
|
+
host?: MotionLayerHost | null;
|
|
97
|
+
/** Pixels per artwork unit of layer pictures (default 1); the longest side is at most `maxSize`. */
|
|
98
|
+
scale?: number;
|
|
99
|
+
/** Longest side of a layer or transition picture (default 1280). */
|
|
100
|
+
maxSize?: number;
|
|
101
|
+
/** Effect time is rounded to this many frames a second, so frames share pictures (default 30). */
|
|
102
|
+
fps?: number;
|
|
103
|
+
/** Pictures kept (default 160). */
|
|
104
|
+
maxEntries?: number;
|
|
105
|
+
maxRenderers?: number;
|
|
106
|
+
/** Draws a frame of a scene as SVG (the controller gives `motionFrameToSvg` with its options). */
|
|
107
|
+
frameSvg?: (scene: MotionScene, time: number) => string;
|
|
108
|
+
}
|
|
109
|
+
/** What a frame would draw (or wait for): failures say why a layer stays empty. */
|
|
110
|
+
export interface MotionLayerFailure {
|
|
111
|
+
key: string;
|
|
112
|
+
layer?: string;
|
|
113
|
+
transition?: string;
|
|
114
|
+
error: Error;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Renders and caches shot layer and transition pictures for one editor. Follows the editor's
|
|
118
|
+
* provider slot: a new provider clears the cache. Without a provider (or a host) it makes no
|
|
119
|
+
* pictures, and frames draw bare subjects and crossfades only.
|
|
120
|
+
*/
|
|
121
|
+
export declare class MotionLayersEngine implements MotionLayerPictures {
|
|
122
|
+
readonly slot: EffectsSlot;
|
|
123
|
+
host: MotionLayerHost | null;
|
|
124
|
+
frameSvg: ((scene: MotionScene, time: number) => string) | undefined;
|
|
125
|
+
private readonly cache;
|
|
126
|
+
private readonly pending;
|
|
127
|
+
private readonly failures;
|
|
128
|
+
private readonly descriptions;
|
|
129
|
+
private readonly listeners;
|
|
130
|
+
private readonly pool;
|
|
131
|
+
private readonly options;
|
|
132
|
+
private generation;
|
|
133
|
+
private readonly detach;
|
|
134
|
+
constructor(options?: MotionLayersEngineOptions);
|
|
135
|
+
get provider(): EffectProvider | null;
|
|
136
|
+
/** Called when a picture is ready (draw the frame again). */
|
|
137
|
+
subscribe(listener: () => void): () => void;
|
|
138
|
+
/** Why pictures failed, newest last. */
|
|
139
|
+
failuresList(): MotionLayerFailure[];
|
|
140
|
+
/** True while any picture is being made. */
|
|
141
|
+
get busy(): boolean;
|
|
142
|
+
/** Resolves once every picture asked for so far is made (or failed). */
|
|
143
|
+
idle(): Promise<void>;
|
|
144
|
+
/** Forgets every picture and failure (a new provider, or the host changed). */
|
|
145
|
+
reset(): void;
|
|
146
|
+
dispose(): void;
|
|
147
|
+
private notify;
|
|
148
|
+
private size;
|
|
149
|
+
private snap;
|
|
150
|
+
private get;
|
|
151
|
+
private request;
|
|
152
|
+
describe(id: string): Promise<EffectDescription>;
|
|
153
|
+
subject(subject: {
|
|
154
|
+
image: string;
|
|
155
|
+
}): string | undefined;
|
|
156
|
+
/** The pixels a layer's subject feeds its effect, at `size`. */
|
|
157
|
+
private subjectPixels;
|
|
158
|
+
layer(scene: MotionScene, active: MotionActiveLayer, b: MotionRect): string | undefined;
|
|
159
|
+
transition(scene: MotionScene, time: number, active: MotionActiveTransition): string | undefined;
|
|
160
|
+
private readonly fromPixels;
|
|
161
|
+
private idleExcept;
|
|
162
|
+
}
|
|
163
|
+
/** A host that draws with the browser's canvas and image decoding, or null outside a browser. */
|
|
164
|
+
export declare function browserMotionLayerHost(doc?: Document | undefined): MotionLayerHost | null;
|
|
165
|
+
/** Whether a scene's layer would draw nothing because its subject slot is empty. */
|
|
166
|
+
export declare const motionLayerSlot: (layer: MotionShotLayer) => string | undefined;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shot layers and transitions (see `MotionShotLayer`, `MotionShotTransition`): when each layer
|
|
3
|
+
* shows, how it is drawn into a frame's SVG, and `MotionLayersEngine`, which renders provider
|
|
4
|
+
* effect layers and transitions to pictures.
|
|
5
|
+
*
|
|
6
|
+
* Frames stay SVG and stay a pure function of time: a layer's pixels go into the frame as an
|
|
7
|
+
* `<image>` (`background` layers under the artwork, `subject` and `overlay` layers over it), taken
|
|
8
|
+
* from the engine's cache. A picture that is not rendered yet is left out and the engine renders it
|
|
9
|
+
* in the background, then tells the editor to draw again; `idle()` waits for every picture asked
|
|
10
|
+
* for, so `AnimationEditorController.toSvgExact` draws exact frames.
|
|
11
|
+
*
|
|
12
|
+
* A transition replaces the frame for its length with the provider's blend of the last frame of the
|
|
13
|
+
* shot before (`from`) and the live frame of its own shot (`to`). Both are drawn as SVG and turned
|
|
14
|
+
* into pixels by the host (`MotionLayerHost.rasterize`). Until it is rendered (or with no provider
|
|
15
|
+
* or host) the two frames crossfade.
|
|
16
|
+
*/
|
|
17
|
+
import { EffectsSlot } from '../effects/helpers.js';
|
|
18
|
+
import type { EffectDescription, EffectLayerRole, EffectPixels, EffectProvider } from '../effects/types.js';
|
|
19
|
+
import type { MotionLayerSubject, MotionRect, MotionScene, MotionShotLayer } from './types.js';
|
|
20
|
+
/** When a layer shows. */
|
|
21
|
+
export interface MotionLayerSpan {
|
|
22
|
+
layer: MotionShotLayer;
|
|
23
|
+
shot: string;
|
|
24
|
+
shotIndex: number;
|
|
25
|
+
/** Its place in its shot's `layers`. */
|
|
26
|
+
index: number;
|
|
27
|
+
role: EffectLayerRole;
|
|
28
|
+
start: number;
|
|
29
|
+
end: number;
|
|
30
|
+
}
|
|
31
|
+
/** A layer showing at a moment. */
|
|
32
|
+
export interface MotionActiveLayer extends MotionLayerSpan {
|
|
33
|
+
/** Ms since the layer started: the time its effect is drawn at. */
|
|
34
|
+
time: number;
|
|
35
|
+
/** Its opacity now, with its fade. */
|
|
36
|
+
opacity: number;
|
|
37
|
+
}
|
|
38
|
+
/** A transition at a moment. */
|
|
39
|
+
export interface MotionActiveTransition {
|
|
40
|
+
/** The shot it plays into. */
|
|
41
|
+
shot: string;
|
|
42
|
+
shotIndex: number;
|
|
43
|
+
effect: string;
|
|
44
|
+
start: number;
|
|
45
|
+
end: number;
|
|
46
|
+
/** 0 → 1 through it. */
|
|
47
|
+
progress: number;
|
|
48
|
+
}
|
|
49
|
+
/** Every layer of the scene with when it shows, in drawing order (shot by shot, bottom to top). Pure and cached per scene. */
|
|
50
|
+
export declare function motionLayerSpans(scene: MotionScene): MotionLayerSpan[];
|
|
51
|
+
/** The layers showing at `time`, in drawing order, with their effect time and faded opacity. */
|
|
52
|
+
export declare function motionLayersAt(scene: MotionScene, time: number): MotionActiveLayer[];
|
|
53
|
+
/** The transition playing at `time`, if any. */
|
|
54
|
+
export declare function motionTransitionAt(scene: MotionScene, time: number): MotionActiveTransition | null;
|
|
55
|
+
/** True when the scene has shot layers or transitions, so frames need `MotionLayerPictures`. */
|
|
56
|
+
export declare const motionSceneHasLayers: (scene: MotionScene) => boolean;
|
|
57
|
+
/** Where frames get layer pictures from (`MotionLayersEngine`). Each returns an image URL, or undefined while it is not ready. */
|
|
58
|
+
export interface MotionLayerPictures {
|
|
59
|
+
/** The picture of an effect layer at its time (the size of its box). */
|
|
60
|
+
layer(scene: MotionScene, active: MotionActiveLayer, box: MotionRect): string | undefined;
|
|
61
|
+
/** A subject picture as a URL usable inside an SVG image (a `data:` URL). */
|
|
62
|
+
subject(subject: Extract<MotionLayerSubject, {
|
|
63
|
+
image: string;
|
|
64
|
+
}>): string | undefined;
|
|
65
|
+
/** The whole frame during a transition. */
|
|
66
|
+
transition(scene: MotionScene, time: number, active: MotionActiveTransition): string | undefined;
|
|
67
|
+
}
|
|
68
|
+
/** An SVG string as a `data:` URL. */
|
|
69
|
+
export declare const svgDataUrl: (svg: string) => string;
|
|
70
|
+
/**
|
|
71
|
+
* Adds a frame's layers to its SVG (made with the artwork's background left out): the background
|
|
72
|
+
* colour, then `background` layers, the artwork, then `subject` and `overlay` layers. Layers with
|
|
73
|
+
* no `rect` fill the camera's view.
|
|
74
|
+
*/
|
|
75
|
+
export declare function withMotionShotLayers(svg: string, scene: MotionScene, time: number, camera: MotionRect, pictures: MotionLayerPictures | undefined, background: boolean): string;
|
|
76
|
+
/**
|
|
77
|
+
* A frame during a transition: the provider's picture filling the view, or until it is ready a
|
|
78
|
+
* crossfade of the last frame of the shot before (`from`, a whole frame SVG, nested with its own
|
|
79
|
+
* framing) and this frame.
|
|
80
|
+
*/
|
|
81
|
+
export declare function motionTransitionSvg(svg: string, from: string, active: MotionActiveTransition, camera: MotionRect, picture: string | undefined): string;
|
|
82
|
+
/**
|
|
83
|
+
* What the engine needs from its host to make pictures: a browser host is
|
|
84
|
+
* `browserMotionLayerHost()`. Outside a browser, give one that rasterizes SVG (e.g. resvg).
|
|
85
|
+
*/
|
|
86
|
+
export interface MotionLayerHost {
|
|
87
|
+
/** Draws a standalone SVG into pixels of this size (straight alpha). */
|
|
88
|
+
rasterize(svg: string, width: number, height: number): Promise<EffectPixels>;
|
|
89
|
+
/** Pixels as an image URL for an SVG `<image>` (a `data:` URL). */
|
|
90
|
+
encode(pixels: EffectPixels): Promise<string> | string;
|
|
91
|
+
/** A picture URL as a `data:` URL, so it draws inside a rasterized SVG (where outside URLs do not load). */
|
|
92
|
+
loadImage(url: string): Promise<string>;
|
|
93
|
+
}
|
|
94
|
+
export interface MotionLayersEngineOptions {
|
|
95
|
+
slot?: EffectsSlot;
|
|
96
|
+
host?: MotionLayerHost | null;
|
|
97
|
+
/** Pixels per artwork unit of layer pictures (default 1); the longest side is at most `maxSize`. */
|
|
98
|
+
scale?: number;
|
|
99
|
+
/** Longest side of a layer or transition picture (default 1280). */
|
|
100
|
+
maxSize?: number;
|
|
101
|
+
/** Effect time is rounded to this many frames a second, so frames share pictures (default 30). */
|
|
102
|
+
fps?: number;
|
|
103
|
+
/** Pictures kept (default 160). */
|
|
104
|
+
maxEntries?: number;
|
|
105
|
+
maxRenderers?: number;
|
|
106
|
+
/** Draws a frame of a scene as SVG (the controller gives `motionFrameToSvg` with its options). */
|
|
107
|
+
frameSvg?: (scene: MotionScene, time: number) => string;
|
|
108
|
+
}
|
|
109
|
+
/** What a frame would draw (or wait for): failures say why a layer stays empty. */
|
|
110
|
+
export interface MotionLayerFailure {
|
|
111
|
+
key: string;
|
|
112
|
+
layer?: string;
|
|
113
|
+
transition?: string;
|
|
114
|
+
error: Error;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Renders and caches shot layer and transition pictures for one editor. Follows the editor's
|
|
118
|
+
* provider slot: a new provider clears the cache. Without a provider (or a host) it makes no
|
|
119
|
+
* pictures, and frames draw bare subjects and crossfades only.
|
|
120
|
+
*/
|
|
121
|
+
export declare class MotionLayersEngine implements MotionLayerPictures {
|
|
122
|
+
readonly slot: EffectsSlot;
|
|
123
|
+
host: MotionLayerHost | null;
|
|
124
|
+
frameSvg: ((scene: MotionScene, time: number) => string) | undefined;
|
|
125
|
+
private readonly cache;
|
|
126
|
+
private readonly pending;
|
|
127
|
+
private readonly failures;
|
|
128
|
+
private readonly descriptions;
|
|
129
|
+
private readonly listeners;
|
|
130
|
+
private readonly pool;
|
|
131
|
+
private readonly options;
|
|
132
|
+
private generation;
|
|
133
|
+
private readonly detach;
|
|
134
|
+
constructor(options?: MotionLayersEngineOptions);
|
|
135
|
+
get provider(): EffectProvider | null;
|
|
136
|
+
/** Called when a picture is ready (draw the frame again). */
|
|
137
|
+
subscribe(listener: () => void): () => void;
|
|
138
|
+
/** Why pictures failed, newest last. */
|
|
139
|
+
failuresList(): MotionLayerFailure[];
|
|
140
|
+
/** True while any picture is being made. */
|
|
141
|
+
get busy(): boolean;
|
|
142
|
+
/** Resolves once every picture asked for so far is made (or failed). */
|
|
143
|
+
idle(): Promise<void>;
|
|
144
|
+
/** Forgets every picture and failure (a new provider, or the host changed). */
|
|
145
|
+
reset(): void;
|
|
146
|
+
dispose(): void;
|
|
147
|
+
private notify;
|
|
148
|
+
private size;
|
|
149
|
+
private snap;
|
|
150
|
+
private get;
|
|
151
|
+
private request;
|
|
152
|
+
describe(id: string): Promise<EffectDescription>;
|
|
153
|
+
subject(subject: {
|
|
154
|
+
image: string;
|
|
155
|
+
}): string | undefined;
|
|
156
|
+
/** The pixels a layer's subject feeds its effect, at `size`. */
|
|
157
|
+
private subjectPixels;
|
|
158
|
+
layer(scene: MotionScene, active: MotionActiveLayer, b: MotionRect): string | undefined;
|
|
159
|
+
transition(scene: MotionScene, time: number, active: MotionActiveTransition): string | undefined;
|
|
160
|
+
private readonly fromPixels;
|
|
161
|
+
private idleExcept;
|
|
162
|
+
}
|
|
163
|
+
/** A host that draws with the browser's canvas and image decoding, or null outside a browser. */
|
|
164
|
+
export declare function browserMotionLayerHost(doc?: Document | undefined): MotionLayerHost | null;
|
|
165
|
+
/** Whether a scene's layer would draw nothing because its subject slot is empty. */
|
|
166
|
+
export declare const motionLayerSlot: (layer: MotionShotLayer) => string | undefined;
|
|
@@ -17,6 +17,8 @@ export declare function clipsShapeProblems(clips: unknown): string[];
|
|
|
17
17
|
export declare function driversShapeProblems(drivers: unknown): string[];
|
|
18
18
|
/** Problems with one shot's shape. */
|
|
19
19
|
export declare function shotShapeProblems(shot: unknown, where: string): string[];
|
|
20
|
+
/** Problems with a shot's `layers` and `transition`. */
|
|
21
|
+
export declare function shotLayersShapeProblems(shot: Record<string, unknown>, name: string): string[];
|
|
20
22
|
/** Problems with a scene's shape (empty when well formed). */
|
|
21
23
|
export declare function motionSceneShapeProblems(input: unknown): string[];
|
|
22
24
|
/** Reads a scene from JSON (a string or a parsed value). Throws `MotionSceneFormatError` listing every problem. */
|
|
@@ -17,6 +17,8 @@ export declare function clipsShapeProblems(clips: unknown): string[];
|
|
|
17
17
|
export declare function driversShapeProblems(drivers: unknown): string[];
|
|
18
18
|
/** Problems with one shot's shape. */
|
|
19
19
|
export declare function shotShapeProblems(shot: unknown, where: string): string[];
|
|
20
|
+
/** Problems with a shot's `layers` and `transition`. */
|
|
21
|
+
export declare function shotLayersShapeProblems(shot: Record<string, unknown>, name: string): string[];
|
|
20
22
|
/** Problems with a scene's shape (empty when well formed). */
|
|
21
23
|
export declare function motionSceneShapeProblems(input: unknown): string[];
|
|
22
24
|
/** Reads a scene from JSON (a string or a parsed value). Throws `MotionSceneFormatError` listing every problem. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CameraMoveSpec, EffectValue } from '../effects/types.cjs';
|
|
1
|
+
import type { CameraMoveSpec, EffectLayer, EffectShotTransition, EffectValue } from '../effects/types.cjs';
|
|
2
2
|
import type { AnimationEasing } from '../animation/easing.cjs';
|
|
3
3
|
import type { AnimationLoopMode } from '../animation/evaluate.cjs';
|
|
4
4
|
import type { VectorDocument } from '../vector/types.cjs';
|
|
@@ -153,6 +153,49 @@ export interface MotionShot {
|
|
|
153
153
|
* durations, staggers and hold all scale by 1 / speed. `fit_animation` sets it to fit a length.
|
|
154
154
|
*/
|
|
155
155
|
speed?: number;
|
|
156
|
+
/**
|
|
157
|
+
* Provider effects and pictures shown with the shot, bottom to top (see `MotionShotLayer`):
|
|
158
|
+
* `background` layers under the artwork, `subject` and `overlay` layers over it.
|
|
159
|
+
*/
|
|
160
|
+
layers?: MotionShotLayer[];
|
|
161
|
+
/**
|
|
162
|
+
* How the shot before gives way to this one: a provider transition effect blends the last
|
|
163
|
+
* frame of the shot before into this shot over `ms`. With no camera `in`, the camera cuts.
|
|
164
|
+
*/
|
|
165
|
+
transition?: MotionShotTransition;
|
|
166
|
+
}
|
|
167
|
+
/** What a shot layer shows or feeds its effect: a picture or SVG (URL, `data:` URL or markup), words, or a `slot` the host fills. */
|
|
168
|
+
export type MotionLayerSubject = {
|
|
169
|
+
image: string;
|
|
170
|
+
} | {
|
|
171
|
+
svg: string;
|
|
172
|
+
} | {
|
|
173
|
+
text: string;
|
|
174
|
+
font?: string;
|
|
175
|
+
weight?: number | string;
|
|
176
|
+
} | {
|
|
177
|
+
slot: string;
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* A layer of a shot (the shape of Flair's `SceneLayer` and the effects contract's
|
|
181
|
+
* `EffectLayer`): a provider effect (a generator, filter, overlay or title), optionally applied
|
|
182
|
+
* to a `subject`, or a bare subject. It lasts from `from` to `until` (default: from the shot's
|
|
183
|
+
* start until the next shot starts), placed at `rect` in artwork units (moving with the camera)
|
|
184
|
+
* or filling the screen.
|
|
185
|
+
*/
|
|
186
|
+
export interface MotionShotLayer extends Omit<EffectLayer, 'id' | 'subject'> {
|
|
187
|
+
/** Unique in the scene (e.g. `layer1`). */
|
|
188
|
+
id: string;
|
|
189
|
+
subject?: MotionLayerSubject;
|
|
190
|
+
/** The provider it was added with (its `id`). */
|
|
191
|
+
provider?: string;
|
|
192
|
+
/** The effect's name when it was added, shown where no provider can draw it. */
|
|
193
|
+
name?: string;
|
|
194
|
+
}
|
|
195
|
+
/** A provider transition into a shot (the effects contract's `EffectShotTransition`). */
|
|
196
|
+
export interface MotionShotTransition extends EffectShotTransition {
|
|
197
|
+
provider?: string;
|
|
198
|
+
name?: string;
|
|
156
199
|
}
|
|
157
200
|
/** How `split` splits outlined text. */
|
|
158
201
|
export type MotionTextUnit = 'letter' | 'word' | 'line';
|