@pixerate/editor 0.70.0 → 0.71.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/index.cjs +135 -43
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +39 -2
- package/dist/animation-editor/index.d.ts +39 -2
- package/dist/animation-editor/index.js +102 -10
- package/dist/animation-editor/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1100,6 +1100,17 @@ interface MotionOverlayOptions {
|
|
|
1100
1100
|
* `motionFrameToSvg`.
|
|
1101
1101
|
*/
|
|
1102
1102
|
declare function motionStageSvg(scene: MotionScene, time: number, options?: MotionSvgOptions & MotionOverlayOptions): string;
|
|
1103
|
+
interface MotionContactSheetOptions extends MotionSvgOptions, MotionOverlayOptions {
|
|
1104
|
+
/** Frames a row (default: about square). */
|
|
1105
|
+
columns?: number;
|
|
1106
|
+
/** Write each frame's time (and shot) under it (default true). */
|
|
1107
|
+
labels?: boolean;
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Several moments of the scene in one SVG, in a grid with each frame's time and shot under it:
|
|
1111
|
+
* a contact sheet, to see a whole animation (or an agent's change to it) at a glance.
|
|
1112
|
+
*/
|
|
1113
|
+
declare function motionContactSheetSvg(scene: MotionScene, times: readonly number[], options?: MotionContactSheetOptions): string;
|
|
1103
1114
|
|
|
1104
1115
|
/** Changes shorter than this (ms) are too quick to follow. */
|
|
1105
1116
|
declare const MOTION_MIN_CHANGE_MS = 120;
|
|
@@ -1195,6 +1206,32 @@ type MotionEditResult = {
|
|
|
1195
1206
|
declare function freshShotId(scene: MotionScene, base?: string): string;
|
|
1196
1207
|
/** Applies edits in order, as one change. Fails without changing anything when one fails. */
|
|
1197
1208
|
declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readonly MotionEdit[]): MotionEditResult;
|
|
1209
|
+
/** What one edit made, for later edits in a batch to refer to (`"$0.indexes[0]"`). */
|
|
1210
|
+
interface MotionEditOutcome {
|
|
1211
|
+
op: string;
|
|
1212
|
+
/** The shot it changed or added to. */
|
|
1213
|
+
shot?: string;
|
|
1214
|
+
/** Shots it added. */
|
|
1215
|
+
shots?: string[];
|
|
1216
|
+
/** Indexes of the commands it added (or where it moved one). */
|
|
1217
|
+
indexes?: number[];
|
|
1218
|
+
/** The clip it set. */
|
|
1219
|
+
clip?: string;
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Resolves references to earlier edits' outcomes in a batch: a string `"$N.path"` (`$last` for the
|
|
1223
|
+
* one before) is replaced by that value, e.g. `"$0.indexes[0]"` for the index of the first command
|
|
1224
|
+
* edit 0 added; `"$$..."` is a literal `$`. Returns the resolved edits with what each made, or why
|
|
1225
|
+
* a reference does not resolve. Nothing is applied.
|
|
1226
|
+
*/
|
|
1227
|
+
declare function resolveMotionEditRefs(scene: MotionScene, edits: readonly MotionEdit[]): {
|
|
1228
|
+
ok: true;
|
|
1229
|
+
edits: MotionEdit[];
|
|
1230
|
+
outcomes: MotionEditOutcome[];
|
|
1231
|
+
} | {
|
|
1232
|
+
ok: false;
|
|
1233
|
+
error: string;
|
|
1234
|
+
};
|
|
1198
1235
|
/** An empty scene over `artwork`. */
|
|
1199
1236
|
declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
|
|
1200
1237
|
|
|
@@ -2109,7 +2146,7 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
|
|
|
2109
2146
|
* A short authoring guide for a model writing vector animations with the animation editor's
|
|
2110
2147
|
* tools. Static, so it caches well as part of a system prompt.
|
|
2111
2148
|
*/
|
|
2112
|
-
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- Drawing a group of strokes: \"order\": \"sequence\" draws them one after another (a signature, a diagram), \"sortBy\": \"distance\" from \"origin\" reveals outward, \"pace\": \"speed\" keeps one speed; draw with \"comet\": 0.2 sends a short stroke along a path and off the end.\n- Reuse motion: set_animation_clip defines a clip (commands targeting \"$\"), and { \"type\": \"play\", \"clip\": name, \"targets\": [...] } plays it on any nodes (with stagger and speed). copy_animation gives other nodes one node's motion.\n- move takes \"via\" waypoints for a curved, smooth path that passes exactly through each point (steady speed by default); use it instead of chaining moves, which stop at each point.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
2149
|
+
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- Drawing a group of strokes: \"order\": \"sequence\" draws them one after another (a signature, a diagram), \"sortBy\": \"distance\" from \"origin\" reveals outward, \"pace\": \"speed\" keeps one speed; draw with \"comet\": 0.2 sends a short stroke along a path and off the end.\n- Reuse motion: set_animation_clip defines a clip (commands targeting \"$\"), and { \"type\": \"play\", \"clip\": name, \"targets\": [...] } plays it on any nodes (with stagger and speed). copy_animation gives other nodes one node's motion.\n- move takes \"via\" waypoints for a curved, smooth path that passes exactly through each point (steady speed by default); use it instead of chaining moves, which stop at each point.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n- In edit_animation, a later op can use what an earlier one made: \"$0.indexes[0]\" (the first command op 1 added), \"$last.shot\".\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result, or with \"times\" for a contact sheet of several moments; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
2113
2150
|
|
|
2114
2151
|
/**
|
|
2115
2152
|
* Helpers for hand-editing UIs (React's and Svelte's command inspector, ease picker, cue picker,
|
|
@@ -2256,4 +2293,4 @@ declare function parseMotionNarration(text: string): {
|
|
|
2256
2293
|
error: string;
|
|
2257
2294
|
};
|
|
2258
2295
|
|
|
2259
|
-
export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, type LottieAnimation, type LottieExport, type LottieExportOptions, type LottieKeyframe, type LottieShape, type LottieValue, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_CLIP_TARGET, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_CHOICES, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, MOTION_TRIGGERS, type MotionBeatGrid, type MotionCamera, type MotionClip, type MotionClipItem, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionDrawOrder, type MotionEasingCurve, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFieldInput, type MotionFieldKind, type MotionFieldSpec, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionGhost, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionOnionSkin, type MotionOverlayOptions, type MotionPath, type MotionPathOptions, type MotionPlayCommand, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSmoothLeg, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionTrigger, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, clipsShapeProblems, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, defaultMotionCommand, describeMotionElements, describeMotionShots, duplicateMotionCommandEdit, fitMotionRect, fitMotionScene, fitMotionSceneEdits, flairAtLeast, flairCurveFor, flairEaseFor, formatMotionNarration, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, highlightMotionSvg, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionClipLayout, motionCommandDuration, motionCommandFields, motionCommandRepeat, motionCommandRows, motionCommandSummary, motionCueChoices, motionCueFromKey, motionCueKey, motionCueTime, motionCycleDuration, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, motionFieldEdit, motionFieldLabel, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionGhosts, motionIssue, motionIssueKey, motionIssueLine, motionMovingIds, motionNodeAtElement, motionNodeClips, motionNodeOffset, motionPath, motionPathLength, motionPathsSvg, motionRestValue, motionRevealClip, motionRevealPadding, motionRulerTicks, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotCueTime, motionShotTimeScale, motionStageSvg, motionTrackKey, namedWithSuggestion, parseMotionFieldInput, parseMotionNarration, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, smoothMotionLegs, smoothMotionTimes, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, toLottie, trackValue, withMotionLayers, withViewBox };
|
|
2296
|
+
export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, type LottieAnimation, type LottieExport, type LottieExportOptions, type LottieKeyframe, type LottieShape, type LottieValue, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_CLIP_TARGET, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_CHOICES, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, MOTION_TRIGGERS, type MotionBeatGrid, type MotionCamera, type MotionClip, type MotionClipItem, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionContactSheetOptions, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionDrawOrder, type MotionEasingCurve, type MotionEdit, type MotionEditOp, type MotionEditOutcome, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFieldInput, type MotionFieldKind, type MotionFieldSpec, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionGhost, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionOnionSkin, type MotionOverlayOptions, type MotionPath, type MotionPathOptions, type MotionPlayCommand, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSmoothLeg, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionTrigger, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, clipsShapeProblems, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, defaultMotionCommand, describeMotionElements, describeMotionShots, duplicateMotionCommandEdit, fitMotionRect, fitMotionScene, fitMotionSceneEdits, flairAtLeast, flairCurveFor, flairEaseFor, formatMotionNarration, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, highlightMotionSvg, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionClipLayout, motionCommandDuration, motionCommandFields, motionCommandRepeat, motionCommandRows, motionCommandSummary, motionContactSheetSvg, motionCueChoices, motionCueFromKey, motionCueKey, motionCueTime, motionCycleDuration, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, motionFieldEdit, motionFieldLabel, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionGhosts, motionIssue, motionIssueKey, motionIssueLine, motionMovingIds, motionNodeAtElement, motionNodeClips, motionNodeOffset, motionPath, motionPathLength, motionPathsSvg, motionRestValue, motionRevealClip, motionRevealPadding, motionRulerTicks, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotCueTime, motionShotTimeScale, motionStageSvg, motionTrackKey, namedWithSuggestion, parseMotionFieldInput, parseMotionNarration, parseMotionScene, resolveMotionCamera, resolveMotionEditRefs, segmentProgress, segmentValue, shotShapeProblems, smoothMotionLegs, smoothMotionTimes, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, toLottie, trackValue, withMotionLayers, withViewBox };
|
|
@@ -1100,6 +1100,17 @@ interface MotionOverlayOptions {
|
|
|
1100
1100
|
* `motionFrameToSvg`.
|
|
1101
1101
|
*/
|
|
1102
1102
|
declare function motionStageSvg(scene: MotionScene, time: number, options?: MotionSvgOptions & MotionOverlayOptions): string;
|
|
1103
|
+
interface MotionContactSheetOptions extends MotionSvgOptions, MotionOverlayOptions {
|
|
1104
|
+
/** Frames a row (default: about square). */
|
|
1105
|
+
columns?: number;
|
|
1106
|
+
/** Write each frame's time (and shot) under it (default true). */
|
|
1107
|
+
labels?: boolean;
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Several moments of the scene in one SVG, in a grid with each frame's time and shot under it:
|
|
1111
|
+
* a contact sheet, to see a whole animation (or an agent's change to it) at a glance.
|
|
1112
|
+
*/
|
|
1113
|
+
declare function motionContactSheetSvg(scene: MotionScene, times: readonly number[], options?: MotionContactSheetOptions): string;
|
|
1103
1114
|
|
|
1104
1115
|
/** Changes shorter than this (ms) are too quick to follow. */
|
|
1105
1116
|
declare const MOTION_MIN_CHANGE_MS = 120;
|
|
@@ -1195,6 +1206,32 @@ type MotionEditResult = {
|
|
|
1195
1206
|
declare function freshShotId(scene: MotionScene, base?: string): string;
|
|
1196
1207
|
/** Applies edits in order, as one change. Fails without changing anything when one fails. */
|
|
1197
1208
|
declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readonly MotionEdit[]): MotionEditResult;
|
|
1209
|
+
/** What one edit made, for later edits in a batch to refer to (`"$0.indexes[0]"`). */
|
|
1210
|
+
interface MotionEditOutcome {
|
|
1211
|
+
op: string;
|
|
1212
|
+
/** The shot it changed or added to. */
|
|
1213
|
+
shot?: string;
|
|
1214
|
+
/** Shots it added. */
|
|
1215
|
+
shots?: string[];
|
|
1216
|
+
/** Indexes of the commands it added (or where it moved one). */
|
|
1217
|
+
indexes?: number[];
|
|
1218
|
+
/** The clip it set. */
|
|
1219
|
+
clip?: string;
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Resolves references to earlier edits' outcomes in a batch: a string `"$N.path"` (`$last` for the
|
|
1223
|
+
* one before) is replaced by that value, e.g. `"$0.indexes[0]"` for the index of the first command
|
|
1224
|
+
* edit 0 added; `"$$..."` is a literal `$`. Returns the resolved edits with what each made, or why
|
|
1225
|
+
* a reference does not resolve. Nothing is applied.
|
|
1226
|
+
*/
|
|
1227
|
+
declare function resolveMotionEditRefs(scene: MotionScene, edits: readonly MotionEdit[]): {
|
|
1228
|
+
ok: true;
|
|
1229
|
+
edits: MotionEdit[];
|
|
1230
|
+
outcomes: MotionEditOutcome[];
|
|
1231
|
+
} | {
|
|
1232
|
+
ok: false;
|
|
1233
|
+
error: string;
|
|
1234
|
+
};
|
|
1198
1235
|
/** An empty scene over `artwork`. */
|
|
1199
1236
|
declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
|
|
1200
1237
|
|
|
@@ -2109,7 +2146,7 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
|
|
|
2109
2146
|
* A short authoring guide for a model writing vector animations with the animation editor's
|
|
2110
2147
|
* tools. Static, so it caches well as part of a system prompt.
|
|
2111
2148
|
*/
|
|
2112
|
-
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- Drawing a group of strokes: \"order\": \"sequence\" draws them one after another (a signature, a diagram), \"sortBy\": \"distance\" from \"origin\" reveals outward, \"pace\": \"speed\" keeps one speed; draw with \"comet\": 0.2 sends a short stroke along a path and off the end.\n- Reuse motion: set_animation_clip defines a clip (commands targeting \"$\"), and { \"type\": \"play\", \"clip\": name, \"targets\": [...] } plays it on any nodes (with stagger and speed). copy_animation gives other nodes one node's motion.\n- move takes \"via\" waypoints for a curved, smooth path that passes exactly through each point (steady speed by default); use it instead of chaining moves, which stop at each point.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
2149
|
+
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- Drawing a group of strokes: \"order\": \"sequence\" draws them one after another (a signature, a diagram), \"sortBy\": \"distance\" from \"origin\" reveals outward, \"pace\": \"speed\" keeps one speed; draw with \"comet\": 0.2 sends a short stroke along a path and off the end.\n- Reuse motion: set_animation_clip defines a clip (commands targeting \"$\"), and { \"type\": \"play\", \"clip\": name, \"targets\": [...] } plays it on any nodes (with stagger and speed). copy_animation gives other nodes one node's motion.\n- move takes \"via\" waypoints for a curved, smooth path that passes exactly through each point (steady speed by default); use it instead of chaining moves, which stop at each point.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n- In edit_animation, a later op can use what an earlier one made: \"$0.indexes[0]\" (the first command op 1 added), \"$last.shot\".\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result, or with \"times\" for a contact sheet of several moments; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
2113
2150
|
|
|
2114
2151
|
/**
|
|
2115
2152
|
* Helpers for hand-editing UIs (React's and Svelte's command inspector, ease picker, cue picker,
|
|
@@ -2256,4 +2293,4 @@ declare function parseMotionNarration(text: string): {
|
|
|
2256
2293
|
error: string;
|
|
2257
2294
|
};
|
|
2258
2295
|
|
|
2259
|
-
export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, type LottieAnimation, type LottieExport, type LottieExportOptions, type LottieKeyframe, type LottieShape, type LottieValue, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_CLIP_TARGET, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_CHOICES, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, MOTION_TRIGGERS, type MotionBeatGrid, type MotionCamera, type MotionClip, type MotionClipItem, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionDrawOrder, type MotionEasingCurve, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFieldInput, type MotionFieldKind, type MotionFieldSpec, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionGhost, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionOnionSkin, type MotionOverlayOptions, type MotionPath, type MotionPathOptions, type MotionPlayCommand, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSmoothLeg, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionTrigger, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, clipsShapeProblems, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, defaultMotionCommand, describeMotionElements, describeMotionShots, duplicateMotionCommandEdit, fitMotionRect, fitMotionScene, fitMotionSceneEdits, flairAtLeast, flairCurveFor, flairEaseFor, formatMotionNarration, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, highlightMotionSvg, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionClipLayout, motionCommandDuration, motionCommandFields, motionCommandRepeat, motionCommandRows, motionCommandSummary, motionCueChoices, motionCueFromKey, motionCueKey, motionCueTime, motionCycleDuration, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, motionFieldEdit, motionFieldLabel, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionGhosts, motionIssue, motionIssueKey, motionIssueLine, motionMovingIds, motionNodeAtElement, motionNodeClips, motionNodeOffset, motionPath, motionPathLength, motionPathsSvg, motionRestValue, motionRevealClip, motionRevealPadding, motionRulerTicks, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotCueTime, motionShotTimeScale, motionStageSvg, motionTrackKey, namedWithSuggestion, parseMotionFieldInput, parseMotionNarration, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, smoothMotionLegs, smoothMotionTimes, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, toLottie, trackValue, withMotionLayers, withViewBox };
|
|
2296
|
+
export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, type LottieAnimation, type LottieExport, type LottieExportOptions, type LottieKeyframe, type LottieShape, type LottieValue, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_CLIP_TARGET, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_CHOICES, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, MOTION_TRIGGERS, type MotionBeatGrid, type MotionCamera, type MotionClip, type MotionClipItem, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionContactSheetOptions, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionDrawOrder, type MotionEasingCurve, type MotionEdit, type MotionEditOp, type MotionEditOutcome, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFieldInput, type MotionFieldKind, type MotionFieldSpec, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionGhost, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionOnionSkin, type MotionOverlayOptions, type MotionPath, type MotionPathOptions, type MotionPlayCommand, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSmoothLeg, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionTrigger, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, clipsShapeProblems, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, defaultMotionCommand, describeMotionElements, describeMotionShots, duplicateMotionCommandEdit, fitMotionRect, fitMotionScene, fitMotionSceneEdits, flairAtLeast, flairCurveFor, flairEaseFor, formatMotionNarration, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, highlightMotionSvg, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionClipLayout, motionCommandDuration, motionCommandFields, motionCommandRepeat, motionCommandRows, motionCommandSummary, motionContactSheetSvg, motionCueChoices, motionCueFromKey, motionCueKey, motionCueTime, motionCycleDuration, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, motionFieldEdit, motionFieldLabel, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionGhosts, motionIssue, motionIssueKey, motionIssueLine, motionMovingIds, motionNodeAtElement, motionNodeClips, motionNodeOffset, motionPath, motionPathLength, motionPathsSvg, motionRestValue, motionRevealClip, motionRevealPadding, motionRulerTicks, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotCueTime, motionShotTimeScale, motionStageSvg, motionTrackKey, namedWithSuggestion, parseMotionFieldInput, parseMotionNarration, parseMotionScene, resolveMotionCamera, resolveMotionEditRefs, segmentProgress, segmentValue, shotShapeProblems, smoothMotionLegs, smoothMotionTimes, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, toLottie, trackValue, withMotionLayers, withViewBox };
|
|
@@ -1537,6 +1537,30 @@ function motionStageSvg(scene, time, options = {}) {
|
|
|
1537
1537
|
const bg = svgOptions.background !== false && scene.artwork.background ? /^\s*<rect[^>]*\/>/.exec(body)?.[0] ?? "" : "";
|
|
1538
1538
|
return `${current.slice(0, open)}${bg}${ghosts.join("")}${body.slice(bg.length)}${paths}</svg>`;
|
|
1539
1539
|
}
|
|
1540
|
+
function motionContactSheetSvg(scene, times, options = {}) {
|
|
1541
|
+
const { columns, labels = true, ...frameOptions } = options;
|
|
1542
|
+
const n = Math.max(1, times.length);
|
|
1543
|
+
const cols = Math.max(1, Math.min(n, Math.floor(columns ?? Math.ceil(Math.sqrt(n)))));
|
|
1544
|
+
const rows = Math.ceil(n / cols);
|
|
1545
|
+
const { width: w, height: h } = scene.artwork;
|
|
1546
|
+
const gap = Math.round(Math.max(w, h) * 0.04);
|
|
1547
|
+
const label = labels ? Math.round(Math.max(12, h * 0.08)) : 0;
|
|
1548
|
+
const timeline = compileMotionScene(scene);
|
|
1549
|
+
const W = cols * w + (cols + 1) * gap;
|
|
1550
|
+
const H = rows * (h + label) + (rows + 1) * gap;
|
|
1551
|
+
const prefix = frameOptions.idPrefix ?? "vg-";
|
|
1552
|
+
const cells = times.map((t, i) => {
|
|
1553
|
+
const x = gap + i % cols * (w + gap);
|
|
1554
|
+
const y = gap + Math.floor(i / cols) * (h + label + gap);
|
|
1555
|
+
const frame = motionStageSvg(scene, t, { ...frameOptions, idPrefix: `${prefix}f${i}-` });
|
|
1556
|
+
const view = /viewBox="([^"]*)"/.exec(frame)?.[1] ?? `0 0 ${w} ${h}`;
|
|
1557
|
+
const inner = innerSvg(frame).replace(new RegExp(` id="(?!${`${prefix}f${i}-`.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})[^"]*"`, "g"), "");
|
|
1558
|
+
const shot = timeline.shots.find((s) => t >= s.start && t < s.end) ?? timeline.shots[timeline.shots.length - 1];
|
|
1559
|
+
const caption = labels ? `<text x="${x + w / 2}" y="${y + h + label * 0.8}" font-family="system-ui, sans-serif" font-size="${Math.round(label * 0.7)}" text-anchor="middle" fill="#64748b">${(t / 1e3).toFixed(2)} s${shot ? ` \xB7 ${shot.id.replace(/[<&]/g, "")}` : ""}</text>` : "";
|
|
1560
|
+
return `<svg x="${x}" y="${y}" width="${w}" height="${h}" viewBox="${view}" overflow="hidden">${inner}</svg><rect x="${x}" y="${y}" width="${w}" height="${h}" fill="none" stroke="#cbd5e1"/>${caption}`;
|
|
1561
|
+
});
|
|
1562
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}"><rect width="${W}" height="${H}" fill="#f8fafc"/>${cells.join("")}</svg>`;
|
|
1563
|
+
}
|
|
1540
1564
|
|
|
1541
1565
|
// src/animation-editor/check.ts
|
|
1542
1566
|
var MOTION_MIN_CHANGE_MS = 120;
|
|
@@ -1990,6 +2014,56 @@ function applyMotionEdits(scene, edits) {
|
|
|
1990
2014
|
if (added.length) return { ok: false, error: `Nothing was changed: ${added.map(motionIssueLine).join(" ")}` };
|
|
1991
2015
|
return { ok: true, scene: next, issues, hints: editHints(before, issues) };
|
|
1992
2016
|
}
|
|
2017
|
+
var REF = /^\$(\d+|last)((?:\.[A-Za-z_]\w*|\[\d+\])+)$/;
|
|
2018
|
+
function resolveMotionEditRefs(scene, edits) {
|
|
2019
|
+
const outcomes = [];
|
|
2020
|
+
const resolved = [];
|
|
2021
|
+
let next = scene;
|
|
2022
|
+
for (let i = 0; i < edits.length; i++) {
|
|
2023
|
+
const where = `op ${i + 1} (${edits[i]?.op})`;
|
|
2024
|
+
let problem = null;
|
|
2025
|
+
const walk = (v) => {
|
|
2026
|
+
if (typeof v === "string") {
|
|
2027
|
+
if (v.startsWith("$$")) return v.slice(1);
|
|
2028
|
+
const m = REF.exec(v);
|
|
2029
|
+
if (!m) return v;
|
|
2030
|
+
const n = m[1] === "last" ? i - 1 : Number(m[1]);
|
|
2031
|
+
if (!(n >= 0 && n < i)) {
|
|
2032
|
+
problem = `${where}: "${v}" refers to op ${n + 1}, but only ops before this one (1 to ${i}) can be referred to.`;
|
|
2033
|
+
return v;
|
|
2034
|
+
}
|
|
2035
|
+
let value = outcomes[n];
|
|
2036
|
+
for (const part of m[2].match(/\.[A-Za-z_]\w*|\[\d+\]/g) ?? []) value = value == null ? void 0 : value[part.startsWith(".") ? part.slice(1) : part.slice(1, -1)];
|
|
2037
|
+
if (value === void 0) problem = `${where}: "${v}" has no value; op ${n + 1} made ${JSON.stringify(outcomes[n])}.`;
|
|
2038
|
+
return value;
|
|
2039
|
+
}
|
|
2040
|
+
if (Array.isArray(v)) return v.map(walk);
|
|
2041
|
+
if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x)]));
|
|
2042
|
+
return v;
|
|
2043
|
+
};
|
|
2044
|
+
const edit = walk(edits[i]);
|
|
2045
|
+
if (problem) return { ok: false, error: `${problem} Nothing was changed.` };
|
|
2046
|
+
const before = next;
|
|
2047
|
+
try {
|
|
2048
|
+
next = applyOne(next, edit);
|
|
2049
|
+
} catch (error) {
|
|
2050
|
+
if (error instanceof EditError) return { ok: false, error: `${where}: ${error.message} Nothing was changed.` };
|
|
2051
|
+
throw error;
|
|
2052
|
+
}
|
|
2053
|
+
resolved.push(edit);
|
|
2054
|
+
const out = { op: edit.op };
|
|
2055
|
+
if (edit.op === "insert_shots") out.shots = edit.shots.map((s) => s.id);
|
|
2056
|
+
if ("shot" in edit && typeof edit.shot === "string") out.shot = edit.op === "update_shot" && edit.set?.id ? edit.set.id : edit.shot;
|
|
2057
|
+
if (edit.op === "add_commands") {
|
|
2058
|
+
const at = edit.at ?? before.shots.find((s) => s.id === edit.shot)?.run.length ?? 0;
|
|
2059
|
+
out.indexes = edit.commands.map((_, k) => at + k);
|
|
2060
|
+
}
|
|
2061
|
+
if (edit.op === "move_command") out.indexes = [edit.to];
|
|
2062
|
+
if (edit.op === "set_clip") out.clip = edit.name;
|
|
2063
|
+
outcomes.push(out);
|
|
2064
|
+
}
|
|
2065
|
+
return { ok: true, edits: resolved, outcomes };
|
|
2066
|
+
}
|
|
1993
2067
|
function createMotionScene(artwork, init = {}) {
|
|
1994
2068
|
return { version: 1, name: init.name ?? "animation", ...init, artwork, shots: init.shots ?? [] };
|
|
1995
2069
|
}
|
|
@@ -3302,9 +3376,9 @@ var EDIT_OP = {
|
|
|
3302
3376
|
object({ op: { const: "delete_shots", description: "Like delete_shots." }, shots: { type: "array", items: SHOT_ID, minItems: 1, description: "Shot ids." } }, ["op", "shots"]),
|
|
3303
3377
|
object({ op: { const: "move_shot", description: "Like move_shot." }, shot: SHOT_ID, to: { type: "integer", minimum: 0, description: "New position (0 = first)." } }, ["op", "shot", "to"]),
|
|
3304
3378
|
object({ op: { const: "add_commands", description: "Like add_commands." }, shot: SHOT_ID, commands: { type: "array", items: MOTION_COMMAND_SCHEMA, minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the shot's run (default: the end)." } }, ["op", "shot", "commands"]),
|
|
3305
|
-
object({ op: { const: "update_command", description: "Like update_command." }, shot: SHOT_ID, command: { type: "integer", minimum: 0, description:
|
|
3306
|
-
object({ op: { const: "move_command", description: "Like move_command." }, shot: SHOT_ID, command: { type: "integer", minimum: 0, description:
|
|
3307
|
-
object({ op: { const: "delete_commands", description: "Like delete_commands." }, shot: SHOT_ID, commands: { type: "array", items: { type: "integer", minimum: 0 }, minItems: 1, description: "Indexes in the shot's run." } }, ["op", "shot", "commands"]),
|
|
3379
|
+
object({ op: { const: "update_command", description: "Like update_command." }, shot: SHOT_ID, command: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `Index in the shot's run, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, set: { type: "object", description: "Command fields to replace." }, remove: { type: "array", items: { type: "string" }, description: "Command fields to clear." } }, ["op", "shot", "command"]),
|
|
3380
|
+
object({ op: { const: "move_command", description: "Like move_command." }, shot: SHOT_ID, command: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `Index in the shot's run, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, to: { type: "integer", minimum: 0, description: "New index in the run (0 = first)." } }, ["op", "shot", "command", "to"]),
|
|
3381
|
+
object({ op: { const: "delete_commands", description: "Like delete_commands." }, shot: SHOT_ID, commands: { type: "array", items: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `An index, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, minItems: 1, description: "Indexes in the shot's run." } }, ["op", "shot", "commands"]),
|
|
3308
3382
|
object({ op: { const: "set_controls", description: "Like set_controls." }, controls: { type: "array", items: CONTROL, description: "Controls (empty clears)." }, presets: { type: "array", items: PRESET, description: "Presets (empty clears)." } }, ["op", "controls"])
|
|
3309
3383
|
]
|
|
3310
3384
|
};
|
|
@@ -3448,7 +3522,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3448
3522
|
const renderFrame = {
|
|
3449
3523
|
name: "render_animation_frame",
|
|
3450
3524
|
title: "Render a frame",
|
|
3451
|
-
description: 'Draws the animation at one moment without changing it, to check it: standalone SVG by default, or a PNG image (format "png") when the host can rasterize. Give a time in ms, or a shot and where in it.',
|
|
3525
|
+
description: 'Draws the animation at one moment (or, with times, several moments as one labelled contact sheet) without changing it, to check it: standalone SVG by default, or a PNG image (format "png") when the host can rasterize. Give a time in ms, or a shot and where in it.',
|
|
3452
3526
|
inputSchema: object({
|
|
3453
3527
|
time: MS("Time from the start"),
|
|
3454
3528
|
shot: { ...SHOT_ID, description: 'Render a moment of this shot instead of "time".' },
|
|
@@ -3463,10 +3537,12 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3463
3537
|
[],
|
|
3464
3538
|
"Draw faded frames either side of the moment, to see motion in one picture."
|
|
3465
3539
|
),
|
|
3540
|
+
times: { type: "array", items: { type: "number", minimum: 0 }, minItems: 2, maxItems: 16, description: "Several moments (ms) to draw as one contact sheet, each labelled with its time and shot, instead of one frame. Overrides time and shot." },
|
|
3541
|
+
columns: { type: "integer", minimum: 1, maximum: 8, description: "With times: frames a row (default about square)." },
|
|
3466
3542
|
motion_paths: { anyOf: [{ type: "boolean" }, { type: "array", items: { type: "string", minLength: 1 } }], description: "Draw where nodes travel (dashed, with a dot where each change starts or ends): true for every node whose place changes, or a list of ids." }
|
|
3467
3543
|
}),
|
|
3468
3544
|
annotations: { title: "Render a frame", ...READ },
|
|
3469
|
-
handler: async ({ time, shot, at = "end", format = "svg", onion_skin, motion_paths }) => {
|
|
3545
|
+
handler: async ({ time, shot, at = "end", format = "svg", onion_skin, motion_paths, times, columns }) => {
|
|
3470
3546
|
const s = scene();
|
|
3471
3547
|
let t = time ?? controller.getState().time;
|
|
3472
3548
|
if (shot !== void 0) {
|
|
@@ -3478,7 +3554,18 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3478
3554
|
const known = new Set(describeMotionElements(s).map((e) => e.id));
|
|
3479
3555
|
for (const id of motion_paths) if (!known.has(id)) throw new Error(`There is no element ${namedWithSuggestion(id, known)} to draw a motion path for.`);
|
|
3480
3556
|
}
|
|
3481
|
-
const
|
|
3557
|
+
const overlays = { ...onion_skin ? { onionSkin: onion_skin } : {}, ...motion_paths ? { motionPaths: motion_paths } : {} };
|
|
3558
|
+
if (times) {
|
|
3559
|
+
const sheet = motionContactSheetSvg(s, times, { pretty: false, ...overlays, ...columns ? { columns } : {} });
|
|
3560
|
+
if (format === "png") {
|
|
3561
|
+
if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_animation_frame with format "svg".');
|
|
3562
|
+
const size = /width="(\d+)" height="(\d+)"/.exec(sheet);
|
|
3563
|
+
const image = await options.rasterize(sheet, { width: Number(size[1]), height: Number(size[2]) });
|
|
3564
|
+
return { content: [{ type: "image", data: image.data, mimeType: image.mimeType }] };
|
|
3565
|
+
}
|
|
3566
|
+
return { times, svg: sheet };
|
|
3567
|
+
}
|
|
3568
|
+
const svg = controller.toSvg(t, { pretty: false, ...overlays });
|
|
3482
3569
|
if (format === "png") {
|
|
3483
3570
|
if (!options.rasterize) throw new Error('This host cannot make PNG images; call render_animation_frame with format "svg".');
|
|
3484
3571
|
const image = await options.rasterize(svg, { width: s.artwork.width, height: s.artwork.height });
|
|
@@ -3822,12 +3909,14 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3822
3909
|
const editAnimation = {
|
|
3823
3910
|
name: "edit_animation",
|
|
3824
3911
|
title: "Make several edits at once",
|
|
3825
|
-
description:
|
|
3912
|
+
description: `Applies several edits in order as one undo step, all or nothing: if one fails, nothing changes and the error names the op ("op 2 (add_commands): \u2026"). A later op can use what an earlier one made: "$0.indexes[0]" is the index of the first command op 1 added, "$last.shot" the shot the op before changed. Returns each op's outcome (shot, shots, indexes, clip), the timing and issues. With dry_run it only reports them.`,
|
|
3826
3913
|
inputSchema: object({ ops: { type: "array", items: EDIT_OP, minItems: 1, description: "Edits, applied in order." }, dry_run: { type: "boolean", description: "Check without applying (default false)." } }, ["ops"]),
|
|
3827
3914
|
annotations: { title: "Make several edits at once", ...WRITE },
|
|
3828
3915
|
handler: ({ ops, dry_run = false }) => {
|
|
3829
|
-
const
|
|
3830
|
-
|
|
3916
|
+
const refs = resolveMotionEditRefs(controller.getScene(), ops);
|
|
3917
|
+
if (!refs.ok) throw new Error(refs.error);
|
|
3918
|
+
const result = controller.apply(refs.edits, "Edit animation", { dryRun: dry_run });
|
|
3919
|
+
return outcome(result, { outcomes: refs.outcomes, ...dry_run ? { dry_run: true, hint: "Nothing was applied; call again without dry_run to apply." } : {} });
|
|
3831
3920
|
}
|
|
3832
3921
|
};
|
|
3833
3922
|
const writeAnimation = {
|
|
@@ -3934,7 +4023,8 @@ Commands
|
|
|
3934
4023
|
Working method
|
|
3935
4024
|
1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).
|
|
3936
4025
|
2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).
|
|
3937
|
-
|
|
4026
|
+
- In edit_animation, a later op can use what an earlier one made: "$0.indexes[0]" (the first command op 1 added), "$last.shot".
|
|
4027
|
+
3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result, or with "times" for a contact sheet of several moments; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.
|
|
3938
4028
|
- For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.
|
|
3939
4029
|
4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.
|
|
3940
4030
|
|
|
@@ -4287,6 +4377,7 @@ export {
|
|
|
4287
4377
|
motionCommandRepeat,
|
|
4288
4378
|
motionCommandRows,
|
|
4289
4379
|
motionCommandSummary,
|
|
4380
|
+
motionContactSheetSvg,
|
|
4290
4381
|
motionCueChoices,
|
|
4291
4382
|
motionCueFromKey,
|
|
4292
4383
|
motionCueKey,
|
|
@@ -4329,6 +4420,7 @@ export {
|
|
|
4329
4420
|
parseMotionNarration,
|
|
4330
4421
|
parseMotionScene,
|
|
4331
4422
|
resolveMotionCamera,
|
|
4423
|
+
resolveMotionEditRefs,
|
|
4332
4424
|
segmentProgress,
|
|
4333
4425
|
segmentValue,
|
|
4334
4426
|
shotShapeProblems,
|