@pixerate/editor 0.229.0 → 0.230.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/camera-tools.d.cts +10 -0
- package/dist/animation-editor/camera-tools.d.ts +10 -0
- package/dist/animation-editor/camera.d.cts +67 -0
- package/dist/animation-editor/camera.d.ts +67 -0
- package/dist/animation-editor/compile.d.cts +4 -0
- package/dist/animation-editor/compile.d.ts +4 -0
- package/dist/animation-editor/controller.d.cts +34 -2
- package/dist/animation-editor/controller.d.ts +34 -2
- package/dist/animation-editor/effect-tools.d.cts +2 -1
- package/dist/animation-editor/effect-tools.d.ts +2 -1
- package/dist/animation-editor/evaluate.d.cts +9 -0
- package/dist/animation-editor/evaluate.d.ts +9 -0
- package/dist/animation-editor/flair.d.cts +8 -0
- package/dist/animation-editor/flair.d.ts +8 -0
- package/dist/animation-editor/index.cjs +603 -217
- package/dist/animation-editor/index.d.cts +2 -0
- package/dist/animation-editor/index.d.ts +2 -0
- package/dist/animation-editor/index.js +454 -68
- package/dist/animation-editor/issues.d.cts +16 -0
- package/dist/animation-editor/issues.d.ts +16 -0
- package/dist/animation-editor/tools.d.cts +1 -1
- package/dist/animation-editor/tools.d.ts +1 -1
- package/dist/animation-editor/types.d.cts +21 -3
- package/dist/animation-editor/types.d.ts +21 -3
- package/dist/canvas/index.cjs +7 -7
- package/dist/canvas/index.js +1 -1
- package/dist/{chunk-IGPEBXUD.cjs → chunk-A57ZQDNN.cjs} +7 -7
- package/dist/{chunk-K5GXW5TR.cjs → chunk-C73U5UI3.cjs} +14 -14
- package/dist/{chunk-EBDZWIOP.cjs → chunk-ERJA5CGT.cjs} +5 -1
- package/dist/{chunk-LPTFDCJO.js → chunk-ONNNNGNS.js} +1 -1
- package/dist/{chunk-5MQOBTNP.cjs → chunk-OPSK22DL.cjs} +80 -9
- package/dist/{chunk-PB6JV62G.js → chunk-SBPGIZQN.js} +1 -1
- package/dist/{chunk-UGYUGZE2.js → chunk-TCZ2J7PR.js} +71 -0
- package/dist/{chunk-W4KFNAWC.js → chunk-TYCJGFCF.js} +5 -1
- package/dist/effects/helpers.d.cts +35 -1
- package/dist/effects/helpers.d.ts +35 -1
- package/dist/effects/index.cjs +60 -44
- package/dist/effects/index.js +18 -2
- package/dist/effects/types.d.cts +15 -0
- package/dist/effects/types.d.ts +15 -0
- package/dist/image-editor/index.cjs +13 -13
- package/dist/image-editor/index.js +1 -1
- package/dist/paint-editor/index.cjs +7 -7
- package/dist/paint-editor/index.js +2 -2
- package/dist/vector/index.cjs +6 -6
- package/dist/vector/index.js +1 -1
- package/dist/video-editor/index.cjs +318 -318
- package/dist/video-editor/index.js +4 -4
- package/package.json +1 -1
- package/skills/pixerate-animation-editor/SKILL.md +28 -1
- package/skills/pixerate-animation-motion-graphics/SKILL.md +3 -0
- package/skills/pixerate-video-editor/SKILL.md +16 -1
- package/skills/pixerate-video-montage/SKILL.md +2 -1
|
@@ -8,7 +8,7 @@ var _chunkGXLZZVR5cjs = require('../chunk-GXLZZVR5.cjs');
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var
|
|
11
|
+
var _chunkERJA5CGTcjs = require('../chunk-ERJA5CGT.cjs');
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
@@ -48,7 +48,13 @@ require('../chunk-NM3G4VQT.cjs');
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
var _chunkOPSK22DLcjs = require('../chunk-OPSK22DL.cjs');
|
|
52
58
|
require('../chunk-WOFXZ3XU.cjs');
|
|
53
59
|
require('../chunk-PQ3H2AAN.cjs');
|
|
54
60
|
require('../chunk-YQGCPL5X.cjs');
|
|
@@ -98,6 +104,7 @@ require('../chunk-IPJ3TEYR.cjs');
|
|
|
98
104
|
|
|
99
105
|
// src/animation-editor/types.ts
|
|
100
106
|
var MOTION_TRIGGERS = ["click", "hover", "press", "scroll"];
|
|
107
|
+
var motionCameraFramed = (camera) => typeof camera.frame === "string" || typeof camera.x === "number";
|
|
101
108
|
var MOTION_TEXT_UNITS = ["letter", "word", "line"];
|
|
102
109
|
var MOTION_CASCADES = ["forward", "backward", "center", "edges", "random"];
|
|
103
110
|
var MOTION_DRIVEN_PROPERTIES = ["x", "y", "rotation", "scaleX", "scaleY", "opacity"];
|
|
@@ -190,7 +197,8 @@ ${problems.map((p) => `- ${p}`).join("\n")}`);
|
|
|
190
197
|
};
|
|
191
198
|
var SCENE_KEYS = ["version", "name", "description", "artwork", "shots", "clips", "drivers", "motionBlur", "loop", "trigger", "fps", "steps", "beat", "narration", "target", "controls", "presets"];
|
|
192
199
|
var SHOT_KEYS = ["id", "label", "camera", "at", "run", "hold", "speed"];
|
|
193
|
-
var CAMERA_KEYS = ["x", "y", "width", "height", "frame", "padding", "ease", "ms", "geometric"];
|
|
200
|
+
var CAMERA_KEYS = ["x", "y", "width", "height", "frame", "padding", "ease", "ms", "geometric", "in", "during"];
|
|
201
|
+
var CAMERA_MOVE_KEYS = ["move", "ms", "preset", "values"];
|
|
194
202
|
var BASE_KEYS = ["type", "targets", "duration", "delay", "stagger", "with", "ease", "note", "repeat", "repeatMode", "steps", "split", "cascade", "source"];
|
|
195
203
|
var DRAW_ORDER_KEYS = ["order", "pace", "align", "sortBy", "origin"];
|
|
196
204
|
var COMMAND_KEYS = {
|
|
@@ -220,14 +228,14 @@ var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
|
220
228
|
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
221
229
|
var isPoint = (v) => isObject(v) && isNum(v.x) && isNum(v.y);
|
|
222
230
|
function unknownKeys(value, known, where, problems) {
|
|
223
|
-
for (const key of Object.keys(value)) if (!known.includes(key)) problems.push(`${where}: unknown field ${
|
|
231
|
+
for (const key of Object.keys(value)) if (!known.includes(key)) problems.push(`${where}: unknown field ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, key, known)}.`);
|
|
224
232
|
}
|
|
225
233
|
function commandShapeProblems(command3, where) {
|
|
226
234
|
const problems = [];
|
|
227
235
|
if (!isObject(command3)) return [`${where} must be an object.`];
|
|
228
236
|
const type = command3.type;
|
|
229
237
|
if (typeof type !== "string" || !MOTION_COMMAND_TYPES.includes(type)) {
|
|
230
|
-
return [`${where}: unknown type ${typeof type === "string" ?
|
|
238
|
+
return [`${where}: unknown type ${typeof type === "string" ? _chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, type, MOTION_COMMAND_TYPES) : String(type)}; use one of ${MOTION_COMMAND_TYPES.join(", ")}.`];
|
|
231
239
|
}
|
|
232
240
|
unknownKeys(command3, COMMAND_KEYS[type], `${where} (${type})`, problems);
|
|
233
241
|
const p = (msg) => problems.push(`${where} (${type}): ${msg}`);
|
|
@@ -279,7 +287,7 @@ function commandShapeProblems(command3, where) {
|
|
|
279
287
|
case "exit": {
|
|
280
288
|
const styles = type === "enter" ? MOTION_ENTER_STYLES : MOTION_EXIT_STYLES;
|
|
281
289
|
if (command3.style !== void 0 && !(typeof command3.style === "string" && styles.includes(command3.style)))
|
|
282
|
-
p(`"style" must be one of ${styles.join(", ")}${typeof command3.style === "string" ? ` (got ${
|
|
290
|
+
p(`"style" must be one of ${styles.join(", ")}${typeof command3.style === "string" ? ` (got ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, command3.style, styles)})` : ""}.`);
|
|
283
291
|
if (command3.direction !== void 0 && !MOTION_DIRECTIONS.includes(command3.direction)) p(`"direction" must be one of ${MOTION_DIRECTIONS.join(", ")}.`);
|
|
284
292
|
optionalNumber("distance");
|
|
285
293
|
if (command3.scale !== void 0 && !(isNum(command3.scale) && command3.scale >= 0)) p(`"scale" must be a number \u2265 0 (the starting scale for pop and zoom).`);
|
|
@@ -432,7 +440,25 @@ function shotShapeProblems(shot, where) {
|
|
|
432
440
|
const isRect = ["x", "y", "width", "height"].every((k) => isNum(c[k]));
|
|
433
441
|
if (typeof c.frame === "string") {
|
|
434
442
|
if (c.padding !== void 0 && !isNum(c.padding)) problems.push(`${name} camera: "padding" must be a number.`);
|
|
435
|
-
} else if (!isRect
|
|
443
|
+
} else if (!isRect && (c.in === void 0 && c.during === void 0 || ["x", "y", "width", "height", "padding"].some((k) => c[k] !== void 0)))
|
|
444
|
+
problems.push(`${name} camera: give { x, y, width, height } or { frame: "<node id>" }, or only a move ("in" or "during") to keep the framing.`);
|
|
445
|
+
for (const field of ["in", "during"]) {
|
|
446
|
+
const m = c[field];
|
|
447
|
+
if (m === void 0) continue;
|
|
448
|
+
if (typeof m === "string") {
|
|
449
|
+
if (!m) problems.push(`${name} camera: "${field}" must name a camera move.`);
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (!isObject(m) || typeof m.move !== "string" || !m.move) {
|
|
453
|
+
problems.push(`${name} camera: "${field}" is a camera move's id, or { "move": id, "ms"?, "preset"?, "values"? }.`);
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
unknownKeys(m, CAMERA_MOVE_KEYS, `${name} camera ${field}`, problems);
|
|
457
|
+
if (m.ms !== void 0 && (field === "during" || !(isNum(m.ms) && m.ms >= 0)))
|
|
458
|
+
problems.push(field === "during" ? `${name} camera: a move while the shot holds plays across the shot's "hold"; set the hold instead of "during.ms".` : `${name} camera: "in.ms" must be a number \u2265 0.`);
|
|
459
|
+
if (m.preset !== void 0 && typeof m.preset !== "string") problems.push(`${name} camera: "${field}.preset" is a preset's name.`);
|
|
460
|
+
if (m.values !== void 0 && !isObject(m.values)) problems.push(`${name} camera: "${field}.values" is an object of the move's control values.`);
|
|
461
|
+
}
|
|
436
462
|
if (c.ease !== void 0 && !_chunkDWJJI6RTcjs.isAnimationEasing.call(void 0, c.ease)) problems.push(`${name} camera: "ease" is not an easing.`);
|
|
437
463
|
if (c.ms !== void 0 && !(isNum(c.ms) && c.ms >= 0)) problems.push(`${name} camera: "ms" must be a number \u2265 0.`);
|
|
438
464
|
if (c.geometric !== void 0 && typeof c.geometric !== "boolean") problems.push(`${name} camera: "geometric" must be true or false.`);
|
|
@@ -1027,12 +1053,17 @@ function compileMotionScene(scene) {
|
|
|
1027
1053
|
const start = t;
|
|
1028
1054
|
let cursor = start;
|
|
1029
1055
|
const f = motionShotTimeScale(shot);
|
|
1056
|
+
const moveIn = shot.camera ? _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, shot.camera.in) : void 0;
|
|
1057
|
+
const moveDuring = shot.camera ? _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, shot.camera.during) : void 0;
|
|
1058
|
+
let playsIn = false;
|
|
1030
1059
|
if (shot.camera) {
|
|
1031
|
-
const
|
|
1032
|
-
|
|
1033
|
-
|
|
1060
|
+
const framed = motionCameraFramed(shot.camera);
|
|
1061
|
+
const rect = framed ? resolveMotionCamera(shot.camera, scene) : null;
|
|
1062
|
+
if (rect && rect.width > 0 && rect.height > 0 || !framed && moveIn) {
|
|
1063
|
+
const ms2 = index === 0 ? 0 : (_nullishCoalesce(_nullishCoalesce(_optionalChain([moveIn, 'optionalAccess', _37 => _37.ms]), () => ( shot.camera.ms)), () => ( MOTION_CAMERA_MS))) * f;
|
|
1034
1064
|
cameraMoves.push({ shot: shot.id, start, end: start + ms2, to: rect, ease: _nullishCoalesce(shot.camera.ease, () => ( MOTION_EASE_IN_OUT)), geometric: shot.camera.geometric === true });
|
|
1035
1065
|
cursor = start + ms2;
|
|
1066
|
+
playsIn = !!moveIn && index > 0;
|
|
1036
1067
|
}
|
|
1037
1068
|
}
|
|
1038
1069
|
const commandsStart = cursor;
|
|
@@ -1042,16 +1073,28 @@ function compileMotionScene(scene) {
|
|
|
1042
1073
|
const base = command3.with === "previous" && i > 0 ? prevStart : runEnd;
|
|
1043
1074
|
const begin = base + (command3.type === "wait" ? 0 : (_nullishCoalesce(command3.delay, () => ( 0))) * f);
|
|
1044
1075
|
const split = command3.type === "wait" ? null : motionCommandSlots(nodes, command3);
|
|
1045
|
-
const slots = _nullishCoalesce(_optionalChain([split, 'optionalAccess',
|
|
1076
|
+
const slots = _nullishCoalesce(_optionalChain([split, 'optionalAccess', _38 => _38.slots]), () => ( []));
|
|
1046
1077
|
const durations = command3.type === "wait" ? [command3.duration * f] : slots.map((s) => motionCommandDuration(command3, scene, s.id) * f);
|
|
1047
|
-
const stagger = (_nullishCoalesce(_optionalChain([split, 'optionalAccess',
|
|
1048
|
-
const end2 = durations.reduce((m, d, k) => Math.max(m, begin + (_nullishCoalesce(_optionalChain([slots, 'access',
|
|
1078
|
+
const stagger = (_nullishCoalesce(_optionalChain([split, 'optionalAccess', _39 => _39.stagger]), () => ( 0))) * f;
|
|
1079
|
+
const end2 = durations.reduce((m, d, k) => Math.max(m, begin + (_nullishCoalesce(_optionalChain([slots, 'access', _40 => _40[k], 'optionalAccess', _41 => _41.slot]), () => ( k))) * stagger + d), begin);
|
|
1049
1080
|
commands.push({ shot: shot.id, shotIndex: index, command: i, type: command3.type, start: begin, end: end2, duration: _nullishCoalesce(durations[0], () => ( 0)) });
|
|
1050
1081
|
prevStart = begin;
|
|
1051
1082
|
runEnd = Math.max(runEnd, end2);
|
|
1052
1083
|
});
|
|
1053
1084
|
const end = runEnd + (_nullishCoalesce(shot.hold, () => ( MOTION_DEFAULT_HOLD))) * f;
|
|
1054
|
-
shots.push({
|
|
1085
|
+
shots.push({
|
|
1086
|
+
id: shot.id,
|
|
1087
|
+
index,
|
|
1088
|
+
...shot.label ? { label: shot.label } : {},
|
|
1089
|
+
start,
|
|
1090
|
+
commandsStart,
|
|
1091
|
+
commandsEnd: runEnd,
|
|
1092
|
+
end,
|
|
1093
|
+
...cue !== void 0 ? { cue } : {},
|
|
1094
|
+
...missedBy !== void 0 ? { missedBy } : {},
|
|
1095
|
+
...playsIn ? { cameraIn: moveIn.move } : {},
|
|
1096
|
+
...moveDuring ? { cameraDuring: moveDuring.move } : {}
|
|
1097
|
+
});
|
|
1055
1098
|
t = end;
|
|
1056
1099
|
});
|
|
1057
1100
|
const tracks = /* @__PURE__ */ new Map();
|
|
@@ -1073,7 +1116,11 @@ function compileMotionScene(scene) {
|
|
|
1073
1116
|
jobs.push({
|
|
1074
1117
|
start: move.start,
|
|
1075
1118
|
order: order++,
|
|
1076
|
-
run: () =>
|
|
1119
|
+
run: () => {
|
|
1120
|
+
const from = valueAt("", "camera", move.start);
|
|
1121
|
+
const to = move.to ? [move.to.x, move.to.y, move.to.width, move.to.height] : from;
|
|
1122
|
+
push({ node: "", property: "camera", start: move.start, end: move.end, from, to, ease: move.ease, shot: move.shot, command: -1, ...move.geometric ? { geometric: true } : {} });
|
|
1123
|
+
}
|
|
1077
1124
|
});
|
|
1078
1125
|
}
|
|
1079
1126
|
for (const timing of commands) {
|
|
@@ -1149,11 +1196,11 @@ function compileMotionScene(scene) {
|
|
|
1149
1196
|
const at = nodes.get(p.id);
|
|
1150
1197
|
let first = { x: 0, y: 0 };
|
|
1151
1198
|
try {
|
|
1152
|
-
const m = _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess',
|
|
1199
|
+
const m = _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _42 => _42.parentWorld]), () => ( _chunkBQE3Y6ZOcjs.IDENTITY_MATRIX)), { effects: false })[0];
|
|
1153
1200
|
if (m && m.type === "M") first = { x: m.x, y: m.y };
|
|
1154
1201
|
} catch (e3) {
|
|
1155
1202
|
}
|
|
1156
|
-
return { id: p.id, len: Math.max(1e-6, motionPathLength(p, _optionalChain([at, 'optionalAccess',
|
|
1203
|
+
return { id: p.id, len: Math.max(1e-6, motionPathLength(p, _optionalChain([at, 'optionalAccess', _43 => _43.parentWorld]))), first };
|
|
1157
1204
|
});
|
|
1158
1205
|
if (!list.length) return null;
|
|
1159
1206
|
const span = Math.max(0, e - s);
|
|
@@ -1182,7 +1229,7 @@ function compileMotionScene(scene) {
|
|
|
1182
1229
|
const style = _nullishCoalesce(command3.style, () => ( "fade"));
|
|
1183
1230
|
const opacity = rest("opacity");
|
|
1184
1231
|
const reveal = style === "wipe" ? motionRevealClip(entry, { style, direction: command3.direction }) : style === "iris" ? motionRevealClip(entry, { style, shape: command3.shape }) : style === "split" ? motionRevealClip(entry, { style, orientation: command3.orientation }) : null;
|
|
1185
|
-
for (const p of ["clipRect", "clipCircle"]) if (p !== _optionalChain([reveal, 'optionalAccess',
|
|
1232
|
+
for (const p of ["clipRect", "clipCircle"]) if (p !== _optionalChain([reveal, 'optionalAccess', _44 => _44.property]) && tracks.has(motionTrackKey(node, p))) seg(p, rest(p), "linear", start, start);
|
|
1186
1233
|
if (reveal) {
|
|
1187
1234
|
seg("opacity", opacity, "linear", start, start);
|
|
1188
1235
|
seg(reveal.property, reveal.to, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: reveal.from });
|
|
@@ -1258,21 +1305,21 @@ function compileMotionScene(scene) {
|
|
|
1258
1305
|
}
|
|
1259
1306
|
case "move": {
|
|
1260
1307
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
1261
|
-
let dx = _nullishCoalesce(_optionalChain([command3, 'access',
|
|
1262
|
-
let dy = _nullishCoalesce(_optionalChain([command3, 'access',
|
|
1308
|
+
let dx = _nullishCoalesce(_optionalChain([command3, 'access', _45 => _45.by, 'optionalAccess', _46 => _46.x]), () => ( 0));
|
|
1309
|
+
let dy = _nullishCoalesce(_optionalChain([command3, 'access', _47 => _47.by, 'optionalAccess', _48 => _48.y]), () => ( 0));
|
|
1263
1310
|
if (command3.to) {
|
|
1264
1311
|
const inv = _chunkBQE3Y6ZOcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
1265
1312
|
const target = _chunkBQE3Y6ZOcjs.applyMatrix.call(void 0, inv, command3.to);
|
|
1266
1313
|
dx = target.x - (entry.center.x + num2("x"));
|
|
1267
1314
|
dy = target.y - (entry.center.y + num2("y"));
|
|
1268
1315
|
}
|
|
1269
|
-
if (_optionalChain([command3, 'access',
|
|
1316
|
+
if (_optionalChain([command3, 'access', _49 => _49.via, 'optionalAccess', _50 => _50.length])) {
|
|
1270
1317
|
const inv = _chunkBQE3Y6ZOcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
1271
1318
|
const x0 = num2("x");
|
|
1272
1319
|
const y0 = num2("y");
|
|
1273
1320
|
const add = command3.blend === "add";
|
|
1274
1321
|
const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkBQE3Y6ZOcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
|
|
1275
|
-
const times = _optionalChain([command3, 'access',
|
|
1322
|
+
const times = _optionalChain([command3, 'access', _51 => _51.times, 'optionalAccess', _52 => _52.length]) === command3.via.length ? [start, ...command3.times.map((f) => start + f * (end - start)), end] : smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(command3.pacing, () => ( "even")));
|
|
1276
1323
|
for (const axis of ["x", "y"]) {
|
|
1277
1324
|
const base = add ? 0 : axis === "x" ? x0 : y0;
|
|
1278
1325
|
for (const leg of smoothMotionLegs(times, offsets.map((o) => o[axis])))
|
|
@@ -1364,7 +1411,7 @@ function compileMotionScene(scene) {
|
|
|
1364
1411
|
for (const track of tracks.values()) track.sort((a, b) => a.start - b.start);
|
|
1365
1412
|
segments.sort((a, b) => a.start - b.start);
|
|
1366
1413
|
const duration = shots.length ? shots[shots.length - 1].end : 0;
|
|
1367
|
-
const timeline = { duration, shots, commands, segments, tracks, ..._optionalChain([scene, 'access',
|
|
1414
|
+
const timeline = { duration, shots, commands, segments, tracks, ..._optionalChain([scene, 'access', _53 => _53.drivers, 'optionalAccess', _54 => _54.length]) ? { drivers: scene.drivers, restOpacity: new Map([...nodes].map(([id, e]) => [id, _nullishCoalesce(e.node.opacity, () => ( 1))])) } : {} };
|
|
1368
1415
|
timelineCache.set(scene, timeline);
|
|
1369
1416
|
return timeline;
|
|
1370
1417
|
}
|
|
@@ -1372,12 +1419,166 @@ function motionShotAt(timeline, time) {
|
|
|
1372
1419
|
return _nullishCoalesce(timeline.shots.find((s) => time < s.end), () => ( timeline.shots[timeline.shots.length - 1]));
|
|
1373
1420
|
}
|
|
1374
1421
|
|
|
1422
|
+
// src/animation-editor/camera.ts
|
|
1423
|
+
var windowCache = /* @__PURE__ */ new WeakMap();
|
|
1424
|
+
function motionShotCameraMove(shot, role) {
|
|
1425
|
+
return _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _55 => _55.camera, 'optionalAccess', _56 => _56[role === "transition" ? "in" : "during"]]));
|
|
1426
|
+
}
|
|
1427
|
+
var motionCameraStage = (scene) => ({ width: scene.artwork.width, height: scene.artwork.height });
|
|
1428
|
+
var effectsPlayCamera = (provider) => !!provider && provider.capabilities.supportsCamera === true && typeof provider.cameraView === "function";
|
|
1429
|
+
async function motionCameraMoves(provider, role) {
|
|
1430
|
+
if (!effectsPlayCamera(provider)) return [];
|
|
1431
|
+
const all = await provider.list({ kind: "camera" });
|
|
1432
|
+
return all.filter((e) => e.kind === "camera" && e.camera && (!role || e.camera.role === role));
|
|
1433
|
+
}
|
|
1434
|
+
function motionCameraWindows(scene, provider) {
|
|
1435
|
+
if (!effectsPlayCamera(provider)) return [];
|
|
1436
|
+
if (!scene.shots.some((s) => s.camera && (s.camera.in !== void 0 || s.camera.during !== void 0))) return [];
|
|
1437
|
+
const timeline = compileMotionScene(scene);
|
|
1438
|
+
let byProvider = windowCache.get(timeline);
|
|
1439
|
+
if (!byProvider) windowCache.set(timeline, byProvider = /* @__PURE__ */ new WeakMap());
|
|
1440
|
+
const cached = byProvider.get(provider);
|
|
1441
|
+
if (cached) return cached;
|
|
1442
|
+
const stage = motionCameraStage(scene);
|
|
1443
|
+
const full = { x: 0, y: 0, width: stage.width, height: stage.height };
|
|
1444
|
+
const track = timeline.tracks.get(motionTrackKey("", "camera"));
|
|
1445
|
+
const boxView = (t) => {
|
|
1446
|
+
const b = trackValue(track, t);
|
|
1447
|
+
return _chunkOPSK22DLcjs.cameraViewOfBox.call(void 0, Array.isArray(b) ? { x: b[0], y: b[1], width: b[2], height: b[3] } : full, stage);
|
|
1448
|
+
};
|
|
1449
|
+
const view = (move, values, from, to, u, ms2) => {
|
|
1450
|
+
try {
|
|
1451
|
+
return provider.cameraView(move, { from, to, u, ms: ms2, stage }, values);
|
|
1452
|
+
} catch (e4) {
|
|
1453
|
+
return null;
|
|
1454
|
+
}
|
|
1455
|
+
};
|
|
1456
|
+
const windows = [];
|
|
1457
|
+
let carry = null;
|
|
1458
|
+
for (const timing of timeline.shots) {
|
|
1459
|
+
const shot = scene.shots[timing.index];
|
|
1460
|
+
const eases = timing.commandsStart > timing.start && !!_optionalChain([track, 'optionalAccess', _57 => _57.some, 'call', _58 => _58((seg) => seg.shot === timing.id)]);
|
|
1461
|
+
const framed = !!_optionalChain([track, 'optionalAccess', _59 => _59.some, 'call', _60 => _60((seg) => seg.shot === timing.id)]);
|
|
1462
|
+
if (timing.cameraIn && timing.commandsStart > timing.start) {
|
|
1463
|
+
const spec = _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _61 => _61.camera, 'optionalAccess', _62 => _62.in]));
|
|
1464
|
+
const from = _nullishCoalesce(carry, () => ( boxView(timing.start)));
|
|
1465
|
+
const to = boxView(timing.commandsStart);
|
|
1466
|
+
if (view(spec.move, spec.values, from, to, 0, timing.commandsStart - timing.start)) {
|
|
1467
|
+
windows.push({ shot: timing.id, kind: "in", move: spec.move, ...spec.values ? { values: spec.values } : {}, start: timing.start, end: timing.commandsStart, from, to, after: null });
|
|
1468
|
+
carry = null;
|
|
1469
|
+
}
|
|
1470
|
+
} else if (carry && eases) {
|
|
1471
|
+
windows.push({ shot: timing.id, kind: "ease", start: timing.start, end: timing.commandsStart, from: carry, to: boxView(timing.commandsStart), after: null });
|
|
1472
|
+
carry = null;
|
|
1473
|
+
} else if (framed) carry = null;
|
|
1474
|
+
if (timing.cameraDuring && timing.end > timing.commandsEnd) {
|
|
1475
|
+
const spec = _chunkOPSK22DLcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _63 => _63.camera, 'optionalAccess', _64 => _64.during]));
|
|
1476
|
+
const from = _nullishCoalesce(carry, () => ( boxView(timing.commandsEnd)));
|
|
1477
|
+
const ms2 = timing.end - timing.commandsEnd;
|
|
1478
|
+
const last = view(spec.move, spec.values, from, from, 1, ms2);
|
|
1479
|
+
if (last) {
|
|
1480
|
+
windows.push({ shot: timing.id, kind: "during", move: spec.move, ...spec.values ? { values: spec.values } : {}, start: timing.commandsEnd, end: timing.end, from, to: from, after: last });
|
|
1481
|
+
carry = last;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
byProvider.set(provider, windows);
|
|
1486
|
+
return windows;
|
|
1487
|
+
}
|
|
1488
|
+
var lerp = (a, b, t) => a + (b - a) * t;
|
|
1489
|
+
var smooth = (t) => t * t * (3 - 2 * t);
|
|
1490
|
+
function easeViews(from, to, u, stage) {
|
|
1491
|
+
const k = smooth(Math.min(1, Math.max(0, u)));
|
|
1492
|
+
const a = _chunkOPSK22DLcjs.cameraBoxOfView.call(void 0, from, stage);
|
|
1493
|
+
const b = _chunkOPSK22DLcjs.cameraBoxOfView.call(void 0, to, stage);
|
|
1494
|
+
const zoom = from.zoom * Math.pow(to.zoom / from.zoom, k);
|
|
1495
|
+
const cx = lerp(a.x + a.width / 2, b.x + b.width / 2, k);
|
|
1496
|
+
const cy = lerp(a.y + a.height / 2, b.y + b.height / 2, k);
|
|
1497
|
+
const view = { zoom, scrollX: stage.width / (2 * zoom) - cx, scrollY: stage.height / (2 * zoom) - cy };
|
|
1498
|
+
for (const key of ["tilt", "turn", "roll"]) if (from[key] || to[key]) view[key] = lerp(_nullishCoalesce(from[key], () => ( 0)), _nullishCoalesce(to[key], () => ( 0)), k);
|
|
1499
|
+
return view;
|
|
1500
|
+
}
|
|
1501
|
+
function motionCameraViewAt(scene, time, provider) {
|
|
1502
|
+
const windows = motionCameraWindows(scene, provider);
|
|
1503
|
+
if (!windows.length || !effectsPlayCamera(provider)) return null;
|
|
1504
|
+
const stage = motionCameraStage(scene);
|
|
1505
|
+
let before;
|
|
1506
|
+
for (const w of windows) {
|
|
1507
|
+
if (w.start > time) break;
|
|
1508
|
+
if (time < w.end || time === w.end && w === windows[windows.length - 1] && w.after) {
|
|
1509
|
+
const u = w.end > w.start ? (time - w.start) / (w.end - w.start) : 1;
|
|
1510
|
+
if (w.kind === "ease") return easeViews(w.from, w.to, u, stage);
|
|
1511
|
+
try {
|
|
1512
|
+
return provider.cameraView(w.move, { from: w.from, to: w.to, u: Math.min(1, Math.max(0, u)), ms: w.end - w.start, stage }, w.values);
|
|
1513
|
+
} catch (e5) {
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
before = w;
|
|
1518
|
+
}
|
|
1519
|
+
if (!_optionalChain([before, 'optionalAccess', _65 => _65.after])) return null;
|
|
1520
|
+
const track = compileMotionScene(scene).tracks.get(motionTrackKey("", "camera"));
|
|
1521
|
+
const retaken = _optionalChain([track, 'optionalAccess', _66 => _66.some, 'call', _67 => _67((seg) => seg.start >= before.end && seg.start <= time)]);
|
|
1522
|
+
return retaken ? null : before.after;
|
|
1523
|
+
}
|
|
1524
|
+
function motionCameraBox(view, scene) {
|
|
1525
|
+
return _chunkOPSK22DLcjs.cameraBoxOfView.call(void 0, view, motionCameraStage(scene));
|
|
1526
|
+
}
|
|
1527
|
+
function motionCameraTransform(view, width) {
|
|
1528
|
+
if (!view || !view.tilt && !view.turn) return "";
|
|
1529
|
+
const distance = (_nullishCoalesce(view.perspective, () => ( 2))) * width;
|
|
1530
|
+
return `perspective(${Math.round(distance)}px)${view.tilt ? ` rotateX(${round(view.tilt)}deg)` : ""}${view.turn ? ` rotateY(${round(-view.turn)}deg)` : ""}`;
|
|
1531
|
+
}
|
|
1532
|
+
var round = (n) => Math.round(n * 1e3) / 1e3;
|
|
1533
|
+
function withCameraViewEffects(svg, view, box, idPrefix = "vg-") {
|
|
1534
|
+
if (!view || !view.roll && !(view.blur && view.blur > 0)) return svg;
|
|
1535
|
+
const open = svg.match(/<svg\b[^>]*>/);
|
|
1536
|
+
const close = svg.lastIndexOf("</svg>");
|
|
1537
|
+
if (!open || close < 0) return svg;
|
|
1538
|
+
const startBody = open.index + open[0].length;
|
|
1539
|
+
const attrs = [];
|
|
1540
|
+
let defs = "";
|
|
1541
|
+
if (view.roll) attrs.push(`transform="rotate(${round(view.roll)} ${round(box.x + box.width / 2)} ${round(box.y + box.height / 2)})"`);
|
|
1542
|
+
if (view.blur && view.blur > 0) {
|
|
1543
|
+
const s = view.blur / view.zoom / 2;
|
|
1544
|
+
const a = (_nullishCoalesce(view.blurAngle, () => ( 0))) * Math.PI / 180;
|
|
1545
|
+
const [sx, sy] = view.blurAngle === void 0 ? [s, s] : [Math.abs(Math.cos(a)) * s, Math.abs(Math.sin(a)) * s];
|
|
1546
|
+
const id = `${idPrefix}camera-blur`;
|
|
1547
|
+
defs = `<defs><filter id="${id}" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="${round(sx)} ${round(sy)}"/></filter></defs>`;
|
|
1548
|
+
attrs.push(`filter="url(#${id})"`);
|
|
1549
|
+
}
|
|
1550
|
+
return `${svg.slice(0, startBody)}${defs}<g ${attrs.join(" ")}>${svg.slice(startBody, close)}</g>${svg.slice(close)}`;
|
|
1551
|
+
}
|
|
1552
|
+
async function checkMotionCameraMoves(scene, provider) {
|
|
1553
|
+
const issues = [];
|
|
1554
|
+
const named = scene.shots.filter((s) => s.camera && (s.camera.in !== void 0 || s.camera.during !== void 0));
|
|
1555
|
+
if (!named.length) return issues;
|
|
1556
|
+
if (!effectsPlayCamera(provider)) {
|
|
1557
|
+
const ids = named.map((s) => `"${s.id}"`).join(", ");
|
|
1558
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "camera-move-not-played", `Shots ${ids} name camera moves, but ${provider ? `${provider.name} has no camera moves` : "no effects provider is set"}, so the camera eases between framings instead; set a provider with camera moves to play them.`));
|
|
1559
|
+
return issues;
|
|
1560
|
+
}
|
|
1561
|
+
for (const shot of named) {
|
|
1562
|
+
for (const [field, role] of [["in", "transition"], ["during", "hold"]]) {
|
|
1563
|
+
const spec = shot.camera[field];
|
|
1564
|
+
if (spec === void 0) continue;
|
|
1565
|
+
try {
|
|
1566
|
+
await _chunkOPSK22DLcjs.resolveCameraMoveSpec.call(void 0, provider, spec, role);
|
|
1567
|
+
} catch (error) {
|
|
1568
|
+
const code = error.code === "invalid_values" || /preset/.test(error.message) ? "camera-move-values" : "camera-move-unknown";
|
|
1569
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, code, error.message, { shot: shot.id }));
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return issues;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1375
1576
|
// src/animation-editor/evaluate.ts
|
|
1376
1577
|
var MOTION_DRAW_EFFECT_ID = "~draw";
|
|
1377
1578
|
var TRANSFORM_PROPS = ["x", "y", "rotation", "scaleX", "scaleY", "follow"];
|
|
1378
1579
|
var tidy = (v) => Math.round(v * 1e6) / 1e6 || 0;
|
|
1379
1580
|
function applyMotionControlValues(scene, values) {
|
|
1380
|
-
if (!values || !_optionalChain([scene, 'access',
|
|
1581
|
+
if (!values || !_optionalChain([scene, 'access', _68 => _68.controls, 'optionalAccess', _69 => _69.length])) return scene;
|
|
1381
1582
|
const map = /* @__PURE__ */ new Map();
|
|
1382
1583
|
for (const control of scene.controls) {
|
|
1383
1584
|
const value = values[control.name];
|
|
@@ -1424,7 +1625,7 @@ function shapeIn(entry, shape) {
|
|
|
1424
1625
|
}
|
|
1425
1626
|
function shapeAt(entry, timeline, nodes, time) {
|
|
1426
1627
|
const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
|
|
1427
|
-
if (!_optionalChain([track, 'optionalAccess',
|
|
1628
|
+
if (!_optionalChain([track, 'optionalAccess', _70 => _70.length])) return null;
|
|
1428
1629
|
const s = activeSegment(track, time);
|
|
1429
1630
|
const fromId = String(s ? s.from : track[0].from);
|
|
1430
1631
|
if (!s) return fromId === entry.node.id ? null : nodes.get(fromId) ? shapeIn(entry, nodes.get(fromId)) : null;
|
|
@@ -1441,14 +1642,14 @@ function motionFollowRoute(entry, path) {
|
|
|
1441
1642
|
if (!path || path.node.type !== "path") return null;
|
|
1442
1643
|
try {
|
|
1443
1644
|
return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkBQE3Y6ZOcjs.invertMatrix.call(void 0, entry.parentWorld));
|
|
1444
|
-
} catch (
|
|
1645
|
+
} catch (e6) {
|
|
1445
1646
|
return null;
|
|
1446
1647
|
}
|
|
1447
1648
|
}
|
|
1448
1649
|
function followAt(entry, timeline, nodes, time) {
|
|
1449
1650
|
const track = timeline.tracks.get(motionTrackKey(entry.node.id, "follow"));
|
|
1450
|
-
const s = _nullishCoalesce(activeSegment(track, time), () => ( _optionalChain([track, 'optionalAccess',
|
|
1451
|
-
if (!_optionalChain([s, 'optionalAccess',
|
|
1651
|
+
const s = _nullishCoalesce(activeSegment(track, time), () => ( _optionalChain([track, 'optionalAccess', _71 => _71[0]])));
|
|
1652
|
+
if (!_optionalChain([s, 'optionalAccess', _72 => _72.path])) return null;
|
|
1452
1653
|
const route = motionFollowRoute(entry, nodes.get(s.path));
|
|
1453
1654
|
const progress = Number(trackValue(track, time));
|
|
1454
1655
|
if (!route || !(progress >= 0)) return null;
|
|
@@ -1456,7 +1657,7 @@ function followAt(entry, timeline, nodes, time) {
|
|
|
1456
1657
|
const at = _chunkGF2RBSDMcjs.bezierPathPointAtLength.call(void 0, route, Math.min(1, Math.max(0, progress)) * _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, route));
|
|
1457
1658
|
if (!at) return null;
|
|
1458
1659
|
return { x: at.point[0], y: at.point[1], angle: s.rotate ? at.angle * 180 / Math.PI : 0 };
|
|
1459
|
-
} catch (
|
|
1660
|
+
} catch (e7) {
|
|
1460
1661
|
return null;
|
|
1461
1662
|
}
|
|
1462
1663
|
}
|
|
@@ -1466,7 +1667,7 @@ function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry
|
|
|
1466
1667
|
const layered = withMotionLayers(timeline, entry.node.id, p, typeof v === "number" ? v : rest, time, raw);
|
|
1467
1668
|
return p === "follow" ? layered : applyMotionDrivers(timeline, entry.node.id, p, layered, time, raw);
|
|
1468
1669
|
};
|
|
1469
|
-
const driven = _optionalChain([timeline, 'access',
|
|
1670
|
+
const driven = _optionalChain([timeline, 'access', _73 => _73.drivers, 'optionalAccess', _74 => _74.some, 'call', _75 => _75((d) => d.target === entry.node.id && d.property !== "opacity")]);
|
|
1470
1671
|
if (!driven && !TRANSFORM_PROPS.some((p) => (follow || p !== "follow") && (timeline.tracks.has(motionTrackKey(entry.node.id, p)) || timeline.tracks.has(motionAddTrackKey(entry.node.id, p))))) return null;
|
|
1471
1672
|
const dx = read("x", 0);
|
|
1472
1673
|
const dy = read("y", 0);
|
|
@@ -1510,7 +1711,7 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
1510
1711
|
if (out.visible === void 0) delete out.visible;
|
|
1511
1712
|
}
|
|
1512
1713
|
const effectTracks = [...timeline.tracks.keys()].filter((k) => k.startsWith(`${id}\0effect:`));
|
|
1513
|
-
if (effectTracks.length && _optionalChain([out, 'access',
|
|
1714
|
+
if (effectTracks.length && _optionalChain([out, 'access', _76 => _76.effects, 'optionalAccess', _77 => _77.length])) {
|
|
1514
1715
|
out = {
|
|
1515
1716
|
...out,
|
|
1516
1717
|
effects: out.effects.map((effect) => {
|
|
@@ -1550,7 +1751,7 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
1550
1751
|
return p;
|
|
1551
1752
|
});
|
|
1552
1753
|
}
|
|
1553
|
-
const opacity = _optionalChain([timeline, 'access',
|
|
1754
|
+
const opacity = _optionalChain([timeline, 'access', _78 => _78.drivers, 'optionalAccess', _79 => _79.some, 'call', _80 => _80((d) => d.target === id && d.property === "opacity")]) ? motionPropertyValue(timeline, id, "opacity", time) : value(id, "opacity");
|
|
1554
1755
|
if (typeof opacity === "number") {
|
|
1555
1756
|
const o = Math.min(1, Math.max(0, tidy(opacity)));
|
|
1556
1757
|
out = { ...out, opacity: o };
|
|
@@ -1565,8 +1766,9 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
1565
1766
|
};
|
|
1566
1767
|
const document = { ...s.artwork, nodes: s.artwork.nodes.map(visit) };
|
|
1567
1768
|
const cam = trackValue(timeline.tracks.get(motionTrackKey("", "camera")), time);
|
|
1568
|
-
const
|
|
1569
|
-
|
|
1769
|
+
const view = motionCameraViewAt(s, time, options.effects);
|
|
1770
|
+
const box = view ? (({ x, y, width, height }) => [x, y, width, height])(motionCameraBox(view, s)) : Array.isArray(cam) ? cam : [0, 0, s.artwork.width, s.artwork.height];
|
|
1771
|
+
return { time, document, camera: { x: tidy(box[0]), y: tidy(box[1]), width: tidy(box[2]), height: tidy(box[3]) }, ...view ? { view } : {}, clips };
|
|
1570
1772
|
}
|
|
1571
1773
|
function motionClipAttrs(clip) {
|
|
1572
1774
|
const { shape: _shape, ...attrs } = clip;
|
|
@@ -1578,7 +1780,7 @@ function motionFrameToSvg(scene, time, options = {}) {
|
|
|
1578
1780
|
const wrap = { ...options.wrap };
|
|
1579
1781
|
for (const [id, clips] of Object.entries(frame.clips))
|
|
1580
1782
|
wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
|
|
1581
|
-
return withViewBox(_chunkBQE3Y6ZOcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera);
|
|
1783
|
+
return withCameraViewEffects(withViewBox(_chunkBQE3Y6ZOcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera), frame.view, frame.camera, prefix);
|
|
1582
1784
|
}
|
|
1583
1785
|
function withViewBox(svg, box) {
|
|
1584
1786
|
const f = (n) => String(Math.round(n * 1e3) / 1e3);
|
|
@@ -1623,7 +1825,7 @@ function motionPath(scene, id, options = {}) {
|
|
|
1623
1825
|
const r = (n) => Math.round(n * 100) / 100;
|
|
1624
1826
|
const centreAt = (t) => {
|
|
1625
1827
|
const node = indexMotionNodes(motionFrameAtCache(scene, t)).get(id);
|
|
1626
|
-
const b = _optionalChain([node, 'optionalAccess',
|
|
1828
|
+
const b = _optionalChain([node, 'optionalAccess', _81 => _81.bounds]);
|
|
1627
1829
|
return b ? { t: r(t), x: r(b.x + b.width / 2), y: r(b.y + b.height / 2) } : null;
|
|
1628
1830
|
};
|
|
1629
1831
|
const points = [];
|
|
@@ -1657,8 +1859,8 @@ function motionBlurTimes(scene, time, blur = {}) {
|
|
|
1657
1859
|
const b = indexMotionNodes(motionFrameAt(scene, time + span / 2).document.nodes);
|
|
1658
1860
|
let travel = 0;
|
|
1659
1861
|
for (const id of ids) {
|
|
1660
|
-
const p = _optionalChain([a, 'access',
|
|
1661
|
-
const q = _optionalChain([b, 'access',
|
|
1862
|
+
const p = _optionalChain([a, 'access', _82 => _82.get, 'call', _83 => _83(id), 'optionalAccess', _84 => _84.bounds]);
|
|
1863
|
+
const q = _optionalChain([b, 'access', _85 => _85.get, 'call', _86 => _86(id), 'optionalAccess', _87 => _87.bounds]);
|
|
1662
1864
|
if (p && q) travel = Math.max(travel, Math.abs(p.x - q.x), Math.abs(p.y - q.y), Math.abs(p.x + p.width - q.x - q.width), Math.abs(p.y + p.height - q.y - q.height));
|
|
1663
1865
|
}
|
|
1664
1866
|
const n = Math.min(most, Math.ceil(travel / 1.5));
|
|
@@ -1670,7 +1872,7 @@ function averagedFrames(scene, times, options, prefix) {
|
|
|
1670
1872
|
return `<g data-motion-blur="${n}" style="isolation:isolate">${times.map((t, k) => {
|
|
1671
1873
|
const own = `${prefix}blur${k}-`;
|
|
1672
1874
|
const frame = motionFrameToSvg(scene, t, { ...options, idPrefix: own, background: false });
|
|
1673
|
-
const view = _nullishCoalesce(_optionalChain([/viewBox="([^"]*)"/, 'access',
|
|
1875
|
+
const view = _nullishCoalesce(_optionalChain([/viewBox="([^"]*)"/, 'access', _88 => _88.exec, 'call', _89 => _89(frame), 'optionalAccess', _90 => _90[1]]), () => ( ""));
|
|
1674
1876
|
const inner = k === n - 1 ? innerSvg(frame) : innerSvg(frame).replace(new RegExp(` id="(?!${own.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})[^"]*"`, "g"), "");
|
|
1675
1877
|
return `<svg viewBox="${view}" preserveAspectRatio="none" style="mix-blend-mode:plus-lighter" opacity="${Math.round(1e4 / n) / 1e4}">${inner}</svg>`;
|
|
1676
1878
|
}).join("")}</g>`;
|
|
@@ -1685,7 +1887,7 @@ function motionStageSvg(scene, time, options = {}) {
|
|
|
1685
1887
|
if (blurTimes.length > 1) {
|
|
1686
1888
|
const open2 = current.indexOf(">") + 1;
|
|
1687
1889
|
const body2 = current.slice(open2, current.lastIndexOf("</svg>"));
|
|
1688
|
-
const bg2 = svgOptions.background !== false && scene.artwork.background ? _nullishCoalesce(_optionalChain([/^\s*<rect[^>]*\/>/, 'access',
|
|
1890
|
+
const bg2 = svgOptions.background !== false && scene.artwork.background ? _nullishCoalesce(_optionalChain([/^\s*<rect[^>]*\/>/, 'access', _91 => _91.exec, 'call', _92 => _92(body2), 'optionalAccess', _93 => _93[0]]), () => ( "")) : "";
|
|
1689
1891
|
current = `${current.slice(0, open2)}${bg2}${averagedFrames(scene, blurTimes, svgOptions, prefix)}</svg>`;
|
|
1690
1892
|
}
|
|
1691
1893
|
if (!onionSkin && !motionPaths) return current;
|
|
@@ -1694,13 +1896,13 @@ function motionStageSvg(scene, time, options = {}) {
|
|
|
1694
1896
|
const inner = innerSvg(motionFrameToSvg(scene, g.time, { ...svgOptions, idPrefix: own, background: false })).replace(new RegExp(` id="(?!${own.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})[^"]*"`, "g"), "");
|
|
1695
1897
|
return `<g data-onion="${g.offset < 0 ? "before" : "after"}" opacity="${g.opacity}">${inner}</g>`;
|
|
1696
1898
|
}) : [];
|
|
1697
|
-
const camera = motionFrameAt(scene, time).camera;
|
|
1899
|
+
const camera = motionFrameAt(scene, time, { effects: svgOptions.effects }).camera;
|
|
1698
1900
|
const ids = motionPaths === true ? motionMovingIds(scene) : motionPaths ? [...motionPaths] : [];
|
|
1699
1901
|
const paths = ids.length ? motionPathsSvg(ids.map((id) => motionPath(scene, id)), camera, motionPathColor) : "";
|
|
1700
1902
|
const open = current.indexOf(">") + 1;
|
|
1701
1903
|
const close = current.lastIndexOf("</svg>");
|
|
1702
1904
|
const body = current.slice(open, close);
|
|
1703
|
-
const bg = svgOptions.background !== false && scene.artwork.background ? _nullishCoalesce(_optionalChain([/^\s*<rect[^>]*\/>/, 'access',
|
|
1905
|
+
const bg = svgOptions.background !== false && scene.artwork.background ? _nullishCoalesce(_optionalChain([/^\s*<rect[^>]*\/>/, 'access', _94 => _94.exec, 'call', _95 => _95(body), 'optionalAccess', _96 => _96[0]]), () => ( "")) : "";
|
|
1704
1906
|
return `${current.slice(0, open)}${bg}${ghosts.join("")}${body.slice(bg.length)}${paths}</svg>`;
|
|
1705
1907
|
}
|
|
1706
1908
|
function motionContactSheetSvg(scene, times, options = {}) {
|
|
@@ -1719,7 +1921,7 @@ function motionContactSheetSvg(scene, times, options = {}) {
|
|
|
1719
1921
|
const x = gap + i % cols * (w + gap);
|
|
1720
1922
|
const y = gap + Math.floor(i / cols) * (h + label + gap);
|
|
1721
1923
|
const frame = motionStageSvg(scene, t, { ...frameOptions, idPrefix: `${prefix}f${i}-` });
|
|
1722
|
-
const view = _nullishCoalesce(_optionalChain([/viewBox="([^"]*)"/, 'access',
|
|
1924
|
+
const view = _nullishCoalesce(_optionalChain([/viewBox="([^"]*)"/, 'access', _97 => _97.exec, 'call', _98 => _98(frame), 'optionalAccess', _99 => _99[1]]), () => ( `0 0 ${w} ${h}`));
|
|
1723
1925
|
const inner = innerSvg(frame).replace(new RegExp(` id="(?!${`${prefix}f${i}-`.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})[^"]*"`, "g"), "");
|
|
1724
1926
|
const shot = _nullishCoalesce(timeline.shots.find((s) => t >= s.start && t < s.end), () => ( timeline.shots[timeline.shots.length - 1]));
|
|
1725
1927
|
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>` : "";
|
|
@@ -1731,7 +1933,7 @@ function motionContactSheetSvg(scene, times, options = {}) {
|
|
|
1731
1933
|
// src/animation-editor/check.ts
|
|
1732
1934
|
var MOTION_MIN_CHANGE_MS = 120;
|
|
1733
1935
|
var NUMERIC_PARAMS = (node, effectId) => {
|
|
1734
|
-
const effect = _optionalChain([node, 'access',
|
|
1936
|
+
const effect = _optionalChain([node, 'access', _100 => _100.effects, 'optionalAccess', _101 => _101.find, 'call', _102 => _102((e) => e.id === effectId)]);
|
|
1735
1937
|
if (!effect) return null;
|
|
1736
1938
|
return Object.entries(effect.params).filter(([, v]) => typeof v === "number").map(([k]) => k);
|
|
1737
1939
|
};
|
|
@@ -1774,96 +1976,97 @@ function checkMotionScene(scene) {
|
|
|
1774
1976
|
const ids = [...nodes.keys()];
|
|
1775
1977
|
const timeline = compileMotionScene(scene);
|
|
1776
1978
|
const artAspect = scene.artwork.width / scene.artwork.height;
|
|
1777
|
-
if (!scene.shots.length) issues.push(
|
|
1979
|
+
if (!scene.shots.length) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "no-shots", "The scene has no shots yet; add one with a list of commands."));
|
|
1778
1980
|
const seen = /* @__PURE__ */ new Set();
|
|
1779
1981
|
for (const shot of scene.shots) {
|
|
1780
|
-
if (seen.has(shot.id)) issues.push(
|
|
1982
|
+
if (seen.has(shot.id)) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "duplicate-shot-id", `Shot id "${shot.id}" is used twice; give each shot its own id.`, { shot: shot.id }));
|
|
1781
1983
|
seen.add(shot.id);
|
|
1782
1984
|
}
|
|
1783
1985
|
const known = (id, code, what, where) => {
|
|
1784
1986
|
if (nodes.has(id)) return true;
|
|
1785
|
-
issues.push(
|
|
1987
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, code, `There is no ${what} ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, ids)} in the artwork${ids.length ? "" : " (it has no nodes yet)"}.`, { ...where, ids: [id] }));
|
|
1786
1988
|
return false;
|
|
1787
1989
|
};
|
|
1788
1990
|
scene.shots.forEach((shot, shotIndex2) => {
|
|
1789
1991
|
if (shot.camera && "frame" in shot.camera && typeof shot.camera.frame === "string") known(shot.camera.frame, "unknown-frame", "node to frame", { shot: shot.id });
|
|
1790
|
-
else if (shot.camera) {
|
|
1992
|
+
else if (shot.camera && motionCameraFramed(shot.camera)) {
|
|
1791
1993
|
const c = shot.camera;
|
|
1792
|
-
if (!(c.width > 0 && c.height > 0)) issues.push(
|
|
1994
|
+
if (!(c.width > 0 && c.height > 0)) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "invalid-camera", `The camera needs a positive width and height (got ${c.width} \xD7 ${c.height}).`, { shot: shot.id }));
|
|
1793
1995
|
else if (Math.abs(c.width / c.height / artAspect - 1) > 0.02)
|
|
1794
|
-
issues.push(
|
|
1996
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "camera-aspect", `The camera is ${c.width} \xD7 ${c.height}, a different shape from the ${scene.artwork.width} \xD7 ${scene.artwork.height} artwork, so it shows bands at the sides; frame a node instead to match.`, { shot: shot.id }));
|
|
1795
1997
|
}
|
|
1796
|
-
if (
|
|
1998
|
+
if (shotIndex2 === 0 && _optionalChain([shot, 'access', _103 => _103.camera, 'optionalAccess', _104 => _104.in]) !== void 0) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "camera-move-first-shot", 'The first shot cuts to its framing (there is none before it to move from), so its camera "in" does not play; put the move on the next shot, or use a "during" move here.', { shot: shot.id }));
|
|
1999
|
+
if (!shot.run.length && !shot.camera && shotIndex2 > 0) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "empty-shot", "This shot only holds; add commands or a camera move, or remove it.", { shot: shot.id }));
|
|
1797
2000
|
shot.run.forEach((command3, i) => {
|
|
1798
2001
|
const where = { shot: shot.id, command: i };
|
|
1799
2002
|
if (command3.type === "wait") return;
|
|
1800
2003
|
const targets = command3.targets.filter((id) => known(id, "unknown-target", "node", where));
|
|
1801
2004
|
const timing = timeline.commands.find((c) => c.shot === shot.id && c.command === i);
|
|
1802
2005
|
if (timing && timing.duration > 0 && timing.duration < MOTION_MIN_CHANGE_MS)
|
|
1803
|
-
issues.push(
|
|
2006
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "too-fast", `This ${command3.type} lasts ${timing.duration} ms, too quick to follow; make it at least ${MOTION_MIN_CHANGE_MS} ms.`, { ...where, measured: timing.duration, needed: MOTION_MIN_CHANGE_MS, unit: "ms", ids: targets }));
|
|
1804
2007
|
if (command3.duration !== void 0 && command3.ease !== void 0) {
|
|
1805
2008
|
const ease = _chunkDWJJI6RTcjs.resolveEasing.call(void 0, command3.ease);
|
|
1806
2009
|
if (ease !== "hold" && ease.type === "spring") {
|
|
1807
2010
|
const settle = _chunkDWJJI6RTcjs.springSettleMs.call(void 0, ease);
|
|
1808
2011
|
if (command3.duration < settle * 0.9)
|
|
1809
|
-
issues.push(
|
|
2012
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "spring-cut-short", `This ${command3.type}'s spring takes ${settle} ms to settle but lasts ${command3.duration} ms, so it jumps to its end; leave "duration" out (the spring sets it) or make it at least ${settle} ms.`, { ...where, measured: command3.duration, needed: settle, unit: "ms", ids: targets }));
|
|
1810
2013
|
}
|
|
1811
2014
|
}
|
|
1812
2015
|
if (command3.type === "follow" && known(command3.path, "unknown-path", "path", where) && nodes.get(command3.path).node.type !== "path")
|
|
1813
|
-
issues.push(
|
|
2016
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "not-a-path", `"${command3.path}" is a group; follow a single path node.`, { ...where, ids: [command3.path] }));
|
|
1814
2017
|
if (command3.type === "morph") known(command3.into, "unknown-shape", "shape", where);
|
|
1815
2018
|
if (command3.type !== "play" && command3.split) {
|
|
1816
2019
|
for (const id of targets)
|
|
1817
2020
|
if (!motionTextLayout(nodes, id))
|
|
1818
|
-
issues.push(
|
|
2021
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "split-not-text", `"${id}" is not a group of letter paths, so "split": "${command3.split}" animates it as a whole; convert the text to outlines and group the letters (get_text_layout shows how they read).`, { ...where, ids: [id] }));
|
|
1819
2022
|
}
|
|
1820
|
-
if (command3.type === "play" && !_optionalChain([scene, 'access',
|
|
1821
|
-
issues.push(
|
|
2023
|
+
if (command3.type === "play" && !_optionalChain([scene, 'access', _105 => _105.clips, 'optionalAccess', _106 => _106[command3.clip]]))
|
|
2024
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-clip", `There is no clip ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, command3.clip, Object.keys(_nullishCoalesce(scene.clips, () => ( {}))))}; define it with set_animation_clip.`, where));
|
|
1822
2025
|
if (command3.type === "match" && known(command3.into, "unknown-shape", "group", where)) {
|
|
1823
2026
|
const into = nodes.get(command3.into);
|
|
1824
2027
|
for (const id of targets) {
|
|
1825
2028
|
const entry = nodes.get(id);
|
|
1826
2029
|
if (id === command3.into || into.ancestors.includes(id) || entry.ancestors.includes(command3.into)) {
|
|
1827
|
-
issues.push(
|
|
2030
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "match-self", `"${id}" cannot match "${command3.into}": one is the other or holds it. Match two separate groups (the second usually hidden).`, { ...where, ids: [id, command3.into] }));
|
|
1828
2031
|
continue;
|
|
1829
2032
|
}
|
|
1830
2033
|
const m = matchMotionNodes(entry.node, into.node);
|
|
1831
2034
|
if (m.unpairedInto.length)
|
|
1832
|
-
issues.push(
|
|
2035
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "match-unpaired", `${m.unpairedInto.map((x) => `"${x}"`).join(", ")} in "${command3.into}" ${m.unpairedInto.length > 1 ? "have" : "has"} no partner in "${id}", so ${m.unpairedInto.length > 1 ? "they do" : "it does"} not appear; add a part with the same name or id to "${id}" (it can start hidden or tiny).`, { ...where, ids: m.unpairedInto }));
|
|
1833
2036
|
}
|
|
1834
2037
|
}
|
|
1835
2038
|
const style = command3.type === "enter" || command3.type === "exit" ? command3.style : void 0;
|
|
1836
2039
|
if (style === "wipe" || style === "iris" || style === "split") {
|
|
1837
2040
|
for (const id of targets)
|
|
1838
2041
|
if (!motionRevealPadding(nodes.get(id)))
|
|
1839
|
-
issues.push(
|
|
2042
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "reveal-no-box", `"${id}" has no width or height (a straight line), so a ${style} cannot clip it and it fades instead; use style "${command3.type === "enter" ? "draw" : "undraw"}" for a line.`, { ...where, ids: [id] }));
|
|
1840
2043
|
}
|
|
1841
2044
|
if (command3.type === "style") {
|
|
1842
2045
|
for (const key of ["fill", "stroke"]) {
|
|
1843
2046
|
const color = command3[key];
|
|
1844
2047
|
if (color === void 0) continue;
|
|
1845
2048
|
if (_chunkA6QWKBJPcjs.normalizeTokenColor.call(void 0, color) === null) {
|
|
1846
|
-
issues.push(
|
|
2049
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "invalid-color", `${key} "${color}" is not a colour this editor reads; use hex ("#0ea5e9"), rgb() or rgba().`, where));
|
|
1847
2050
|
continue;
|
|
1848
2051
|
}
|
|
1849
2052
|
for (const id of targets) {
|
|
1850
2053
|
const node = nodes.get(id).node;
|
|
1851
2054
|
const paths = node.type === "path" ? [node] : _chunkBQE3Y6ZOcjs.collectPathNodes.call(void 0, node);
|
|
1852
2055
|
if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
|
|
1853
|
-
issues.push(
|
|
2056
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
|
|
1854
2057
|
}
|
|
1855
2058
|
}
|
|
1856
2059
|
}
|
|
1857
2060
|
if (command3.type === "color-pulse") {
|
|
1858
2061
|
const key = _nullishCoalesce(command3.paint, () => ( "fill"));
|
|
1859
2062
|
const color = _nullishCoalesce(command3.color, () => ( "#f59e0b"));
|
|
1860
|
-
if (_chunkA6QWKBJPcjs.normalizeTokenColor.call(void 0, color) === null) issues.push(
|
|
2063
|
+
if (_chunkA6QWKBJPcjs.normalizeTokenColor.call(void 0, color) === null) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "invalid-color", `color "${color}" is not a colour this editor reads; use hex ("#0ea5e9"), rgb() or rgba().`, where));
|
|
1861
2064
|
else
|
|
1862
2065
|
for (const id of targets) {
|
|
1863
2066
|
const node = nodes.get(id).node;
|
|
1864
2067
|
const paths = node.type === "path" ? [node] : _chunkBQE3Y6ZOcjs.collectPathNodes.call(void 0, node);
|
|
1865
2068
|
if (paths.some((p) => typeof p[key] !== "string"))
|
|
1866
|
-
issues.push(
|
|
2069
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient or no ${key}, so a colour pulse cannot tint it; give it a solid ${key} or pulse the ${key === "fill" ? "stroke" : "fill"}.`, { ...where, ids: [id] }));
|
|
1867
2070
|
}
|
|
1868
2071
|
}
|
|
1869
2072
|
if (command3.type === "effect") {
|
|
@@ -1872,9 +2075,9 @@ function checkMotionScene(scene) {
|
|
|
1872
2075
|
const params = NUMERIC_PARAMS(node, command3.effect);
|
|
1873
2076
|
const effects = (_nullishCoalesce(node.effects, () => ( []))).map((e) => e.id);
|
|
1874
2077
|
if (!params)
|
|
1875
|
-
issues.push(
|
|
2078
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-effect", `"${id}" has no effect ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, command3.effect, effects)}${effects.length ? `; its effects are ${effects.map((e) => `"${e}"`).join(", ")}` : "; it has no live effects"}.`, { ...where, ids: [id] }));
|
|
1876
2079
|
else if (!params.includes(command3.param))
|
|
1877
|
-
issues.push(
|
|
2080
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-effect-param", `Effect "${command3.effect}" has no numeric parameter ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, command3.param, params)}; use one of ${params.join(", ")}.`, { ...where, ids: [id] }));
|
|
1878
2081
|
}
|
|
1879
2082
|
}
|
|
1880
2083
|
if (timing) {
|
|
@@ -1883,10 +2086,10 @@ function checkMotionScene(scene) {
|
|
|
1883
2086
|
const before = Math.max(0, timing.start - 0.5);
|
|
1884
2087
|
const visible = timing.start > 0 ? visibleAt(timeline, id, before, node) : node.visible !== false;
|
|
1885
2088
|
if (command3.type === "enter" && visible && timing.start > 0)
|
|
1886
|
-
issues.push(
|
|
2089
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "enter-visible", `"${id}" is already showing when it enters, so it blinks out first; remove the enter or exit it earlier.`, { ...where, ids: [id] }));
|
|
1887
2090
|
const probe = command3.type === "exit" ? timing.start + 0.5 : (timing.start + timing.end) / 2;
|
|
1888
2091
|
if (command3.type !== "enter" && command3.type !== "draw" && !visibleAt(timeline, id, probe, node))
|
|
1889
|
-
issues.push(
|
|
2092
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "exit-hidden", `"${id}" is hidden when this ${command3.type} starts, so it is not seen; enter it first.`, { ...where, ids: [id] }));
|
|
1890
2093
|
}
|
|
1891
2094
|
}
|
|
1892
2095
|
});
|
|
@@ -1894,7 +2097,7 @@ function checkMotionScene(scene) {
|
|
|
1894
2097
|
const drivers = _nullishCoalesce(scene.drivers, () => ( []));
|
|
1895
2098
|
drivers.forEach((d, i) => {
|
|
1896
2099
|
for (const id of [d.target, d.source.node])
|
|
1897
|
-
if (!nodes.has(id)) issues.push(
|
|
2100
|
+
if (!nodes.has(id)) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-target", `Driver ${i + 1} names ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, [...nodes.keys()])}, which the artwork does not have.`, { ids: [id] }));
|
|
1898
2101
|
});
|
|
1899
2102
|
{
|
|
1900
2103
|
const key = (n, p) => `${n}.${p}`;
|
|
@@ -1911,20 +2114,20 @@ function checkMotionScene(scene) {
|
|
|
1911
2114
|
return false;
|
|
1912
2115
|
};
|
|
1913
2116
|
for (const k of edges.keys()) if (visit(k, [])) break;
|
|
1914
|
-
if (loop.length) issues.push(
|
|
2117
|
+
if (loop.length) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "driver-cycle", `Drivers follow each other round in a loop (${loop.join(" \u2190 ")}); remove one of them.`, { ids: [...new Set(loop.map((k) => k.split(".")[0]))] }));
|
|
1915
2118
|
}
|
|
1916
2119
|
for (const [name, clip] of Object.entries(_nullishCoalesce(scene.clips, () => ( {}))))
|
|
1917
2120
|
for (const command3 of clip.run)
|
|
1918
2121
|
if (command3.type !== "wait") {
|
|
1919
2122
|
for (const id of command3.targets)
|
|
1920
|
-
if (id !== MOTION_CLIP_TARGET && !nodes.has(id)) issues.push(
|
|
2123
|
+
if (id !== MOTION_CLIP_TARGET && !nodes.has(id)) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-target", `Clip "${name}" names ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, [...nodes.keys()])}, which the artwork does not have; use "$" for the node the clip is played on.`, { ids: [id] }));
|
|
1921
2124
|
}
|
|
1922
2125
|
if (scene.trigger) {
|
|
1923
|
-
if ((_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") issues.push(
|
|
2126
|
+
if ((_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "trigger-loop", `The scene plays on ${scene.trigger}, so its "${scene.loop}" loop does not apply; set loop to "none" or remove the trigger.`, {}));
|
|
1924
2127
|
if (scene.trigger === "click") {
|
|
1925
|
-
if (scene.shots.length === 1) issues.push(
|
|
2128
|
+
if (scene.shots.length === 1) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "click-one-shot", "The scene plays on click but has one shot, so every click replays it from the start; split it into shots (each click plays the next one).", { shot: scene.shots[0].id }));
|
|
1926
2129
|
scene.shots.forEach((shot, i) => {
|
|
1927
|
-
if (i > 0 && shot.at) issues.push(
|
|
2130
|
+
if (i > 0 && shot.at) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "click-cue", `Shot "${shot.id}" is cued, but on click a shot starts when it is clicked to; remove its "at" or the trigger.`, { shot: shot.id }));
|
|
1928
2131
|
});
|
|
1929
2132
|
}
|
|
1930
2133
|
}
|
|
@@ -1932,11 +2135,11 @@ function checkMotionScene(scene) {
|
|
|
1932
2135
|
if (!shot.at) return;
|
|
1933
2136
|
const timing = timeline.shots[i];
|
|
1934
2137
|
if (timing.cue === void 0) {
|
|
1935
|
-
const what = shot.at.beat !== void 0 ? `beat ${shot.at.beat}, but the scene has no beat grid; set one with set_animation_settings ({ "beat": { "bpm": \u2026 } })` : `word ${shot.at.word}, but the narration has ${_nullishCoalesce(_optionalChain([scene, 'access',
|
|
1936
|
-
issues.push(
|
|
2138
|
+
const what = shot.at.beat !== void 0 ? `beat ${shot.at.beat}, but the scene has no beat grid; set one with set_animation_settings ({ "beat": { "bpm": \u2026 } })` : `word ${shot.at.word}, but the narration has ${_nullishCoalesce(_optionalChain([scene, 'access', _107 => _107.narration, 'optionalAccess', _108 => _108.words, 'access', _109 => _109.length]), () => ( 0))} words (indexes from 0)`;
|
|
2139
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-cue", `Shot "${shot.id}" is cued to ${what}.`, { shot: shot.id }));
|
|
1937
2140
|
} else if (timing.missedBy !== void 0) {
|
|
1938
2141
|
const late = Math.round(timing.missedBy);
|
|
1939
|
-
issues.push(
|
|
2142
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "cue-missed", `Shot "${shot.id}" is cued at ${Math.round(timing.cue)} ms but starts ${late} ms late, because the shot before runs until ${Math.round(timing.start)} ms; shorten that shot (its hold, durations or speed) or cue this one later.`, { shot: shot.id, measured: late, needed: 0, unit: "ms" }));
|
|
1940
2143
|
}
|
|
1941
2144
|
});
|
|
1942
2145
|
for (const [key, track] of timeline.tracks) {
|
|
@@ -1948,7 +2151,7 @@ function checkMotionScene(scene) {
|
|
|
1948
2151
|
const property = key.split("\0")[1];
|
|
1949
2152
|
if (!a.node) continue;
|
|
1950
2153
|
issues.push(
|
|
1951
|
-
|
|
2154
|
+
_chunkERJA5CGTcjs.motionIssue.call(void 0, "overlap", `"${a.node}" ${property} is changed by two commands at once (shot "${a.shot}" command ${a.command + 1} and shot "${b.shot}" command ${b.command + 1}); the later one takes over. Start it after the first ends, or use with: "after".`, {
|
|
1952
2155
|
shot: b.shot,
|
|
1953
2156
|
command: b.command,
|
|
1954
2157
|
ids: [a.node]
|
|
@@ -1965,26 +2168,26 @@ function checkMotionScene(scene) {
|
|
|
1965
2168
|
const cam = frame.camera;
|
|
1966
2169
|
const docIndex = indexMotionNodes(frame.document.nodes);
|
|
1967
2170
|
for (const id of command3.targets) {
|
|
1968
|
-
const b = _optionalChain([docIndex, 'access',
|
|
2171
|
+
const b = _optionalChain([docIndex, 'access', _110 => _110.get, 'call', _111 => _111(id), 'optionalAccess', _112 => _112.bounds]);
|
|
1969
2172
|
if (!b || reported.has(id) || !visibleAt(timeline, id, timing.end, nodes.get(id).node)) continue;
|
|
1970
2173
|
const outside = b.x + b.width < cam.x || b.y + b.height < cam.y || b.x > cam.x + cam.width || b.y > cam.y + cam.height;
|
|
1971
2174
|
if (outside) {
|
|
1972
2175
|
reported.add(id);
|
|
1973
|
-
issues.push(
|
|
2176
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "out-of-frame", `"${id}" is outside the camera when this ${command3.type} ends, so it is not seen; move it into frame or move the camera.`, { shot: timing.shot, command: timing.command, ids: [id] }));
|
|
1974
2177
|
}
|
|
1975
2178
|
}
|
|
1976
2179
|
}
|
|
1977
2180
|
if (scene.controls) {
|
|
1978
2181
|
for (const control of scene.controls) {
|
|
1979
2182
|
if (!usesColor(scene, control.default))
|
|
1980
|
-
issues.push(
|
|
2183
|
+
issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "unknown-control-color", `Control "${control.name}" stands for ${control.default}, which the scene never uses; set its default to a colour in the artwork.`));
|
|
1981
2184
|
}
|
|
1982
2185
|
}
|
|
1983
2186
|
if (scene.target && scene.shots.length) {
|
|
1984
2187
|
const seconds = Math.round(timeline.duration / 100) / 10;
|
|
1985
2188
|
const [min, max] = scene.target;
|
|
1986
|
-
if (seconds > max) issues.push(
|
|
1987
|
-
if (seconds < min) issues.push(
|
|
2189
|
+
if (seconds > max) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "scene-too-long", `The scene runs ${seconds} s, past its ${max} s target; shorten holds or durations, or fit it (fit_animation).`, { measured: seconds, needed: max, unit: "s" }));
|
|
2190
|
+
if (seconds < min) issues.push(_chunkERJA5CGTcjs.motionIssue.call(void 0, "scene-too-short", `The scene runs ${seconds} s, under its ${min} s target; hold longer, add shots, or fit it (fit_animation).`, { measured: seconds, needed: min, unit: "s" }));
|
|
1988
2191
|
}
|
|
1989
2192
|
return issues;
|
|
1990
2193
|
}
|
|
@@ -2013,7 +2216,7 @@ var fail = (message) => {
|
|
|
2013
2216
|
};
|
|
2014
2217
|
function shotIndex(scene, id) {
|
|
2015
2218
|
const i = scene.shots.findIndex((s) => s.id === id);
|
|
2016
|
-
if (i < 0) fail(`There is no shot ${
|
|
2219
|
+
if (i < 0) fail(`There is no shot ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, scene.shots.map((s) => s.id))}; the shots are ${scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
|
|
2017
2220
|
return i;
|
|
2018
2221
|
}
|
|
2019
2222
|
function position(at, length, what) {
|
|
@@ -2071,7 +2274,7 @@ function applyOne(scene, edit) {
|
|
|
2071
2274
|
if (typeof edit.name !== "string" || !edit.name) fail('Give the clip a "name".');
|
|
2072
2275
|
const clips = { ..._nullishCoalesce(scene.clips, () => ( {})) };
|
|
2073
2276
|
if (edit.clip === null) {
|
|
2074
|
-
if (!clips[edit.name]) fail(`There is no clip ${
|
|
2277
|
+
if (!clips[edit.name]) fail(`There is no clip ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, edit.name, Object.keys(clips))} to delete.`);
|
|
2075
2278
|
const playing = scene.shots.filter((s) => s.run.some((c) => c.type === "play" && c.clip === edit.name)).map((s) => `"${s.id}"`);
|
|
2076
2279
|
if (playing.length) fail(`Clip "${edit.name}" is played in shot${playing.length > 1 ? "s" : ""} ${playing.join(", ")}; remove those play commands first.`);
|
|
2077
2280
|
delete clips[edit.name];
|
|
@@ -2177,7 +2380,7 @@ function applyOne(scene, edit) {
|
|
|
2177
2380
|
const names = new Set(edit.controls.map((c) => c.name));
|
|
2178
2381
|
for (const preset2 of _nullishCoalesce(next.presets, () => ( [])))
|
|
2179
2382
|
for (const key of Object.keys(preset2.values))
|
|
2180
|
-
if (!names.has(key)) fail(`Preset "${preset2.name}" sets ${
|
|
2383
|
+
if (!names.has(key)) fail(`Preset "${preset2.name}" sets ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, key, names)}, which is not a control.`);
|
|
2181
2384
|
return next;
|
|
2182
2385
|
}
|
|
2183
2386
|
case "replace_scene":
|
|
@@ -2185,11 +2388,11 @@ function applyOne(scene, edit) {
|
|
|
2185
2388
|
}
|
|
2186
2389
|
}
|
|
2187
2390
|
function errorKeys(issues) {
|
|
2188
|
-
return new Set(issues.filter((i) => i.severity === "error").map(
|
|
2391
|
+
return new Set(issues.filter((i) => i.severity === "error").map(_chunkERJA5CGTcjs.motionIssueKey));
|
|
2189
2392
|
}
|
|
2190
2393
|
function editHints(before, after) {
|
|
2191
|
-
const old = new Set(before.map(
|
|
2192
|
-
return after.filter((i) => i.code === "overlap" && !old.has(
|
|
2394
|
+
const old = new Set(before.map(_chunkERJA5CGTcjs.motionIssueKey));
|
|
2395
|
+
return after.filter((i) => i.code === "overlap" && !old.has(_chunkERJA5CGTcjs.motionIssueKey.call(void 0, i))).map(_chunkERJA5CGTcjs.motionIssueLine);
|
|
2193
2396
|
}
|
|
2194
2397
|
function applyMotionEdits(scene, edits) {
|
|
2195
2398
|
const list = Array.isArray(edits) ? edits : [edits];
|
|
@@ -2197,9 +2400,9 @@ function applyMotionEdits(scene, edits) {
|
|
|
2197
2400
|
let next = scene;
|
|
2198
2401
|
for (let i = 0; i < list.length; i++) {
|
|
2199
2402
|
const edit = list[i];
|
|
2200
|
-
const prefix = list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess',
|
|
2403
|
+
const prefix = list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess', _113 => _113.op])}): ` : "";
|
|
2201
2404
|
if (!edit || !MOTION_EDIT_OPS.includes(edit.op))
|
|
2202
|
-
return { ok: false, error: `${prefix}Unknown op ${
|
|
2405
|
+
return { ok: false, error: `${prefix}Unknown op ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, String(_optionalChain([edit, 'optionalAccess', _114 => _114.op])), MOTION_EDIT_OPS)}. Nothing was changed.` };
|
|
2203
2406
|
try {
|
|
2204
2407
|
next = applyOne(next, edit);
|
|
2205
2408
|
} catch (error) {
|
|
@@ -2211,8 +2414,8 @@ function applyMotionEdits(scene, edits) {
|
|
|
2211
2414
|
}
|
|
2212
2415
|
const issues = checkMotionScene(next);
|
|
2213
2416
|
const had = errorKeys(before);
|
|
2214
|
-
const added = issues.filter((i) => i.severity === "error" && !had.has(
|
|
2215
|
-
if (added.length) return { ok: false, error: `Nothing was changed: ${added.map(
|
|
2417
|
+
const added = issues.filter((i) => i.severity === "error" && !had.has(_chunkERJA5CGTcjs.motionIssueKey.call(void 0, i)));
|
|
2418
|
+
if (added.length) return { ok: false, error: `Nothing was changed: ${added.map(_chunkERJA5CGTcjs.motionIssueLine).join(" ")}` };
|
|
2216
2419
|
return { ok: true, scene: next, issues, hints: editHints(before, issues) };
|
|
2217
2420
|
}
|
|
2218
2421
|
var REF = /^\$(\d+|last)((?:\.[A-Za-z_]\w*|\[\d+\])+)$/;
|
|
@@ -2221,7 +2424,7 @@ function resolveMotionEditRefs(scene, edits) {
|
|
|
2221
2424
|
const resolved = [];
|
|
2222
2425
|
let next = scene;
|
|
2223
2426
|
for (let i = 0; i < edits.length; i++) {
|
|
2224
|
-
const where = `op ${i + 1} (${_optionalChain([edits, 'access',
|
|
2427
|
+
const where = `op ${i + 1} (${_optionalChain([edits, 'access', _115 => _115[i], 'optionalAccess', _116 => _116.op])})`;
|
|
2225
2428
|
let problem = null;
|
|
2226
2429
|
const walk = (v) => {
|
|
2227
2430
|
if (typeof v === "string") {
|
|
@@ -2254,9 +2457,9 @@ function resolveMotionEditRefs(scene, edits) {
|
|
|
2254
2457
|
resolved.push(edit);
|
|
2255
2458
|
const out = { op: edit.op };
|
|
2256
2459
|
if (edit.op === "insert_shots") out.shots = edit.shots.map((s) => s.id);
|
|
2257
|
-
if ("shot" in edit && typeof edit.shot === "string") out.shot = edit.op === "update_shot" && _optionalChain([edit, 'access',
|
|
2460
|
+
if ("shot" in edit && typeof edit.shot === "string") out.shot = edit.op === "update_shot" && _optionalChain([edit, 'access', _117 => _117.set, 'optionalAccess', _118 => _118.id]) ? edit.set.id : edit.shot;
|
|
2258
2461
|
if (edit.op === "add_commands") {
|
|
2259
|
-
const at = _nullishCoalesce(_nullishCoalesce(edit.at, () => ( _optionalChain([before, 'access',
|
|
2462
|
+
const at = _nullishCoalesce(_nullishCoalesce(edit.at, () => ( _optionalChain([before, 'access', _119 => _119.shots, 'access', _120 => _120.find, 'call', _121 => _121((s) => s.id === edit.shot), 'optionalAccess', _122 => _122.run, 'access', _123 => _123.length]))), () => ( 0));
|
|
2260
2463
|
out.indexes = edit.commands.map((_, k) => at + k);
|
|
2261
2464
|
}
|
|
2262
2465
|
if (edit.op === "move_command") out.indexes = [edit.to];
|
|
@@ -2275,7 +2478,7 @@ function fitMotionScene(scene, ms2, options = {}) {
|
|
|
2275
2478
|
if (!(Number.isFinite(ms2) && ms2 > 0)) throw new Error("Give the length to fit as a number of milliseconds above 0.");
|
|
2276
2479
|
const ids = scene.shots.map((s) => s.id);
|
|
2277
2480
|
const keep = new Set(_nullishCoalesce(options.keep, () => ( [])));
|
|
2278
|
-
for (const id of keep) if (!ids.includes(id)) throw new Error(`There is no shot ${
|
|
2481
|
+
for (const id of keep) if (!ids.includes(id)) throw new Error(`There is no shot ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, ids)} to keep.`);
|
|
2279
2482
|
const timeline = compileMotionScene(scene);
|
|
2280
2483
|
let kept = 0;
|
|
2281
2484
|
let rest = 0;
|
|
@@ -2303,7 +2506,7 @@ var COLOR_GAP = 80;
|
|
|
2303
2506
|
var MAX_VIA = 64;
|
|
2304
2507
|
function motionNodePose(scene, id, time) {
|
|
2305
2508
|
const entry = indexMotionNodes(scene.artwork.nodes).get(id);
|
|
2306
|
-
if (!entry) throw new Error(`There is no element ${
|
|
2509
|
+
if (!entry) throw new Error(`There is no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, [...indexMotionNodes(scene.artwork.nodes).keys()])} in the artwork.`);
|
|
2307
2510
|
const timeline = compileMotionScene(scene);
|
|
2308
2511
|
const drawn = indexMotionNodes(motionFrameAt(scene, time).document.nodes).get(id);
|
|
2309
2512
|
const centre = _chunkBQE3Y6ZOcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
|
|
@@ -2321,7 +2524,7 @@ function motionNodePose(scene, id, time) {
|
|
|
2321
2524
|
...typeof fill === "string" && fill !== "transparent" ? { fill } : {},
|
|
2322
2525
|
...typeof stroke === "string" && stroke !== "transparent" ? { stroke } : {},
|
|
2323
2526
|
...typeof width === "number" ? { strokeWidth: width } : {},
|
|
2324
|
-
bounds: _nullishCoalesce(_optionalChain([drawn, 'optionalAccess',
|
|
2527
|
+
bounds: _nullishCoalesce(_optionalChain([drawn, 'optionalAccess', _124 => _124.bounds]), () => ( null))
|
|
2325
2528
|
};
|
|
2326
2529
|
}
|
|
2327
2530
|
function simplifyTimedSamples(times, values, tol) {
|
|
@@ -2356,7 +2559,7 @@ function simplifyTimedSamples(times, values, tol) {
|
|
|
2356
2559
|
keep.forEach((k, i) => k && out.push(i));
|
|
2357
2560
|
return out;
|
|
2358
2561
|
}
|
|
2359
|
-
var
|
|
2562
|
+
var round2 = (n, places = 2) => Math.round(n * 10 ** places) / 10 ** places || 0;
|
|
2360
2563
|
var ms = (n) => Math.max(0, Math.round(n));
|
|
2361
2564
|
function motionTakeProblems(scene, take) {
|
|
2362
2565
|
const problems = [];
|
|
@@ -2366,7 +2569,7 @@ function motionTakeProblems(scene, take) {
|
|
|
2366
2569
|
take.samples.forEach((s, i) => {
|
|
2367
2570
|
const where = `Sample ${i + 1}`;
|
|
2368
2571
|
if (!s || typeof s !== "object") return problems.push(`${where} must be an object.`);
|
|
2369
|
-
if (typeof s.node !== "string" || !nodes.has(s.node)) problems.push(`${where}: the artwork has no element ${
|
|
2572
|
+
if (typeof s.node !== "string" || !nodes.has(s.node)) problems.push(`${where}: the artwork has no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, String(s.node), [...nodes.keys()])}; get_animation lists the element ids.`);
|
|
2370
2573
|
if (!num2(s.t) || s.t < 0) problems.push(`${where}: "t" must be ms from the start of the take, \u2265 0.`);
|
|
2371
2574
|
if (s.x === void 0 !== (s.y === void 0)) problems.push(`${where}: give "x" and "y" together (the centre, document units).`);
|
|
2372
2575
|
for (const k of ["x", "y", "scaleX", "scaleY", "rotation", "opacity", "strokeWidth"]) if (s[k] !== void 0 && !num2(s[k])) problems.push(`${where}: "${k}" must be a number.`);
|
|
@@ -2416,15 +2619,15 @@ function channelCommands(node, channel, pose, samples, tol, kept) {
|
|
|
2416
2619
|
const base = { targets, duration: ms(duration), ease, ...extra };
|
|
2417
2620
|
switch (channel) {
|
|
2418
2621
|
case "move":
|
|
2419
|
-
return { type: "move", ...base, to: { x:
|
|
2622
|
+
return { type: "move", ...base, to: { x: round2(to[0]), y: round2(to[1]) } };
|
|
2420
2623
|
case "scale":
|
|
2421
|
-
return { type: "scale", ...base, to: Math.abs(to[0] - to[1]) < 1e-4 ?
|
|
2624
|
+
return { type: "scale", ...base, to: Math.abs(to[0] - to[1]) < 1e-4 ? round2(to[0], 4) : { x: round2(to[0], 4), y: round2(to[1], 4) } };
|
|
2422
2625
|
case "rotation":
|
|
2423
|
-
return { type: "rotate", ...base, to:
|
|
2626
|
+
return { type: "rotate", ...base, to: round2(to[0]) };
|
|
2424
2627
|
case "opacity":
|
|
2425
|
-
return { type: "fade", ...base, to:
|
|
2628
|
+
return { type: "fade", ...base, to: round2(to[0], 4) };
|
|
2426
2629
|
default:
|
|
2427
|
-
return { type: "style", ...base, strokeWidth:
|
|
2630
|
+
return { type: "style", ...base, strokeWidth: round2(to[0]) };
|
|
2428
2631
|
}
|
|
2429
2632
|
};
|
|
2430
2633
|
if (differs(list[0].v, rest)) {
|
|
@@ -2444,10 +2647,10 @@ function channelCommands(node, channel, pose, samples, tol, kept) {
|
|
|
2444
2647
|
const span = end.t - first.t;
|
|
2445
2648
|
const via = [];
|
|
2446
2649
|
for (const k of keep.slice(1, -1)) {
|
|
2447
|
-
const f =
|
|
2448
|
-
if (f > (_nullishCoalesce(_optionalChain([via, 'access',
|
|
2650
|
+
const f = round2((list[k].t - first.t) / span, 6);
|
|
2651
|
+
if (f > (_nullishCoalesce(_optionalChain([via, 'access', _125 => _125.at, 'call', _126 => _126(-1), 'optionalAccess', _127 => _127.f]), () => ( 0))) && f < 1) via.push({ s: list[k], f });
|
|
2449
2652
|
}
|
|
2450
|
-
const extra = via.length ? { via: via.map(({ s }) => ({ x:
|
|
2653
|
+
const extra = via.length ? { via: via.map(({ s }) => ({ x: round2(s.v[0]), y: round2(s.v[1]) })), times: via.map(({ f }) => f) } : {};
|
|
2451
2654
|
out.push({ start: first.t, command: make(end.v, span, "linear", extra) });
|
|
2452
2655
|
kept.n += via.length + 2;
|
|
2453
2656
|
return out;
|
|
@@ -2551,7 +2754,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2551
2754
|
const behaviors = _nullishCoalesce(options.behaviors, () => ( flairAtLeast(flair, "0.38")));
|
|
2552
2755
|
const springs = flairAtLeast(flair, "0.39");
|
|
2553
2756
|
const strobes = flairAtLeast(flair, "0.39");
|
|
2554
|
-
const writeEase = (ease) => typeof ease === "string" || "spring" in ease ? ease : ease.map(
|
|
2757
|
+
const writeEase = (ease) => typeof ease === "string" || "spring" in ease ? ease : ease.map(round4);
|
|
2555
2758
|
const easeOf2 = (segment) => {
|
|
2556
2759
|
const resolved = _chunkDWJJI6RTcjs.resolveEasing.call(void 0, segment.ease);
|
|
2557
2760
|
if (resolved !== "hold" && resolved.type === "spring") {
|
|
@@ -2564,8 +2767,8 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2564
2767
|
return back && curves ? flairCurveFor(back, curves) : void 0;
|
|
2565
2768
|
};
|
|
2566
2769
|
const plays = (s) => (!s.behavior || behaviors) && (!s.steps || strobes) && !s.geometric;
|
|
2567
|
-
const
|
|
2568
|
-
const f = (n) => String(
|
|
2770
|
+
const round4 = (n) => Math.round(n * 10 ** precision) / 10 ** precision;
|
|
2771
|
+
const f = (n) => String(round4(n));
|
|
2569
2772
|
const timeline = compileMotionScene(scene);
|
|
2570
2773
|
const nodes = indexMotionNodes(scene.artwork.nodes);
|
|
2571
2774
|
const notes = [];
|
|
@@ -2623,7 +2826,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2623
2826
|
const wrapper = freshId(`${id}--follow`);
|
|
2624
2827
|
const centre = freshId(`${id}--follow-centre`);
|
|
2625
2828
|
const c = entry.center;
|
|
2626
|
-
const at = _optionalChain([motionNodeOffset, 'call',
|
|
2829
|
+
const at = _optionalChain([motionNodeOffset, 'call', _128 => _128(entry, timeline, 0, nodes), 'optionalAccess', _129 => _129.follow]);
|
|
2627
2830
|
const placed = at ? `translate(${f(at.x)} ${f(at.y)})${at.angle ? ` rotate(${f(at.angle)})` : ""}` : void 0;
|
|
2628
2831
|
(wrap[id] ??= []).push({ id: wrapper, ...placed ? { transform: placed } : {} }, { id: centre, transform: `translate(${f(-c.x)} ${f(-c.y)})` });
|
|
2629
2832
|
follows.push({ id, wrapper, routes: ids, segments: followSegments.filter((seg) => seg.path && ids.has(seg.path)) });
|
|
@@ -2631,7 +2834,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2631
2834
|
}
|
|
2632
2835
|
const opacitySources = sourcesOf(id, ["opacity"]);
|
|
2633
2836
|
if (timeline.tracks.has(motionTrackKey(id, "opacity")) || opacitySources.length)
|
|
2634
|
-
channels.push({ id, kind: "attr", attr: "opacity", segments: [...track(id, "opacity"), ...opacitySources], exact: (s) => plays(s) && !drivenBy.has(s), value: (t) =>
|
|
2837
|
+
channels.push({ id, kind: "attr", attr: "opacity", segments: [...track(id, "opacity"), ...opacitySources], exact: (s) => plays(s) && !drivenBy.has(s), value: (t) => round4(motionPropertyValue(timeline, id, "opacity", t)) });
|
|
2635
2838
|
const followed = follows.some((x) => x.id === id);
|
|
2636
2839
|
const transformSegments = [...TRANSFORM_PROPS2.flatMap((p) => followed && p === "follow" ? [] : [...track(id, p), ..._nullishCoalesce(timeline.tracks.get(motionAddTrackKey(id, p)), () => ( []))]), ...sourcesOf(id, ["x", "y", "rotation", "scaleX", "scaleY"])];
|
|
2637
2840
|
if (transformSegments.length) {
|
|
@@ -2664,11 +2867,11 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2664
2867
|
paint("fill", "fill");
|
|
2665
2868
|
paint("stroke", "stroke");
|
|
2666
2869
|
const width = owner(path, "strokeWidth");
|
|
2667
|
-
if (width) channels.push({ id: path.id, kind: "attr", attr: "stroke-width", segments: [...track(width, "strokeWidth")], exact: () => true, value: (t) =>
|
|
2870
|
+
if (width) channels.push({ id: path.id, kind: "attr", attr: "stroke-width", segments: [...track(width, "strokeWidth")], exact: () => true, value: (t) => round4(Number(trackValue(track(width, "strokeWidth"), t))) });
|
|
2668
2871
|
const fade = owner(path, "fillOpacity");
|
|
2669
|
-
if (fade) channels.push({ id: path.id, kind: "attr", attr: "fill-opacity", segments: [...track(fade, "fillOpacity")], exact: () => true, value: (t) =>
|
|
2872
|
+
if (fade) channels.push({ id: path.id, kind: "attr", attr: "fill-opacity", segments: [...track(fade, "fillOpacity")], exact: () => true, value: (t) => round4(Number(trackValue(track(fade, "fillOpacity"), t))) });
|
|
2670
2873
|
const draw = owner(path, "drawEnd");
|
|
2671
|
-
if (draw) channels.push({ id: path.id, kind: "draw", segments: [...track(draw, "drawEnd")], exact: () => true, value: (t) =>
|
|
2874
|
+
if (draw) channels.push({ id: path.id, kind: "draw", segments: [...track(draw, "drawEnd")], exact: () => true, value: (t) => round4(Math.min(1, Math.max(0, Number(trackValue(track(draw, "drawEnd"), t))))) });
|
|
2672
2875
|
if (owner(path, "drawStart")) notes.push(`"${path.id}": drawing from a start other than 0 is not exported; Flair draws from the start of the path.`);
|
|
2673
2876
|
}
|
|
2674
2877
|
const shapeSegments = [...timeline.tracks.entries()].filter(([k]) => k.startsWith(`${id}\0`) && (k.endsWith("\0shape") || k.includes("\0effect:"))).flatMap(([, v]) => v);
|
|
@@ -2684,7 +2887,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2684
2887
|
exact: () => false,
|
|
2685
2888
|
value: (t) => {
|
|
2686
2889
|
const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
|
|
2687
|
-
const now = _chunkBQE3Y6ZOcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call',
|
|
2890
|
+
const now = _chunkBQE3Y6ZOcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _130 => _130(frame.document.nodes), 'access', _131 => _131.get, 'call', _132 => _132(id), 'optionalAccess', _133 => _133.node]));
|
|
2688
2891
|
if (!now || now.type !== "path") return "";
|
|
2689
2892
|
const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, now, _chunkBQE3Y6ZOcjs.IDENTITY_MATRIX, { effects: false }), inverse);
|
|
2690
2893
|
return _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
|
|
@@ -2694,7 +2897,26 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2694
2897
|
}
|
|
2695
2898
|
}
|
|
2696
2899
|
const camera = track("", "camera");
|
|
2697
|
-
|
|
2900
|
+
const windows = motionCameraWindows(scene, options.effects);
|
|
2901
|
+
const moveSegments = windows.map((w) => ({ node: "", property: "camera", start: w.start, end: w.end, from: [], to: [], ease: "linear", shot: w.shot, command: -1 }));
|
|
2902
|
+
const sampledMove = new WeakSet(moveSegments);
|
|
2903
|
+
const cameraValue = windows.length ? (t) => {
|
|
2904
|
+
const box = motionFrameAt(scene, t, { draw: false, offsets: false, effects: options.effects }).camera;
|
|
2905
|
+
return [box.x, box.y, box.width, box.height].map(round4);
|
|
2906
|
+
} : (t) => trackValue(camera, t).map(round4);
|
|
2907
|
+
if (camera.length || windows.length) channels.push({ id: "", kind: "view", segments: [...camera, ...moveSegments].sort((a, b) => a.start - b.start), exact: (seg) => !sampledMove.has(seg), overshoot: true, value: cameraValue });
|
|
2908
|
+
const cameraTag = (t) => {
|
|
2909
|
+
const w = windows.find((x) => t >= x.start - 1e-6 && t < x.end - 1e-6 && x.move);
|
|
2910
|
+
if (w) return `${w.move}@${w.shot}`;
|
|
2911
|
+
const seg = camera.find((x) => t >= x.start - 1e-6 && t < Math.max(x.end, x.start + 1e-3));
|
|
2912
|
+
const shot = seg ? scene.shots.find((x) => x.id === seg.shot) : void 0;
|
|
2913
|
+
const move = _optionalChain([_chunkOPSK22DLcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _134 => _134.camera, 'optionalAccess', _135 => _135.in])), 'optionalAccess', _136 => _136.move]);
|
|
2914
|
+
return move && shot ? `${move}@${shot.id}` : void 0;
|
|
2915
|
+
};
|
|
2916
|
+
const unplayed = scene.shots.filter((x) => x.camera && (x.camera.in !== void 0 || x.camera.during !== void 0) && !windows.some((w) => w.shot === x.id));
|
|
2917
|
+
if (unplayed.length)
|
|
2918
|
+
notes.push(`The camera moves of ${unplayed.map((x) => `"${x.id}"`).join(", ")} are written as eased framings, tagged with the move's id${options.effects ? " (the effects provider cannot play them)" : "; pass an effects provider with camera moves (options.effects) to sample them exactly"}.`);
|
|
2919
|
+
if (windows.length) notes.push("Camera moves are written as framings (the view box): their tilt, turn, roll and motion blur are not carried over to Flair.");
|
|
2698
2920
|
const animate = [];
|
|
2699
2921
|
let sampled = 0;
|
|
2700
2922
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
@@ -2702,12 +2924,16 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2702
2924
|
const written = writeEase(ease);
|
|
2703
2925
|
const base = {
|
|
2704
2926
|
...channel.id ? { id: channel.id } : {},
|
|
2705
|
-
...delay > 0 ? { delay:
|
|
2706
|
-
ms:
|
|
2927
|
+
...delay > 0 ? { delay: round4(delay) } : {},
|
|
2928
|
+
ms: round4(ms2),
|
|
2707
2929
|
ease: written,
|
|
2708
|
-
..._optionalChain([segment, 'optionalAccess',
|
|
2709
|
-
..._optionalChain([segment, 'optionalAccess',
|
|
2930
|
+
..._optionalChain([segment, 'optionalAccess', _137 => _137.behavior]) ? { behavior: segment.behavior } : {},
|
|
2931
|
+
..._optionalChain([segment, 'optionalAccess', _138 => _138.steps]) ? { strobe: segment.steps } : {}
|
|
2710
2932
|
};
|
|
2933
|
+
if (channel.kind === "view") {
|
|
2934
|
+
const tag2 = cameraTag(delay);
|
|
2935
|
+
if (tag2) base.tag = tag2;
|
|
2936
|
+
}
|
|
2711
2937
|
if (channel.kind === "view") animate.push({ ...base, view: to });
|
|
2712
2938
|
else if (channel.kind === "draw") animate.push({ ...base, draw: [from, to] });
|
|
2713
2939
|
else if (channel.kind === "attrs") {
|
|
@@ -2745,6 +2971,16 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2745
2971
|
const t0 = a + (b - a) * (k - 1) / n;
|
|
2746
2972
|
const t1 = a + (b - a) * k / n;
|
|
2747
2973
|
const next = channel.value(t1);
|
|
2974
|
+
const jump = channel.kind === "view" && active.some((x) => sampledMove.has(x)) ? viewJump(channel.value, t0, t1) : void 0;
|
|
2975
|
+
if (jump) {
|
|
2976
|
+
const [before, after] = [channel.value(jump - 1e-3), channel.value(jump)];
|
|
2977
|
+
emit(channel, t0, jump - t0, prev, before, "linear");
|
|
2978
|
+
emit(channel, jump, 0, before, after, "linear");
|
|
2979
|
+
if (!same(after, next)) emit(channel, jump, t1 - jump, after, next, "linear");
|
|
2980
|
+
sampled += 2;
|
|
2981
|
+
prev = next;
|
|
2982
|
+
continue;
|
|
2983
|
+
}
|
|
2748
2984
|
if (!same(prev, next)) {
|
|
2749
2985
|
emit(channel, t0, t1 - t0, prev, next, "linear");
|
|
2750
2986
|
sampled++;
|
|
@@ -2757,11 +2993,11 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2757
2993
|
const starts = follow.segments.map((seg) => seg.start);
|
|
2758
2994
|
for (const seg of follow.segments) {
|
|
2759
2995
|
const along = { id: follow.wrapper, along: follow.routes.get(seg.path), ...seg.rotate ? { orient: true } : {} };
|
|
2760
|
-
const progress = (t) =>
|
|
2996
|
+
const progress = (t) => round4(Math.min(1, Math.max(0, Number(segmentValue(seg, t)))));
|
|
2761
2997
|
const curve = seg.end > seg.start ? plays(seg) ? easeOf2(seg) : void 0 : "linear";
|
|
2762
2998
|
if (curve && !(overshoots(curve) && seg.rotate)) {
|
|
2763
2999
|
const ends = seg.reverse ? [Number(seg.to), Number(seg.from)] : [Number(seg.from), Number(seg.to)];
|
|
2764
|
-
animate.push({ ...along, ...seg.start > 0 ? { delay:
|
|
3000
|
+
animate.push({ ...along, ...seg.start > 0 ? { delay: round4(seg.start) } : {}, ms: round4(seg.end - seg.start), ease: writeEase(curve), ...seg.steps ? { strobe: seg.steps } : {}, at: [round4(ends[0]), round4(ends[1])] });
|
|
2765
3001
|
continue;
|
|
2766
3002
|
}
|
|
2767
3003
|
const until = Math.min(seg.end, ...starts.filter((t) => t > seg.start));
|
|
@@ -2769,7 +3005,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2769
3005
|
for (let k = 1; k <= n; k++) {
|
|
2770
3006
|
const t0 = seg.start + (until - seg.start) * (k - 1) / n;
|
|
2771
3007
|
const t1 = seg.start + (until - seg.start) * k / n;
|
|
2772
|
-
animate.push({ ...along, ...t0 > 0 ? { delay:
|
|
3008
|
+
animate.push({ ...along, ...t0 > 0 ? { delay: round4(t0) } : {}, ms: round4(t1 - t0), ease: "linear", at: [progress(t0), progress(t1)] });
|
|
2773
3009
|
sampled++;
|
|
2774
3010
|
}
|
|
2775
3011
|
}
|
|
@@ -2784,7 +3020,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2784
3020
|
timeline.shots.forEach((shot, i) => {
|
|
2785
3021
|
if (shot.start <= at + 1e-6) step = i;
|
|
2786
3022
|
});
|
|
2787
|
-
const delay =
|
|
3023
|
+
const delay = round4(at - timeline.shots[step].start);
|
|
2788
3024
|
delete a.delay;
|
|
2789
3025
|
if (delay > 0) a.delay = delay;
|
|
2790
3026
|
a.step = step + 1;
|
|
@@ -2796,7 +3032,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2796
3032
|
let svg = _chunkBQE3Y6ZOcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkBQE3Y6ZOcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
|
|
2797
3033
|
if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
|
|
2798
3034
|
let motion = { svg, animate };
|
|
2799
|
-
if (_optionalChain([scene, 'access',
|
|
3035
|
+
if (_optionalChain([scene, 'access', _139 => _139.controls, 'optionalAccess', _140 => _140.length])) {
|
|
2800
3036
|
const declarations = scene.controls.map((c) => `{{${c.name}: color default=${c.default.toUpperCase()}${c.label ? ` label='${c.label.replace(/'/g, "\u2019")}'` : ""}}}`).join(" ");
|
|
2801
3037
|
const swap = (text) => scene.controls.reduce((s, c) => s.replace(new RegExp(`${c.default}(?![0-9a-fA-F])`, "gi"), `{{${c.name}}}`), text);
|
|
2802
3038
|
svg = svg.replace(/^(<svg[^>]*>)/, `$1<!-- ${declarations} -->`);
|
|
@@ -2804,7 +3040,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2804
3040
|
svg = svg.slice(0, header) + swap(svg.slice(header));
|
|
2805
3041
|
motion = { svg, animate: animate.map((a) => a.attrs ? { ...a, attrs: Object.fromEntries(Object.entries(a.attrs).map(([k, [x, y]]) => [k, [typeof x === "string" ? swap(x) : x, typeof y === "string" ? swap(y) : y]])) } : a) };
|
|
2806
3042
|
}
|
|
2807
|
-
return { motion, duration: timeline.duration, hold: Math.max(0,
|
|
3043
|
+
return { motion, duration: timeline.duration, hold: Math.max(0, round4(timeline.duration - lastChange)), sampled, notes: [...new Set(notes)], ...trigger ? { trigger } : {} };
|
|
2808
3044
|
}
|
|
2809
3045
|
var kebab = (text) => text.trim().replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "animation";
|
|
2810
3046
|
function toFlairVectorEffect(scene, options = {}) {
|
|
@@ -2818,7 +3054,7 @@ function toFlairVectorEffect(scene, options = {}) {
|
|
|
2818
3054
|
tags: _nullishCoalesce(options.tags, () => ( [])),
|
|
2819
3055
|
motion: out.motion,
|
|
2820
3056
|
hold: out.hold,
|
|
2821
|
-
..._optionalChain([scene, 'access',
|
|
3057
|
+
..._optionalChain([scene, 'access', _141 => _141.presets, 'optionalAccess', _142 => _142.length]) ? { presets: scene.presets } : {},
|
|
2822
3058
|
...out.trigger ? { trigger: out.trigger } : {}
|
|
2823
3059
|
};
|
|
2824
3060
|
}
|
|
@@ -2836,6 +3072,20 @@ function toFlairEffectDocument(scene, options = {}) {
|
|
|
2836
3072
|
presets: _nullishCoalesce(scene.presets, () => ( []))
|
|
2837
3073
|
};
|
|
2838
3074
|
}
|
|
3075
|
+
function viewJump(value, t0, t1) {
|
|
3076
|
+
const box = (t) => value(t);
|
|
3077
|
+
const apart = (a2, b2) => Math.hypot(a2[0] + a2[2] / 2 - b2[0] - b2[2] / 2, a2[1] + a2[3] / 2 - b2[1] - b2[3] / 2, a2[2] - b2[2]);
|
|
3078
|
+
let lo = t0;
|
|
3079
|
+
let hi = t1;
|
|
3080
|
+
for (let i = 0; i < 40 && hi - lo > 1e-4; i++) {
|
|
3081
|
+
const mid = (lo + hi) / 2;
|
|
3082
|
+
if (apart(box(lo), box(mid)) >= apart(box(mid), box(hi))) hi = mid;
|
|
3083
|
+
else lo = mid;
|
|
3084
|
+
}
|
|
3085
|
+
const a = box(lo);
|
|
3086
|
+
const b = box(hi);
|
|
3087
|
+
return apart(a, b) > Math.min(a[2], b[2]) / 20 ? hi : void 0;
|
|
3088
|
+
}
|
|
2839
3089
|
|
|
2840
3090
|
// src/animation-editor/flair-import.ts
|
|
2841
3091
|
var PLACEHOLDER = /\{\{\s*([A-Za-z_]\w*)\s*(?::\s*([A-Za-z0-9]*)([^}]*))?\}\}/g;
|
|
@@ -2862,7 +3112,7 @@ function resolvePlaceholders(motion, notes) {
|
|
|
2862
3112
|
const filled = text.replace(PLACEHOLDER, (_, name) => {
|
|
2863
3113
|
const d = declared.get(name);
|
|
2864
3114
|
if (!d) unknown.add(name);
|
|
2865
|
-
return (_nullishCoalesce(_optionalChain([d, 'optionalAccess',
|
|
3115
|
+
return (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _143 => _143.value]), () => ( ""))).replace(/"/g, '\\"');
|
|
2866
3116
|
});
|
|
2867
3117
|
for (const name of unknown) notes.push(`Placeholder "{{${name}}}" has no declaration, so it was left empty.`);
|
|
2868
3118
|
return { motion: JSON.parse(filled), controls };
|
|
@@ -2916,7 +3166,7 @@ function commandsFor(anim, nodes, entered, notes) {
|
|
|
2916
3166
|
if (anim.along) {
|
|
2917
3167
|
const path = nodes.get(anim.along);
|
|
2918
3168
|
if (!path || path.node.type !== "path") notes.push(`${where} follows "${anim.along}", which is not a path in the artwork; the follow was skipped.`);
|
|
2919
|
-
else out.push({ type: "follow", targets, path: anim.along, from: _nullishCoalesce(_optionalChain([anim, 'access',
|
|
3169
|
+
else out.push({ type: "follow", targets, path: anim.along, from: _nullishCoalesce(_optionalChain([anim, 'access', _144 => _144.at, 'optionalAccess', _145 => _145[0]]), () => ( 0)), to: _nullishCoalesce(_optionalChain([anim, 'access', _146 => _146.at, 'optionalAccess', _147 => _147[1]]), () => ( 1)), ...anim.orient ? { rotate: true } : {}, ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
2920
3170
|
}
|
|
2921
3171
|
for (const [attr, [a, b]] of Object.entries(_nullishCoalesce(anim.attrs, () => ( {})))) {
|
|
2922
3172
|
if (attr === "opacity") {
|
|
@@ -2927,7 +3177,7 @@ function commandsFor(anim, nodes, entered, notes) {
|
|
|
2927
3177
|
out.push({ type: "enter", targets, style: "fade", ...timing, ...ease(MOTION_EASE_OUT) });
|
|
2928
3178
|
} else out.push({ type: "fade", targets, to: Math.min(1, Math.max(0, to)), ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
2929
3179
|
} else if (attr === "fill" || attr === "stroke") {
|
|
2930
|
-
if (_optionalChain([behavior, 'optionalAccess',
|
|
3180
|
+
if (_optionalChain([behavior, 'optionalAccess', _148 => _148.type]) === "pulse") out.push({ type: "color-pulse", targets, color: String(b), paint: attr, count: _nullishCoalesce(behavior.count, () => ( 1)), ...timing, ...ease("linear") });
|
|
2931
3181
|
else {
|
|
2932
3182
|
if (behavior) notes.push(`${where}: a ${attr} ${behavior.type} became a plain colour change.`);
|
|
2933
3183
|
out.push({ type: "style", targets, [attr]: String(b), ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
@@ -3050,7 +3300,7 @@ function rgba(color) {
|
|
|
3050
3300
|
const n = (i) => parseInt(hex.slice(i, i + 2), 16) / 255;
|
|
3051
3301
|
return [n(1), n(3), n(5), hex.length >= 9 ? parseInt(hex.slice(7, 9), 16) / 255 : 1];
|
|
3052
3302
|
}
|
|
3053
|
-
function lottieContours(path,
|
|
3303
|
+
function lottieContours(path, round4) {
|
|
3054
3304
|
const out = [];
|
|
3055
3305
|
let cur = null;
|
|
3056
3306
|
let px = 0;
|
|
@@ -3091,7 +3341,7 @@ function lottieContours(path, round3) {
|
|
|
3091
3341
|
}
|
|
3092
3342
|
}
|
|
3093
3343
|
if (cur) out.push(cur);
|
|
3094
|
-
return out.map((c) => ({ c: c.c, v: c.v.map((p) => p.map(
|
|
3344
|
+
return out.map((c) => ({ c: c.c, v: c.v.map((p) => p.map(round4)), i: c.i.map((p) => p.map(round4)), o: c.o.map((p) => p.map(round4)) }));
|
|
3095
3345
|
}
|
|
3096
3346
|
function staticParts(m) {
|
|
3097
3347
|
const sx = Math.hypot(m[0], m[1]);
|
|
@@ -3103,8 +3353,8 @@ function staticParts(m) {
|
|
|
3103
3353
|
function toLottie(scene, options = {}) {
|
|
3104
3354
|
const fps = _nullishCoalesce(_nullishCoalesce(options.fps, () => ( scene.fps)), () => ( 30));
|
|
3105
3355
|
const precision = _nullishCoalesce(options.precision, () => ( 3));
|
|
3106
|
-
const
|
|
3107
|
-
const frame = (ms2) =>
|
|
3356
|
+
const round4 = (n) => Math.round(n * 10 ** precision) / 10 ** precision;
|
|
3357
|
+
const frame = (ms2) => round4(ms2 * fps / 1e3);
|
|
3108
3358
|
const timeline = compileMotionScene(scene);
|
|
3109
3359
|
const nodes = indexMotionNodes(scene.artwork.nodes);
|
|
3110
3360
|
const notes = [];
|
|
@@ -3121,16 +3371,16 @@ function toLottie(scene, options = {}) {
|
|
|
3121
3371
|
return [e.x1, e.y1, e.x2, e.y2];
|
|
3122
3372
|
};
|
|
3123
3373
|
const animate = (segments, value, exact = true) => {
|
|
3124
|
-
const rest = value(0).map(
|
|
3374
|
+
const rest = value(0).map(round4);
|
|
3125
3375
|
if (!segments.length) return { a: 0, k: rest.length === 1 ? rest[0] : rest };
|
|
3126
3376
|
const keys = [];
|
|
3127
3377
|
const key = (t, v, ease) => {
|
|
3128
|
-
const k = { t: frame(t), s: v.map(
|
|
3378
|
+
const k = { t: frame(t), s: v.map(round4) };
|
|
3129
3379
|
if (ease === "hold") k.h = 1;
|
|
3130
3380
|
else {
|
|
3131
3381
|
const [x1, y1, x2, y2] = ease === "linear" || !ease ? [0, 0, 1, 1] : ease;
|
|
3132
|
-
k.o = { x: [
|
|
3133
|
-
k.i = { x: [
|
|
3382
|
+
k.o = { x: [round4(x1)], y: [round4(y1)] };
|
|
3383
|
+
k.i = { x: [round4(x2)], y: [round4(y2)] };
|
|
3134
3384
|
}
|
|
3135
3385
|
if (keys.length && keys[keys.length - 1].t === k.t) keys[keys.length - 1] = k;
|
|
3136
3386
|
else keys.push(k);
|
|
@@ -3178,7 +3428,7 @@ function toLottie(scene, options = {}) {
|
|
|
3178
3428
|
const poseTransform = (entry) => {
|
|
3179
3429
|
const id = entry.node.id;
|
|
3180
3430
|
const tr = STATIC_TR();
|
|
3181
|
-
const c = [entry.center.x, entry.center.y].map(
|
|
3431
|
+
const c = [entry.center.x, entry.center.y].map(round4);
|
|
3182
3432
|
const own = (p) => track(id, p);
|
|
3183
3433
|
const sources = motionDriverSources(timeline, id, ["x", "y", "rotation", "scaleX", "scaleY"]);
|
|
3184
3434
|
const layered = ["x", "y", "rotation", "scaleX", "scaleY"].some((p) => layers(id, p).length) || sources.length > 0;
|
|
@@ -3189,7 +3439,7 @@ function toLottie(scene, options = {}) {
|
|
|
3189
3439
|
tr.p = animate(mixed ? [...own("x"), ...own("y"), ...own("follow"), ...layers(id, "x"), ...layers(id, "y"), ...sources] : [...own("x"), ...own("y")], (t) => poseAt(entry, t).p, !mixed);
|
|
3190
3440
|
tr.r = animate(mixed ? [...own("rotation"), ...own("follow"), ...layers(id, "rotation"), ...sources] : own("rotation"), (t) => [poseAt(entry, t).r], !mixed);
|
|
3191
3441
|
tr.s = animate(mixed ? [...own("scaleX"), ...own("scaleY"), ...layers(id, "scaleX"), ...layers(id, "scaleY"), ...sources] : [...own("scaleX"), ...own("scaleY")], (t) => poseAt(entry, t).s, !mixed);
|
|
3192
|
-
if (tr.p.a === 0) tr.p = { a: 0, k: poseAt(entry, 0).p.map(
|
|
3442
|
+
if (tr.p.a === 0) tr.p = { a: 0, k: poseAt(entry, 0).p.map(round4) };
|
|
3193
3443
|
}
|
|
3194
3444
|
const opacitySources = motionDriverSources(timeline, id, ["opacity"]);
|
|
3195
3445
|
if (opacitySources.length) {
|
|
@@ -3198,7 +3448,7 @@ function toLottie(scene, options = {}) {
|
|
|
3198
3448
|
}
|
|
3199
3449
|
const opacity = own("opacity");
|
|
3200
3450
|
const rest = _nullishCoalesce(entry.node.opacity, () => ( 1));
|
|
3201
|
-
tr.o = opacity.length ? animate(opacity, (t) => [Math.min(1, Math.max(0, Number(_nullishCoalesce(trackValue(opacity, t), () => ( rest))))) * 100]) : { a: 0, k:
|
|
3451
|
+
tr.o = opacity.length ? animate(opacity, (t) => [Math.min(1, Math.max(0, Number(_nullishCoalesce(trackValue(opacity, t), () => ( rest))))) * 100]) : { a: 0, k: round4(rest * 100) };
|
|
3202
3452
|
return tr;
|
|
3203
3453
|
};
|
|
3204
3454
|
const owner = (path, p) => {
|
|
@@ -3217,10 +3467,10 @@ function toLottie(scene, options = {}) {
|
|
|
3217
3467
|
const shapeSegments = [...timeline.tracks.entries()].filter(([k]) => k.startsWith(`${path.id}\0`) && (k.endsWith("\0shape") || k.includes("\0effect:"))).flatMap(([, v]) => v);
|
|
3218
3468
|
const geometryAt = (t) => {
|
|
3219
3469
|
if (!shapeSegments.length) return _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, path);
|
|
3220
|
-
const now = _optionalChain([indexMotionNodes, 'call',
|
|
3470
|
+
const now = _optionalChain([indexMotionNodes, 'call', _149 => _149(motionFrameAt(scene, t, { draw: false, offsets: false }).document.nodes), 'access', _150 => _150.get, 'call', _151 => _151(path.id), 'optionalAccess', _152 => _152.node]);
|
|
3221
3471
|
return now && now.type === "path" ? _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, _chunkBQE3Y6ZOcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkBQE3Y6ZOcjs.vectorPathWorldBezier.call(void 0, path);
|
|
3222
3472
|
};
|
|
3223
|
-
const rest = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(0)),
|
|
3473
|
+
const rest = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(0)), round4);
|
|
3224
3474
|
rest.forEach((contour, n) => {
|
|
3225
3475
|
let ks = { a: 0, k: contour };
|
|
3226
3476
|
if (shapeSegments.length) {
|
|
@@ -3229,7 +3479,7 @@ function toLottie(scene, options = {}) {
|
|
|
3229
3479
|
const count = Math.max(1, Math.ceil(end * fps / 1e3));
|
|
3230
3480
|
for (let k = 0; k <= count && fits; k++) {
|
|
3231
3481
|
const t = end * k / count;
|
|
3232
|
-
const c = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(t)),
|
|
3482
|
+
const c = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(t)), round4)[n];
|
|
3233
3483
|
if (!c || c.v.length !== contour.v.length || c.c !== contour.c) fits = false;
|
|
3234
3484
|
else keys.push({ t: frame(t), s: [c], ...k < count ? { o: { x: [0], y: [0] }, i: { x: [1], y: [1] } } : {} });
|
|
3235
3485
|
}
|
|
@@ -3258,14 +3508,14 @@ function toLottie(scene, options = {}) {
|
|
|
3258
3508
|
items.push({
|
|
3259
3509
|
ty: "st",
|
|
3260
3510
|
nm: "Stroke",
|
|
3261
|
-
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( stroke)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(stroke, () => ( [0, 0, 0, 1]))).map(
|
|
3511
|
+
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( stroke)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(stroke, () => ( [0, 0, 0, 1]))).map(round4) },
|
|
3262
3512
|
o: { a: 0, k: 100 },
|
|
3263
|
-
w: widthFrom ? animate(track(widthFrom, "strokeWidth"), (t) => [Math.max(0, Number(_nullishCoalesce(_nullishCoalesce(trackValue(track(widthFrom, "strokeWidth"), t), () => ( path.strokeWidth)), () => ( 1))))]) : { a: 0, k:
|
|
3513
|
+
w: widthFrom ? animate(track(widthFrom, "strokeWidth"), (t) => [Math.max(0, Number(_nullishCoalesce(_nullishCoalesce(trackValue(track(widthFrom, "strokeWidth"), t), () => ( path.strokeWidth)), () => ( 1))))]) : { a: 0, k: round4(_nullishCoalesce(path.strokeWidth, () => ( 1))) },
|
|
3264
3514
|
lc: path.strokeLinecap === "round" ? 2 : path.strokeLinecap === "square" ? 3 : 1,
|
|
3265
3515
|
lj: path.strokeLinejoin === "round" ? 2 : path.strokeLinejoin === "bevel" ? 3 : 1,
|
|
3266
3516
|
ml: 4
|
|
3267
3517
|
});
|
|
3268
|
-
if (_optionalChain([path, 'access',
|
|
3518
|
+
if (_optionalChain([path, 'access', _153 => _153.strokeDasharray, 'optionalAccess', _154 => _154.length])) notes.push(`"${path.id}": its dashes are not exported; the stroke is solid.`);
|
|
3269
3519
|
if (path.strokeAlign && path.strokeAlign !== "center") notes.push(`"${path.id}": its stroke is drawn centred (Lottie has no inside or outside strokes).`);
|
|
3270
3520
|
}
|
|
3271
3521
|
const fill = paintOf(path.fill, "fill", path.id);
|
|
@@ -3275,7 +3525,7 @@ function toLottie(scene, options = {}) {
|
|
|
3275
3525
|
items.push({
|
|
3276
3526
|
ty: "fl",
|
|
3277
3527
|
nm: "Fill",
|
|
3278
|
-
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( fill)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(fill, () => ( [0, 0, 0, 1]))).map(
|
|
3528
|
+
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( fill)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(fill, () => ( [0, 0, 0, 1]))).map(round4) },
|
|
3279
3529
|
o: fade.length ? animate(fade, (t) => [Math.min(1, Math.max(0, Number(_nullishCoalesce(trackValue(fade, t), () => ( 1))))) * 100]) : { a: 0, k: 100 },
|
|
3280
3530
|
r: path.fillRule === "evenodd" ? 2 : 1
|
|
3281
3531
|
});
|
|
@@ -3301,9 +3551,9 @@ function toLottie(scene, options = {}) {
|
|
|
3301
3551
|
const parts = staticParts(m);
|
|
3302
3552
|
if (!parts) notes.push(`"${node.id}": its transform skews, which is not exported; it is drawn without the skew.`);
|
|
3303
3553
|
else {
|
|
3304
|
-
innerTr.p = { a: 0, k: parts.p.map(
|
|
3305
|
-
innerTr.s = { a: 0, k: parts.s.map(
|
|
3306
|
-
innerTr.r = { a: 0, k:
|
|
3554
|
+
innerTr.p = { a: 0, k: parts.p.map(round4) };
|
|
3555
|
+
innerTr.s = { a: 0, k: parts.s.map(round4) };
|
|
3556
|
+
innerTr.r = { a: 0, k: round4(parts.r) };
|
|
3307
3557
|
}
|
|
3308
3558
|
}
|
|
3309
3559
|
}
|
|
@@ -3313,7 +3563,7 @@ function toLottie(scene, options = {}) {
|
|
|
3313
3563
|
const artwork = { ...scene.artwork, nodes: _chunkBQE3Y6ZOcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
|
|
3314
3564
|
const content = shown(artwork.nodes).reverse().map(nodeGroup);
|
|
3315
3565
|
if (artwork.background && rgba(artwork.background))
|
|
3316
|
-
content.push({ ty: "gr", nm: "Background", it: [{ ty: "rc", nm: "Background", p: { a: 0, k: [artwork.width / 2, artwork.height / 2] }, s: { a: 0, k: [artwork.width, artwork.height] }, r: { a: 0, k: 0 } }, { ty: "fl", c: { a: 0, k: rgba(artwork.background).map(
|
|
3566
|
+
content.push({ ty: "gr", nm: "Background", it: [{ ty: "rc", nm: "Background", p: { a: 0, k: [artwork.width / 2, artwork.height / 2] }, s: { a: 0, k: [artwork.width, artwork.height] }, r: { a: 0, k: 0 } }, { ty: "fl", c: { a: 0, k: rgba(artwork.background).map(round4) }, o: { a: 0, k: 100 }, r: 1 }, STATIC_TR()] });
|
|
3317
3567
|
const camera = track("", "camera");
|
|
3318
3568
|
const root = STATIC_TR();
|
|
3319
3569
|
if (camera.length) {
|
|
@@ -3359,7 +3609,7 @@ var kids = (el, name) => el ? Array.from(el.children).filter((c) => c.localName
|
|
|
3359
3609
|
var kid = (el, name) => _nullishCoalesce(kids(el, name)[0], () => ( null));
|
|
3360
3610
|
var deep = (el, name) => el ? Array.from(el.getElementsByTagNameNS("*", name)) : [];
|
|
3361
3611
|
var num = (el, attr, fallback = 0) => {
|
|
3362
|
-
const v = _optionalChain([el, 'optionalAccess',
|
|
3612
|
+
const v = _optionalChain([el, 'optionalAccess', _155 => _155.getAttribute, 'call', _156 => _156(attr)]);
|
|
3363
3613
|
const n = v === null || v === void 0 ? NaN : Number(v);
|
|
3364
3614
|
return Number.isFinite(n) ? n : fallback;
|
|
3365
3615
|
};
|
|
@@ -3467,8 +3717,8 @@ function placement(xfrm, map) {
|
|
|
3467
3717
|
const ext = kid(xfrm, "ext");
|
|
3468
3718
|
const [x, y, w, h] = map(num(off, "x"), num(off, "y"), num(ext, "cx"), num(ext, "cy"));
|
|
3469
3719
|
const rot = num(xfrm, "rot") / 6e4 * (Math.PI / 180);
|
|
3470
|
-
const fx = _optionalChain([xfrm, 'optionalAccess',
|
|
3471
|
-
const fy = _optionalChain([xfrm, 'optionalAccess',
|
|
3720
|
+
const fx = _optionalChain([xfrm, 'optionalAccess', _157 => _157.getAttribute, 'call', _158 => _158("flipH")]) === "1" ? -1 : 1;
|
|
3721
|
+
const fy = _optionalChain([xfrm, 'optionalAccess', _159 => _159.getAttribute, 'call', _160 => _160("flipV")]) === "1" ? -1 : 1;
|
|
3472
3722
|
const cx = x + w / 2;
|
|
3473
3723
|
const cy = y + h / 2;
|
|
3474
3724
|
const cos = Math.cos(rot);
|
|
@@ -3495,7 +3745,7 @@ function shapes(ctx, tree, map) {
|
|
|
3495
3745
|
const nv = el.firstElementChild;
|
|
3496
3746
|
const cNvPr = kid(nv, "cNvPr");
|
|
3497
3747
|
const spid = num(cNvPr, "id", -1);
|
|
3498
|
-
const name = _nullishCoalesce(_optionalChain([cNvPr, 'optionalAccess',
|
|
3748
|
+
const name = _nullishCoalesce(_optionalChain([cNvPr, 'optionalAccess', _161 => _161.getAttribute, 'call', _162 => _162("name")]), () => ( ""));
|
|
3499
3749
|
if (el.localName === "grpSp") {
|
|
3500
3750
|
const xfrm = kid(kid(el, "grpSpPr"), "xfrm");
|
|
3501
3751
|
const off = kid(xfrm, "off");
|
|
@@ -3516,7 +3766,7 @@ function shapes(ctx, tree, map) {
|
|
|
3516
3766
|
if (el.localName !== "sp" && el.localName !== "cxnSp") continue;
|
|
3517
3767
|
const spPr = kid(el, "spPr");
|
|
3518
3768
|
const { w, h, transform } = placement(kid(spPr, "xfrm"), map);
|
|
3519
|
-
const prst = _optionalChain([kid, 'call',
|
|
3769
|
+
const prst = _optionalChain([kid, 'call', _163 => _163(spPr, "prstGeom"), 'optionalAccess', _164 => _164.getAttribute, 'call', _165 => _165("prst")]);
|
|
3520
3770
|
const cust = kid(spPr, "custGeom");
|
|
3521
3771
|
let subpaths = cust ? custom(cust, w, h) : prst ? preset(prst, w, h) : null;
|
|
3522
3772
|
if (!subpaths) {
|
|
@@ -3630,13 +3880,13 @@ function command(ctx, ctn, scene, artwork, target, hidden) {
|
|
|
3630
3880
|
}
|
|
3631
3881
|
if (cls === "path") {
|
|
3632
3882
|
const motion = deep(ctn, "animMotion")[0];
|
|
3633
|
-
const d = _optionalChain([motion, 'optionalAccess',
|
|
3883
|
+
const d = _optionalChain([motion, 'optionalAccess', _166 => _166.getAttribute, 'call', _167 => _167("path")]);
|
|
3634
3884
|
if (!d) return null;
|
|
3635
3885
|
const entry = artwork.flatMap(function all(n) {
|
|
3636
3886
|
return n.type === "group" ? [n, ...n.children.flatMap(all)] : [n];
|
|
3637
3887
|
}).find((n) => n.id === target);
|
|
3638
|
-
const t = _nullishCoalesce(_optionalChain([entry, 'optionalAccess',
|
|
3639
|
-
const p = _optionalChain([entry, 'optionalAccess',
|
|
3888
|
+
const t = _nullishCoalesce(_optionalChain([entry, 'optionalAccess', _168 => _168.transform]), () => ( [1, 0, 0, 1, 0, 0]));
|
|
3889
|
+
const p = _optionalChain([entry, 'optionalAccess', _169 => _169.type]) === "path" ? _optionalChain([entry, 'access', _170 => _170.subpaths, 'access', _171 => _171[0], 'optionalAccess', _172 => _172.anchors]) : void 0;
|
|
3640
3890
|
const xs = (_nullishCoalesce(p, () => ( []))).map((a) => a.x);
|
|
3641
3891
|
const ys = (_nullishCoalesce(p, () => ( []))).map((a) => a.y);
|
|
3642
3892
|
const lx = xs.length ? (Math.min(...xs) + Math.max(...xs)) / 2 : 0;
|
|
@@ -3688,9 +3938,9 @@ async function fromPptxAnimation(data, options = {}) {
|
|
|
3688
3938
|
if (!path.includes("theme/")) continue;
|
|
3689
3939
|
const theme = await xml(ctx, path);
|
|
3690
3940
|
const scheme = deep(theme, "clrScheme")[0];
|
|
3691
|
-
for (const c of Array.from(_nullishCoalesce(_optionalChain([scheme, 'optionalAccess',
|
|
3941
|
+
for (const c of Array.from(_nullishCoalesce(_optionalChain([scheme, 'optionalAccess', _173 => _173.children]), () => ( [])))) {
|
|
3692
3942
|
const v = c.firstElementChild;
|
|
3693
|
-
const hex = _optionalChain([v, 'optionalAccess',
|
|
3943
|
+
const hex = _optionalChain([v, 'optionalAccess', _174 => _174.localName]) === "srgbClr" ? v.getAttribute("val") : _optionalChain([v, 'optionalAccess', _175 => _175.getAttribute, 'call', _176 => _176("lastClr")]);
|
|
3694
3944
|
if (hex) ctx.theme.set(c.localName, `#${hex.toLowerCase()}`);
|
|
3695
3945
|
}
|
|
3696
3946
|
break;
|
|
@@ -3808,7 +4058,7 @@ function withoutMotionEffect(scene, instance) {
|
|
|
3808
4058
|
const shots = [];
|
|
3809
4059
|
for (const shot of scene.shots) {
|
|
3810
4060
|
const run = shot.run.filter((c, i) => {
|
|
3811
|
-
const mine = _optionalChain([sourceOf, 'call',
|
|
4061
|
+
const mine = _optionalChain([sourceOf, 'call', _177 => _177(c), 'optionalAccess', _178 => _178.instance]) === instance;
|
|
3812
4062
|
if (mine && !place) place = { shot: shot.id, index: i };
|
|
3813
4063
|
return !mine;
|
|
3814
4064
|
});
|
|
@@ -3828,7 +4078,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3828
4078
|
|
|
3829
4079
|
|
|
3830
4080
|
/** The effects provider slot (see `setEffectsProvider`). */
|
|
3831
|
-
__init() {this.effects = new (0,
|
|
4081
|
+
__init() {this.effects = new (0, _chunkOPSK22DLcjs.EffectsSlot)()}
|
|
3832
4082
|
|
|
3833
4083
|
|
|
3834
4084
|
__init2() {this.selection = null}
|
|
@@ -3895,7 +4145,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3895
4145
|
time: p.time,
|
|
3896
4146
|
playing: p.playing,
|
|
3897
4147
|
loop: p.loop,
|
|
3898
|
-
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call',
|
|
4148
|
+
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _179 => _179(timeline, p.time), 'optionalAccess', _180 => _180.id]), () => ( null)),
|
|
3899
4149
|
selection: this.selection,
|
|
3900
4150
|
readOnly: this.readOnly,
|
|
3901
4151
|
error: this.error,
|
|
@@ -3943,7 +4193,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3943
4193
|
this.applying = false;
|
|
3944
4194
|
}
|
|
3945
4195
|
this.notify();
|
|
3946
|
-
_optionalChain([this, 'access',
|
|
4196
|
+
_optionalChain([this, 'access', _181 => _181.onChange, 'optionalCall', _182 => _182(scene)]);
|
|
3947
4197
|
}
|
|
3948
4198
|
commit(label, next, merge) {
|
|
3949
4199
|
const before = this.scene;
|
|
@@ -4013,7 +4263,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4013
4263
|
try {
|
|
4014
4264
|
plan = await work();
|
|
4015
4265
|
} catch (error) {
|
|
4016
|
-
if (
|
|
4266
|
+
if (_chunkOPSK22DLcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
|
|
4017
4267
|
throw error;
|
|
4018
4268
|
}
|
|
4019
4269
|
const r = this.apply({ op: "replace_scene", scene: plan.scene }, plan.label, { merge });
|
|
@@ -4024,11 +4274,11 @@ var AnimationEditorController = (_class = class {
|
|
|
4024
4274
|
}
|
|
4025
4275
|
async describeFor(effect, kinds) {
|
|
4026
4276
|
const provider = this.effects.require();
|
|
4027
|
-
if (!provider.applyVectorEffect) throw new (0,
|
|
4277
|
+
if (!provider.applyVectorEffect) throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
|
|
4028
4278
|
const d = await provider.describe(effect);
|
|
4029
4279
|
if (!kinds.includes(d.kind)) {
|
|
4030
4280
|
const hint = d.kind === "motion" ? "apply it to nodes with apply_effect" : d.kind === "vector" ? "add it with add_vector_effect" : "it draws pixels, which scenes cannot hold";
|
|
4031
|
-
throw new (0,
|
|
4281
|
+
throw new (0, _chunkOPSK22DLcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
|
|
4032
4282
|
}
|
|
4033
4283
|
return d;
|
|
4034
4284
|
}
|
|
@@ -4049,7 +4299,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4049
4299
|
return this.effectEdit(async () => {
|
|
4050
4300
|
this.knownNodes(targets);
|
|
4051
4301
|
const d = await this.describeFor(effect, ["motion"]);
|
|
4052
|
-
const values =
|
|
4302
|
+
const values = _chunkOPSK22DLcjs.resolveEffectValues.call(void 0, d, options.values);
|
|
4053
4303
|
const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
|
|
4054
4304
|
const motion = await this.effects.require().applyVectorEffect(d.id, { svg: motionArtworkSvg(this.scene.artwork), nodeIds: [...targets] }, values);
|
|
4055
4305
|
const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
|
|
@@ -4071,7 +4321,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4071
4321
|
addVectorEffect(effect, options = {}) {
|
|
4072
4322
|
return this.effectEdit(async () => {
|
|
4073
4323
|
const d = await this.describeFor(effect, ["vector"]);
|
|
4074
|
-
const values =
|
|
4324
|
+
const values = _chunkOPSK22DLcjs.resolveEffectValues.call(void 0, d, options.values);
|
|
4075
4325
|
const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
|
|
4076
4326
|
const motion = await this.effects.require().applyVectorEffect(d.id, motionArtworkSvg(this.scene.artwork), values);
|
|
4077
4327
|
const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
|
|
@@ -4095,7 +4345,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4095
4345
|
else if (k in d.controls.properties) base[k] = d.defaults[k];
|
|
4096
4346
|
else throw new Error(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
|
|
4097
4347
|
}
|
|
4098
|
-
const merged = { ...base, ...
|
|
4348
|
+
const merged = { ...base, ..._chunkOPSK22DLcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
|
|
4099
4349
|
const { scene: bare, place } = withoutMotionEffect(this.scene, instance);
|
|
4100
4350
|
const provider = this.effects.require();
|
|
4101
4351
|
const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
|
|
@@ -4105,7 +4355,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4105
4355
|
const { group, shots: shots2, notes: notes2 } = motionPartsFromVectorEffect(bare.artwork, motion2, source);
|
|
4106
4356
|
const index = this.scene.artwork.nodes.findIndex((n) => n.id === instance);
|
|
4107
4357
|
const nodes = [...bare.artwork.nodes];
|
|
4108
|
-
nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess',
|
|
4358
|
+
nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess', _183 => _183.transform]) ? { ...group, transform: old.transform } : group);
|
|
4109
4359
|
const at = this.scene.shots.findIndex((s) => was.shots.includes(s.id));
|
|
4110
4360
|
const kept = bare.shots;
|
|
4111
4361
|
const nextShots = [...kept.slice(0, Math.max(0, at)), ...shots2, ...kept.slice(Math.max(0, at))];
|
|
@@ -4116,7 +4366,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4116
4366
|
let shots = bare.shots;
|
|
4117
4367
|
if (place && shots.some((s) => s.id === place.shot)) shots = shots.map((s) => s.id === place.shot ? { ...s, run: [...s.run.slice(0, place.index), ...commands, ...s.run.slice(place.index)] } : s);
|
|
4118
4368
|
else {
|
|
4119
|
-
const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess',
|
|
4369
|
+
const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess', _184 => _184.shot]));
|
|
4120
4370
|
shots = [...shots.slice(0, Math.max(0, at)), { id: instance, label: d.name, run: commands }, ...shots.slice(Math.max(0, at))];
|
|
4121
4371
|
}
|
|
4122
4372
|
return { scene: { ...bare, shots }, label: `Change ${d.name}`, instance, notes };
|
|
@@ -4129,6 +4379,64 @@ var AnimationEditorController = (_class = class {
|
|
|
4129
4379
|
const r = this.apply({ op: "replace_scene", scene: withoutMotionEffect(this.scene, instance).scene }, `Remove ${_nullishCoalesce(was.name, () => ( was.effect))}`);
|
|
4130
4380
|
return r.ok ? { ok: true, effect: was, notes: [] } : r;
|
|
4131
4381
|
}
|
|
4382
|
+
/**
|
|
4383
|
+
* The provider's camera moves for a role (`transition` for a shot's `camera.in`, `hold` for its
|
|
4384
|
+
* `camera.during`), or all of them. Empty without a provider that has camera moves.
|
|
4385
|
+
*/
|
|
4386
|
+
cameraMoves(role) {
|
|
4387
|
+
return motionCameraMoves(this.effects.provider, role);
|
|
4388
|
+
}
|
|
4389
|
+
/**
|
|
4390
|
+
* Sets the camera move a shot gets in with (`transition`, its `camera.in`) or plays while it
|
|
4391
|
+
* holds (`hold`, its `camera.during`). The move is checked against the provider first (its
|
|
4392
|
+
* role, preset and values; a preset's values are written out), then set in one undo step.
|
|
4393
|
+
* A shot with no camera gets one that keeps the framing. Returns the shot's camera and when the
|
|
4394
|
+
* move plays. `merge` folds a slider drag's changes into one undo step.
|
|
4395
|
+
*/
|
|
4396
|
+
async setShotCameraMove(shot, role, spec, options = {}) {
|
|
4397
|
+
const reason = this.readOnlyReason();
|
|
4398
|
+
if (reason) return this.refuse(reason);
|
|
4399
|
+
const found = this.scene.shots.find((s) => s.id === shot);
|
|
4400
|
+
if (!found) return this.refuse(`There is no shot "${shot}"; the shots are ${this.scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
|
|
4401
|
+
let resolved;
|
|
4402
|
+
try {
|
|
4403
|
+
resolved = await _chunkOPSK22DLcjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
|
|
4404
|
+
} catch (error) {
|
|
4405
|
+
if (_chunkOPSK22DLcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
|
|
4406
|
+
throw error;
|
|
4407
|
+
}
|
|
4408
|
+
const field = _chunkOPSK22DLcjs.cameraMoveField.call(void 0, role);
|
|
4409
|
+
const current = this.scene.shots.find((s) => s.id === shot);
|
|
4410
|
+
if (!current) return this.refuse(`Shot "${shot}" was removed while the move was checked.`);
|
|
4411
|
+
const parts = role === "transition" && resolved.spec.ms === void 0 ? { ...resolved.spec, ms: resolved.description.camera.durationMs } : resolved.spec;
|
|
4412
|
+
const simple = parts.ms === void 0 && parts.preset === void 0 && parts.values === void 0;
|
|
4413
|
+
const camera = { ..._nullishCoalesce(current.camera, () => ( {})), [field]: simple ? parts.move : parts };
|
|
4414
|
+
const r = this.apply({ op: "update_shot", shot, set: { camera } }, `${role === "hold" ? "Hold move" : "Camera move"} ${resolved.description.name}`, { merge: options.merge });
|
|
4415
|
+
if (!r.ok) return r;
|
|
4416
|
+
return this.cameraMoveResult(shot, role, resolved.description.id);
|
|
4417
|
+
}
|
|
4418
|
+
/** Removes a shot's camera move for a role, keeping its framing (a camera left with nothing is removed). One undo step. Works without a provider. */
|
|
4419
|
+
clearShotCameraMove(shot, role) {
|
|
4420
|
+
const found = this.scene.shots.find((s) => s.id === shot);
|
|
4421
|
+
if (!found) return this.refuse(`There is no shot "${shot}"; the shots are ${this.scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
|
|
4422
|
+
const field = _chunkOPSK22DLcjs.cameraMoveField.call(void 0, role);
|
|
4423
|
+
if (_optionalChain([found, 'access', _185 => _185.camera, 'optionalAccess', _186 => _186[field]]) === void 0) return this.refuse(`Shot "${shot}" has no camera "${field}" move to clear${_optionalChain([found, 'access', _187 => _187.camera, 'optionalAccess', _188 => _188[field === "in" ? "during" : "in"]]) !== void 0 ? `; it has a "${field === "in" ? "during" : "in"}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
|
|
4424
|
+
const rest = { ...found.camera };
|
|
4425
|
+
delete rest[field];
|
|
4426
|
+
const keep = motionCameraFramed(rest) || rest.in !== void 0 || rest.during !== void 0;
|
|
4427
|
+
const r = this.apply(keep ? { op: "update_shot", shot, set: { camera: rest } } : { op: "update_shot", shot, remove: ["camera"] }, role === "hold" ? "Clear hold move" : "Clear camera move");
|
|
4428
|
+
if (!r.ok) return r;
|
|
4429
|
+
return this.cameraMoveResult(shot, role);
|
|
4430
|
+
}
|
|
4431
|
+
cameraMoveResult(shot, role, move) {
|
|
4432
|
+
const timing = compileMotionScene(this.scene).shots.find((s) => s.id === shot);
|
|
4433
|
+
const camera = _nullishCoalesce(_optionalChain([this, 'access', _189 => _189.scene, 'access', _190 => _190.shots, 'access', _191 => _191.find, 'call', _192 => _192((s) => s.id === shot), 'optionalAccess', _193 => _193.camera]), () => ( null));
|
|
4434
|
+
const window = role === "transition" ? { start: timing.start, end: timing.commandsStart } : { start: timing.commandsEnd, end: timing.end };
|
|
4435
|
+
const notes = [];
|
|
4436
|
+
if (move && role === "transition" && timing.index === 0) notes.push('This is the first shot, which cuts to its framing, so its "in" move does not play; it plays from the second shot on.');
|
|
4437
|
+
if (move && !effectsPlayCamera(this.effects.provider)) notes.push("The provider cannot play camera moves, so the camera eases instead.");
|
|
4438
|
+
return { ok: true, shot, camera, ...move ? { window } : {}, notes };
|
|
4439
|
+
}
|
|
4132
4440
|
/** Opens a scene (JSON or object). `clearHistory` drops the undo stack (opening a file); otherwise it is one undo step. */
|
|
4133
4441
|
load(scene, options = {}) {
|
|
4134
4442
|
if (options.clearHistory) this.cancelRecording();
|
|
@@ -4193,13 +4501,13 @@ var AnimationEditorController = (_class = class {
|
|
|
4193
4501
|
viewScene() {
|
|
4194
4502
|
const r = this.recording;
|
|
4195
4503
|
if (!r) return this.scene;
|
|
4196
|
-
if (_optionalChain([r, 'access',
|
|
4504
|
+
if (_optionalChain([r, 'access', _194 => _194.preview, 'optionalAccess', _195 => _195.count]) === r.samples.length) return r.preview.scene;
|
|
4197
4505
|
let scene = this.scene;
|
|
4198
4506
|
if (r.samples.length) {
|
|
4199
4507
|
try {
|
|
4200
4508
|
const { shot, at } = motionTakeShot(this.scene, { samples: r.samples, length: Math.max(0, this.player.currentTime - r.start) }, r.options);
|
|
4201
4509
|
scene = { ...this.scene, shots: [...this.scene.shots.slice(0, at), shot, ...this.scene.shots.slice(at)] };
|
|
4202
|
-
} catch (
|
|
4510
|
+
} catch (e8) {
|
|
4203
4511
|
}
|
|
4204
4512
|
}
|
|
4205
4513
|
r.preview = { count: r.samples.length, scene };
|
|
@@ -4207,11 +4515,11 @@ var AnimationEditorController = (_class = class {
|
|
|
4207
4515
|
}
|
|
4208
4516
|
/** The scene at `time` (default: the playhead). */
|
|
4209
4517
|
frame(time = this.player.currentTime, options = {}) {
|
|
4210
|
-
return motionFrameAt(this.viewScene(), time, options);
|
|
4518
|
+
return motionFrameAt(this.viewScene(), time, { effects: this.effects.provider, ...options });
|
|
4211
4519
|
}
|
|
4212
4520
|
/** The scene at `time` (default: the playhead) as SVG. */
|
|
4213
4521
|
toSvg(time = this.player.currentTime, options = {}) {
|
|
4214
|
-
return motionStageSvg(this.viewScene(), time, options);
|
|
4522
|
+
return motionStageSvg(this.viewScene(), time, { effects: this.effects.provider, ...options });
|
|
4215
4523
|
}
|
|
4216
4524
|
// ---------------------------------------------------------------------------------------
|
|
4217
4525
|
// Recording
|
|
@@ -4278,13 +4586,13 @@ var AnimationEditorController = (_class = class {
|
|
|
4278
4586
|
}
|
|
4279
4587
|
/** Records the drag's pose with the pointer at `point` (document units). */
|
|
4280
4588
|
updateRecordGesture(point) {
|
|
4281
|
-
const g = _optionalChain([this, 'access',
|
|
4589
|
+
const g = _optionalChain([this, 'access', _196 => _196.recording, 'optionalAccess', _197 => _197.gesture]);
|
|
4282
4590
|
if (g) this.recordGesture(g.pose, point);
|
|
4283
4591
|
}
|
|
4284
4592
|
/** Ends the stage drag (the take keeps recording). */
|
|
4285
4593
|
endRecordGesture() {
|
|
4286
4594
|
const r = this.recording;
|
|
4287
|
-
if (!_optionalChain([r, 'optionalAccess',
|
|
4595
|
+
if (!_optionalChain([r, 'optionalAccess', _198 => _198.gesture])) return;
|
|
4288
4596
|
r.gesture = null;
|
|
4289
4597
|
this.notify();
|
|
4290
4598
|
}
|
|
@@ -4298,7 +4606,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4298
4606
|
this.recordSample(g.node, { scaleX: Math.max(0.01, pose.scaleX * f), scaleY: Math.max(0.01, pose.scaleY * f) });
|
|
4299
4607
|
} else {
|
|
4300
4608
|
const turn = (Math.atan2(point.y - c.y, point.x - c.x) - Math.atan2(g.from.y - c.y, g.from.x - c.x)) * (180 / Math.PI);
|
|
4301
|
-
const was = _nullishCoalesce(_optionalChain([this, 'access',
|
|
4609
|
+
const was = _nullishCoalesce(_optionalChain([this, 'access', _199 => _199.recording, 'access', _200 => _200.samples, 'access', _201 => _201.filter, 'call', _202 => _202((s) => s.node === g.node && s.rotation !== void 0), 'access', _203 => _203.at, 'call', _204 => _204(-1), 'optionalAccess', _205 => _205.rotation]), () => ( pose.rotation));
|
|
4302
4610
|
let next = pose.rotation + turn;
|
|
4303
4611
|
next += 360 * Math.round((was - next) / 360);
|
|
4304
4612
|
this.recordSample(g.node, { rotation: next });
|
|
@@ -4354,15 +4662,15 @@ var AnimationEditorController = (_class = class {
|
|
|
4354
4662
|
}
|
|
4355
4663
|
/** The scene as a Flair `SvgMotion`. */
|
|
4356
4664
|
toFlairMotion(options = {}) {
|
|
4357
|
-
return toFlairSvgMotion(this.scene, options);
|
|
4665
|
+
return toFlairSvgMotion(this.scene, { effects: this.effects.provider, ...options });
|
|
4358
4666
|
}
|
|
4359
4667
|
/** The scene as a Flair catalog vector effect. */
|
|
4360
4668
|
toFlairEffect(options = {}) {
|
|
4361
|
-
return toFlairVectorEffect(this.scene, options);
|
|
4669
|
+
return toFlairVectorEffect(this.scene, { effects: this.effects.provider, ...options });
|
|
4362
4670
|
}
|
|
4363
4671
|
/** The scene as a Flair `EffectDocument`. */
|
|
4364
4672
|
toFlairDocument(options = {}) {
|
|
4365
|
-
return toFlairEffectDocument(this.scene, options);
|
|
4673
|
+
return toFlairEffectDocument(this.scene, { effects: this.effects.provider, ...options });
|
|
4366
4674
|
}
|
|
4367
4675
|
}, _class);
|
|
4368
4676
|
|
|
@@ -4392,7 +4700,7 @@ function elementsOf(args) {
|
|
|
4392
4700
|
if (Array.isArray(args.ops)) {
|
|
4393
4701
|
for (const op of args.ops) {
|
|
4394
4702
|
fromShot(op);
|
|
4395
|
-
if (Array.isArray(_optionalChain([op, 'optionalAccess',
|
|
4703
|
+
if (Array.isArray(_optionalChain([op, 'optionalAccess', _206 => _206.shots]))) op.shots.forEach(fromShot);
|
|
4396
4704
|
}
|
|
4397
4705
|
}
|
|
4398
4706
|
return out.slice(0, 4);
|
|
@@ -4574,7 +4882,7 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
4574
4882
|
oneOf: MOTION_COMMAND_TYPES.map((type) => MOTION_COMMAND_TYPE_SCHEMAS[type])
|
|
4575
4883
|
};
|
|
4576
4884
|
var REF2 = (name, description) => ({ $ref: `#/$defs/${name}`, ...description ? { description } : {} });
|
|
4577
|
-
var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access',
|
|
4885
|
+
var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _207 => _207.exec, 'call', _208 => _208(text), 'optionalAccess', _209 => _209[0]]), () => ( text));
|
|
4578
4886
|
var COMMAND_TYPE_LINES = MOTION_COMMAND_TYPES.map((type) => `${type}: ${firstSentence(_nullishCoalesce(MOTION_COMMAND_TYPE_SCHEMAS[type].description, () => ( "")))}`);
|
|
4579
4887
|
var EASE_COMPACT = {
|
|
4580
4888
|
description: `Easing: a preset, or a curve { "type": "cubic-bezier", x1, y1, x2, y2 }, { "type": "spring", stiffness, damping, mass, velocity } (spring presets are Figma's; with no "duration" it lasts until it settles) or { "type": "elastic", amplitude, period, mode }. Default: ease-out for entrances, ease-in-out for moves.`,
|
|
@@ -4776,11 +5084,11 @@ function describeElement(node, ancestors) {
|
|
|
4776
5084
|
...effects.length ? { effects } : {}
|
|
4777
5085
|
};
|
|
4778
5086
|
}
|
|
4779
|
-
var
|
|
5087
|
+
var round3 = (n) => Math.round(n * 10) / 10;
|
|
4780
5088
|
function describeMotionElements(scene) {
|
|
4781
5089
|
return [...indexMotionNodes(scene.artwork.nodes).values()].map((e) => ({
|
|
4782
5090
|
...describeElement(e.node, e.ancestors),
|
|
4783
|
-
...e.bounds ? { bounds: { x:
|
|
5091
|
+
...e.bounds ? { bounds: { x: round3(e.bounds.x), y: round3(e.bounds.y), width: round3(e.bounds.width), height: round3(e.bounds.height) } } : {}
|
|
4784
5092
|
}));
|
|
4785
5093
|
}
|
|
4786
5094
|
function describeMotionShots(scene) {
|
|
@@ -4808,7 +5116,7 @@ var issueSummary = (issues) => ({
|
|
|
4808
5116
|
errors: issues.filter((i) => i.severity === "error").length,
|
|
4809
5117
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
4810
5118
|
notes: issues.filter((i) => i.severity === "note").length,
|
|
4811
|
-
lines: issues.map((i) => `${i.severity}: ${
|
|
5119
|
+
lines: issues.map((i) => `${i.severity}: ${_chunkERJA5CGTcjs.motionIssueLine.call(void 0, i)}`)
|
|
4812
5120
|
});
|
|
4813
5121
|
function createAnimationEditorToolProvider(controller, options = {}) {
|
|
4814
5122
|
const readOnlyReason = () => {
|
|
@@ -4872,7 +5180,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4872
5180
|
annotations: { title: "Describe command types", ...READ },
|
|
4873
5181
|
handler: ({ types }) => {
|
|
4874
5182
|
for (const type of types)
|
|
4875
|
-
if (!MOTION_COMMAND_TYPES.includes(type)) throw new Error(`There is no command type ${
|
|
5183
|
+
if (!MOTION_COMMAND_TYPES.includes(type)) throw new Error(`There is no command type ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, type, MOTION_COMMAND_TYPES)}; use one of ${MOTION_COMMAND_TYPES.join(", ")}.`);
|
|
4876
5184
|
return { commands: types.map((type) => ({ type, schema: MOTION_COMMAND_TYPE_SCHEMAS[type] })) };
|
|
4877
5185
|
}
|
|
4878
5186
|
};
|
|
@@ -4945,7 +5253,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4945
5253
|
}
|
|
4946
5254
|
if (Array.isArray(motion_paths)) {
|
|
4947
5255
|
const known = new Set(describeMotionElements(s).map((e) => e.id));
|
|
4948
|
-
for (const id of motion_paths) if (!known.has(id)) throw new Error(`There is no element ${
|
|
5256
|
+
for (const id of motion_paths) if (!known.has(id)) throw new Error(`There is no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, known)} to draw a motion path for.`);
|
|
4949
5257
|
}
|
|
4950
5258
|
const overlays = { ...onion_skin ? { onionSkin: onion_skin } : {}, ...motion_paths ? { motionPaths: motion_paths } : {} };
|
|
4951
5259
|
if (times) {
|
|
@@ -4983,9 +5291,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4983
5291
|
handler: ({ from = 0, to, limit = 200 }) => {
|
|
4984
5292
|
const s = scene();
|
|
4985
5293
|
const timeline = compileMotionScene(s);
|
|
4986
|
-
const words = _nullishCoalesce(_optionalChain([s, 'access',
|
|
5294
|
+
const words = _nullishCoalesce(_optionalChain([s, 'access', _210 => _210.narration, 'optionalAccess', _211 => _211.words]), () => ( []));
|
|
4987
5295
|
const end = _nullishCoalesce(to, () => ( Math.max(timeline.duration, words.length ? _nullishCoalesce(words[words.length - 1].end, () => ( words[words.length - 1].start)) : 0)));
|
|
4988
|
-
const shotAt = (ms2) => _optionalChain([timeline, 'access',
|
|
5296
|
+
const shotAt = (ms2) => _optionalChain([timeline, 'access', _212 => _212.shots, 'access', _213 => _213.find, 'call', _214 => _214((x) => ms2 >= x.start && ms2 < x.end), 'optionalAccess', _215 => _215.id]);
|
|
4989
5297
|
const beats = [];
|
|
4990
5298
|
if (s.beat && s.beat.bpm > 0) {
|
|
4991
5299
|
const first = Math.max(0, Math.ceil(motionBeatAt(s.beat, from).beat - 1e-9));
|
|
@@ -5015,7 +5323,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
5015
5323
|
handler: ({ group }) => {
|
|
5016
5324
|
const s = scene();
|
|
5017
5325
|
const nodes = indexMotionNodes(s.artwork.nodes);
|
|
5018
|
-
if (!nodes.has(group)) throw new Error(`There is no element ${
|
|
5326
|
+
if (!nodes.has(group)) throw new Error(`There is no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, group, [...nodes.keys()])}.`);
|
|
5019
5327
|
const layout = motionTextLayout(nodes, group);
|
|
5020
5328
|
if (!layout) throw new Error(`"${group}" is not a group of paths; convert the text to outlines (one path a letter) and group it.`);
|
|
5021
5329
|
return { group, letters: layout.lines.reduce((n, l) => n + l.words.reduce((m, w) => m + w.letters.length, 0), 0), ...layout };
|
|
@@ -5035,7 +5343,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
5035
5343
|
handler: ({ node, from, to, step }) => {
|
|
5036
5344
|
const s = scene();
|
|
5037
5345
|
const ids = describeMotionElements(s).map((e) => e.id);
|
|
5038
|
-
if (!ids.includes(node)) throw new Error(`There is no element ${
|
|
5346
|
+
if (!ids.includes(node)) throw new Error(`There is no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, node, ids)}.`);
|
|
5039
5347
|
return motionPath(s, node, { from, to, step });
|
|
5040
5348
|
}
|
|
5041
5349
|
};
|
|
@@ -5287,11 +5595,11 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
5287
5595
|
handler: ({ from, to, shots, stagger }) => {
|
|
5288
5596
|
const s = scene();
|
|
5289
5597
|
const ids = describeMotionElements(s).map((e) => e.id);
|
|
5290
|
-
for (const id of [from, ...to]) if (!ids.includes(id)) throw new Error(`There is no element ${
|
|
5598
|
+
for (const id of [from, ...to]) if (!ids.includes(id)) throw new Error(`There is no element ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, ids)}. Nothing was changed.`);
|
|
5291
5599
|
if (to.includes(from)) throw new Error(`"to" includes "${from}" itself; give other elements. Nothing was changed.`);
|
|
5292
5600
|
const only = shots ? new Set(shots) : null;
|
|
5293
5601
|
if (only) {
|
|
5294
|
-
for (const id of only) if (!s.shots.some((x) => x.id === id)) throw new Error(`There is no shot ${
|
|
5602
|
+
for (const id of only) if (!s.shots.some((x) => x.id === id)) throw new Error(`There is no shot ${_chunkERJA5CGTcjs.namedWithSuggestion.call(void 0, id, s.shots.map((x) => x.id))}. Nothing was changed.`);
|
|
5295
5603
|
}
|
|
5296
5604
|
const copied = {};
|
|
5297
5605
|
const edits = [];
|
|
@@ -5361,7 +5669,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
5361
5669
|
inputSchema: object({ shot: SHOT_ID, commands: { type: "array", items: REF2("command"), minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the run (default: the end)." } }, ["shot", "commands"]),
|
|
5362
5670
|
annotations: { title: "Add commands to a shot", ...WRITE },
|
|
5363
5671
|
handler: ({ shot, commands, at }) => {
|
|
5364
|
-
const before = _nullishCoalesce(_optionalChain([scene, 'call',
|
|
5672
|
+
const before = _nullishCoalesce(_optionalChain([scene, 'call', _216 => _216(), 'access', _217 => _217.shots, 'access', _218 => _218.find, 'call', _219 => _219((s) => s.id === shot), 'optionalAccess', _220 => _220.run, 'access', _221 => _221.length]), () => ( 0));
|
|
5365
5673
|
const first = _nullishCoalesce(at, () => ( before));
|
|
5366
5674
|
return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
|
|
5367
5675
|
const shots = describeMotionShots(s);
|
|
@@ -5562,7 +5870,7 @@ var TIMING = /* @__PURE__ */ new Set(["duration", "delay", "stagger", "with", "e
|
|
|
5562
5870
|
var COLORS = /* @__PURE__ */ new Set(["fill", "stroke", "color"]);
|
|
5563
5871
|
var NODES = /* @__PURE__ */ new Set(["into", "path"]);
|
|
5564
5872
|
function branch(type) {
|
|
5565
|
-
return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access',
|
|
5873
|
+
return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _222 => _222.properties, 'optionalAccess', _223 => _223.type, 'optionalAccess', _224 => _224.const]) === type);
|
|
5566
5874
|
}
|
|
5567
5875
|
function unitOf(type, name) {
|
|
5568
5876
|
if (name === "duration" || name === "delay" || name === "stagger") return "ms";
|
|
@@ -5597,7 +5905,7 @@ function kindOf(name, schema) {
|
|
|
5597
5905
|
}
|
|
5598
5906
|
function motionCommandFields(type) {
|
|
5599
5907
|
const schema = branch(type);
|
|
5600
|
-
if (!_optionalChain([schema, 'optionalAccess',
|
|
5908
|
+
if (!_optionalChain([schema, 'optionalAccess', _225 => _225.properties])) return [];
|
|
5601
5909
|
const required = new Set(_nullishCoalesce(schema.required, () => ( [])));
|
|
5602
5910
|
const fields = Object.entries(schema.properties).filter(([name]) => name !== "type").map(([name, s]) => {
|
|
5603
5911
|
const kind = kindOf(name, s);
|
|
@@ -5654,7 +5962,7 @@ function defaultMotionCommand(type, targets, scene) {
|
|
|
5654
5962
|
if (type === "wait") return { type: "wait", duration: 500 };
|
|
5655
5963
|
if (!targets.length) return { error: "Pick a target first: click an element on the stage." };
|
|
5656
5964
|
const nodes = [...indexMotionNodes(scene.artwork.nodes).values()];
|
|
5657
|
-
const other = (pred) => _optionalChain([nodes, 'access',
|
|
5965
|
+
const other = (pred) => _optionalChain([nodes, 'access', _226 => _226.find, 'call', _227 => _227((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _228 => _228.node, 'access', _229 => _229.id]);
|
|
5658
5966
|
const base = { targets: [...targets] };
|
|
5659
5967
|
switch (type) {
|
|
5660
5968
|
case "scale":
|
|
@@ -5685,8 +5993,8 @@ function defaultMotionCommand(type, targets, scene) {
|
|
|
5685
5993
|
}
|
|
5686
5994
|
case "effect": {
|
|
5687
5995
|
for (const id of targets) {
|
|
5688
|
-
const node = _optionalChain([nodes, 'access',
|
|
5689
|
-
for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess',
|
|
5996
|
+
const node = _optionalChain([nodes, 'access', _230 => _230.find, 'call', _231 => _231((e) => e.node.id === id), 'optionalAccess', _232 => _232.node]);
|
|
5997
|
+
for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _233 => _233.effects]), () => ( []))) {
|
|
5690
5998
|
const param = Object.entries(effect.params).find(([, v]) => typeof v === "number");
|
|
5691
5999
|
if (param) return { type, ...base, effect: effect.id, param: param[0], to: param[1] + 1 };
|
|
5692
6000
|
}
|
|
@@ -5711,11 +6019,11 @@ function motionCommandRows(scene, shotId) {
|
|
|
5711
6019
|
return scene.shots[index].run.map((command3, i) => {
|
|
5712
6020
|
const t = timeline.commands.find((c) => c.shotIndex === index && c.command === i);
|
|
5713
6021
|
const primitive = motionFlairPrimitive(command3);
|
|
5714
|
-
return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess',
|
|
6022
|
+
return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _234 => _234.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _235 => _235.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
|
|
5715
6023
|
});
|
|
5716
6024
|
}
|
|
5717
6025
|
function duplicateMotionCommandEdit(scene, shot, command3) {
|
|
5718
|
-
const run = _nullishCoalesce(_optionalChain([scene, 'access',
|
|
6026
|
+
const run = _nullishCoalesce(_optionalChain([scene, 'access', _236 => _236.shots, 'access', _237 => _237.find, 'call', _238 => _238((s) => s.id === shot), 'optionalAccess', _239 => _239.run]), () => ( []));
|
|
5719
6027
|
return { op: "add_commands", shot, commands: run[command3] ? [structuredClone(run[command3])] : [], at: command3 + 1 };
|
|
5720
6028
|
}
|
|
5721
6029
|
var MOTION_EASE_CHOICES = [
|
|
@@ -5800,7 +6108,7 @@ function motionCueFromKey(key) {
|
|
|
5800
6108
|
function motionCueChoices(scene, limit = 256) {
|
|
5801
6109
|
const choices = [];
|
|
5802
6110
|
const s = (ms2) => `${(ms2 / 1e3).toFixed(2)} s`;
|
|
5803
|
-
const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access',
|
|
6111
|
+
const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _240 => _240.narration, 'optionalAccess', _241 => _241.words, 'access', _242 => _242.map, 'call', _243 => _243((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
|
|
5804
6112
|
if (scene.beat && scene.beat.bpm > 0) {
|
|
5805
6113
|
for (let beat = 0; choices.length < limit; beat++) {
|
|
5806
6114
|
const time = motionBeatTime(scene.beat, beat);
|
|
@@ -5810,7 +6118,7 @@ function motionCueChoices(scene, limit = 256) {
|
|
|
5810
6118
|
choices.push({ value: `beat:${beat}`, label: `Beat ${beat} (bar ${at.bar}.${at.beatInBar}) \xB7 ${s(time)}`, time });
|
|
5811
6119
|
}
|
|
5812
6120
|
}
|
|
5813
|
-
_optionalChain([scene, 'access',
|
|
6121
|
+
_optionalChain([scene, 'access', _244 => _244.narration, 'optionalAccess', _245 => _245.words, 'access', _246 => _246.forEach, 'call', _247 => _247((w, i) => {
|
|
5814
6122
|
if (choices.length < limit * 2) choices.push({ value: `word:${i}`, label: `Word ${i} \u201C${w.text}\u201D \xB7 ${s(w.start)}`, time: w.start });
|
|
5815
6123
|
})]);
|
|
5816
6124
|
return choices;
|
|
@@ -5819,7 +6127,7 @@ function motionShotCueTime(scene, cue) {
|
|
|
5819
6127
|
return cue ? motionCueTime(scene, cue) : void 0;
|
|
5820
6128
|
}
|
|
5821
6129
|
function formatMotionNarration(narration) {
|
|
5822
|
-
return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess',
|
|
6130
|
+
return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _248 => _248.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
|
|
5823
6131
|
}
|
|
5824
6132
|
function parseMotionNarration(text) {
|
|
5825
6133
|
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
@@ -5856,6 +6164,71 @@ function parseMotionDrivers(text) {
|
|
|
5856
6164
|
return { drivers };
|
|
5857
6165
|
}
|
|
5858
6166
|
|
|
6167
|
+
// src/animation-editor/camera-tools.ts
|
|
6168
|
+
var ROLE = {
|
|
6169
|
+
type: "string",
|
|
6170
|
+
enum: ["transition", "hold"],
|
|
6171
|
+
description: `transition: the move the camera gets into the shot with (its camera "in": a glide, whip pan, punch zoom, cut). hold: the move it makes while the shot holds (its camera "during": a Ken Burns drift, a crash zoom), played across the shot's hold.`
|
|
6172
|
+
};
|
|
6173
|
+
var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {}, ..._optionalChain([e, 'access', _249 => _249.tags, 'optionalAccess', _250 => _250.length]) ? { tags: e.tags } : {} });
|
|
6174
|
+
var done = (r) => {
|
|
6175
|
+
if (!r.ok) throw new Error(r.error);
|
|
6176
|
+
return { shot: r.shot, camera: r.camera, ...r.window ? { window: r.window } : {}, ...r.notes.length ? { notes: r.notes } : {} };
|
|
6177
|
+
};
|
|
6178
|
+
function animationCameraMoveTools(controller, ctx) {
|
|
6179
|
+
return [
|
|
6180
|
+
{
|
|
6181
|
+
name: "list_camera_moves",
|
|
6182
|
+
title: "List camera moves",
|
|
6183
|
+
description: "Lists the effects provider's camera moves, for a role or both: { available, moves: [{ id, name, role, durationMs, cut (0\u20131 of the way through where the view jumps, for moves that cut), description, tags }] }. Use the ids with set_shot_camera_move (role transition for how the camera gets into a shot, hold for how it moves while the shot holds) and describe_effect for a move's controls and presets. Without a provider that has camera moves it returns available: false and the reason; the camera then eases between framings.",
|
|
6184
|
+
inputSchema: { type: "object", properties: { role: ROLE }, additionalProperties: false },
|
|
6185
|
+
annotations: { title: "List camera moves", ...ctx.annotations.read },
|
|
6186
|
+
handler: async (args) => {
|
|
6187
|
+
const provider = controller.effectsProvider;
|
|
6188
|
+
if (!effectsPlayCamera(provider)) return { available: false, reason: provider ? `${provider.name} has no camera moves (capabilities.supportsCamera is not set), so shots ease between framings.` : "No effects provider is registered, so there are no camera moves; shots ease between framings.", moves: [] };
|
|
6189
|
+
return { available: true, provider: provider.name, moves: (await controller.cameraMoves(args.role)).map(summary) };
|
|
6190
|
+
}
|
|
6191
|
+
},
|
|
6192
|
+
{
|
|
6193
|
+
name: "set_shot_camera_move",
|
|
6194
|
+
title: "Set a shot's camera move",
|
|
6195
|
+
description: `Sets the camera move a shot gets in with (role transition, its camera "in") or makes while it holds (role hold, its camera "during"), from list_camera_moves. The move is checked first: an id of the wrong role, an unknown preset or values outside its controls are refused with the moves or presets that fit. A shot with no camera gets one that keeps the framing; set the framing itself with update_shot. One undo step. Returns { shot, camera (the shot's camera now), window: { start, end } (ms when the move plays), notes }. The first shot cuts to its framing, so its transition does not play. A hold move plays across the shot's hold: lengthen it with update_shot (hold) for a slower move.`,
|
|
6196
|
+
inputSchema: {
|
|
6197
|
+
type: "object",
|
|
6198
|
+
properties: {
|
|
6199
|
+
shot: { type: "string", minLength: 1, description: "A shot id from get_animation." },
|
|
6200
|
+
role: ROLE,
|
|
6201
|
+
move: { type: "string", minLength: 1, description: "A camera move id of that role from list_camera_moves." },
|
|
6202
|
+
ms: { type: "number", minimum: 0, maximum: _chunkOPSK22DLcjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (0\u2013${_chunkOPSK22DLcjs.CAMERA_MOVE_MAX_MS}; default the move's durationMs). Not for a hold, which plays across the shot's hold.` },
|
|
6203
|
+
preset: { type: "string", minLength: 1, description: "A preset of the move by name, from describe_effect; its values are written out on the shot." },
|
|
6204
|
+
values: ctx.valuesSchema("Control values over the move's defaults (and the preset's), from describe_effect")
|
|
6205
|
+
},
|
|
6206
|
+
required: ["shot", "role", "move"],
|
|
6207
|
+
additionalProperties: false
|
|
6208
|
+
},
|
|
6209
|
+
annotations: { title: "Set a shot's camera move", ...ctx.annotations.writeIdempotent },
|
|
6210
|
+
handler: async (args) => {
|
|
6211
|
+
ctx.requireProvider();
|
|
6212
|
+
const spec = { move: args.move, ...args.ms !== void 0 ? { ms: args.ms } : {}, ...args.preset !== void 0 ? { preset: args.preset } : {}, ...args.values !== void 0 ? { values: args.values } : {} };
|
|
6213
|
+
return done(await controller.setShotCameraMove(args.shot, args.role, spec));
|
|
6214
|
+
}
|
|
6215
|
+
},
|
|
6216
|
+
{
|
|
6217
|
+
name: "clear_shot_camera_move",
|
|
6218
|
+
title: "Clear a shot's camera move",
|
|
6219
|
+
description: `Removes a shot's camera move for a role (transition: its camera "in"; hold: its camera "during"), keeping its framing; the camera then eases into the shot, or stays still while it holds. Works without a provider. One undo step. Returns { shot, camera (null when the shot has none left), notes }.`,
|
|
6220
|
+
inputSchema: {
|
|
6221
|
+
type: "object",
|
|
6222
|
+
properties: { shot: { type: "string", minLength: 1, description: "A shot id from get_animation." }, role: ROLE },
|
|
6223
|
+
required: ["shot", "role"],
|
|
6224
|
+
additionalProperties: false
|
|
6225
|
+
},
|
|
6226
|
+
annotations: { title: "Clear a shot's camera move", ...ctx.annotations.destructive },
|
|
6227
|
+
handler: async (args) => done(controller.clearShotCameraMove(args.shot, args.role))
|
|
6228
|
+
}
|
|
6229
|
+
];
|
|
6230
|
+
}
|
|
6231
|
+
|
|
5859
6232
|
// src/animation-editor/effect-tools.ts
|
|
5860
6233
|
var info = (e) => ({ id: e.instance, effect: e.effect, ...e.name ? { name: e.name } : {}, ...e.provider ? { provider: e.provider } : {}, role: e.kind === "vector" ? "vector picture" : "motion", enabled: true, values: e.values, targets: e.targets, shots: e.shots });
|
|
5861
6234
|
function createAnimationEffectsToolProvider(controller, options = {}) {
|
|
@@ -5864,11 +6237,11 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
|
|
|
5864
6237
|
if (ro) return typeof ro === "string" ? ro : "The animation is read-only.";
|
|
5865
6238
|
return controller.readOnlyReason();
|
|
5866
6239
|
};
|
|
5867
|
-
const
|
|
6240
|
+
const done2 = (r, target) => {
|
|
5868
6241
|
if (!r.ok) throw new Error(r.error);
|
|
5869
6242
|
return { target, effect: info(r.effect), effects: controller.appliedEffects().filter((e) => e.targets.includes(target)).map(info), ...r.notes.length ? { notes: r.notes } : {} };
|
|
5870
6243
|
};
|
|
5871
|
-
return withAnimationPlayback(
|
|
6244
|
+
return withAnimationPlayback(_chunkOPSK22DLcjs.createEffectToolProvider.call(void 0, {
|
|
5872
6245
|
id: _nullishCoalesce(options.id, () => ( "animation-effects")),
|
|
5873
6246
|
namespace: options.namespace,
|
|
5874
6247
|
title: "Animation effects",
|
|
@@ -5891,16 +6264,17 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
|
|
|
5891
6264
|
},
|
|
5892
6265
|
apply: async (target, effect, args) => {
|
|
5893
6266
|
if (args.index !== void 0 || args.opacity !== void 0 || args.enabled === false) throw new Error("index, opacity and enabled do not apply to motion effects; the effect becomes commands in a new shot.");
|
|
5894
|
-
return
|
|
6267
|
+
return done2(await controller.applyMotionEffect(effect, [target], { values: args.values }), target);
|
|
5895
6268
|
},
|
|
5896
6269
|
update: async (target, instance, changes) => {
|
|
5897
6270
|
const extra = ["enabled", "opacity", "index"].filter((k) => changes[k] !== void 0);
|
|
5898
6271
|
if (extra.length) throw new Error(`A motion effect only takes values; ${extra.join(", ")} do not apply (move or delete its commands with edit_animation).`);
|
|
5899
|
-
return
|
|
6272
|
+
return done2(await controller.updateMotionEffect(instance, _nullishCoalesce(changes.values, () => ( {}))), target);
|
|
5900
6273
|
},
|
|
5901
|
-
remove: async (target, instance) =>
|
|
6274
|
+
remove: async (target, instance) => done2(controller.removeMotionEffect(instance), target),
|
|
5902
6275
|
subscribe: (notify) => controller.subscribe(() => notify()),
|
|
5903
6276
|
extraTools: (ctx) => [
|
|
6277
|
+
...animationCameraMoveTools(controller, ctx),
|
|
5904
6278
|
{
|
|
5905
6279
|
name: "add_vector_effect",
|
|
5906
6280
|
title: "Add a vector effect",
|
|
@@ -6126,4 +6500,16 @@ function createAnimationEditorDocument(controller) {
|
|
|
6126
6500
|
|
|
6127
6501
|
|
|
6128
6502
|
|
|
6129
|
-
|
|
6503
|
+
|
|
6504
|
+
|
|
6505
|
+
|
|
6506
|
+
|
|
6507
|
+
|
|
6508
|
+
|
|
6509
|
+
|
|
6510
|
+
|
|
6511
|
+
|
|
6512
|
+
|
|
6513
|
+
|
|
6514
|
+
|
|
6515
|
+
exports.ANIMATION_EDITOR_AGENT_INSTRUCTIONS = ANIMATION_EDITOR_AGENT_INSTRUCTIONS; exports.AnimationEditorController = AnimationEditorController; exports.FLAIR_EASES = FLAIR_EASES; exports.FLAIR_EXPORT_VERSION = FLAIR_EXPORT_VERSION; exports.MOTION_ADDITIVE_PROPERTIES = MOTION_ADDITIVE_PROPERTIES; exports.MOTION_BLENDS = MOTION_BLENDS; exports.MOTION_CAMERA_MS = MOTION_CAMERA_MS; exports.MOTION_CASCADES = MOTION_CASCADES; exports.MOTION_CLIP_TARGET = MOTION_CLIP_TARGET; exports.MOTION_COMMAND_FIELDS = MOTION_COMMAND_FIELDS; exports.MOTION_COMMAND_SCHEMA = MOTION_COMMAND_SCHEMA; exports.MOTION_COMMAND_TYPES = MOTION_COMMAND_TYPES; exports.MOTION_COMMAND_TYPE_SCHEMAS = MOTION_COMMAND_TYPE_SCHEMAS; exports.MOTION_DEFAULT_DURATIONS = MOTION_DEFAULT_DURATIONS; exports.MOTION_DEFAULT_HOLD = MOTION_DEFAULT_HOLD; exports.MOTION_DIRECTIONS = MOTION_DIRECTIONS; exports.MOTION_DRAW_EFFECT_ID = MOTION_DRAW_EFFECT_ID; exports.MOTION_DRAW_MS_PER_UNIT = MOTION_DRAW_MS_PER_UNIT; exports.MOTION_DRAW_RANGE = MOTION_DRAW_RANGE; exports.MOTION_DRIVEN_PROPERTIES = MOTION_DRIVEN_PROPERTIES; exports.MOTION_EASE_CHOICES = MOTION_EASE_CHOICES; exports.MOTION_EASE_IN_OUT = MOTION_EASE_IN_OUT; exports.MOTION_EASE_OUT = MOTION_EASE_OUT; exports.MOTION_EDIT_OPS = MOTION_EDIT_OPS; exports.MOTION_ENTER_STYLES = MOTION_ENTER_STYLES; exports.MOTION_EXIT_STYLES = MOTION_EXIT_STYLES; exports.MOTION_IRIS_SHAPES = MOTION_IRIS_SHAPES; exports.MOTION_ISSUE_CODES = _chunkERJA5CGTcjs.MOTION_ISSUE_CODES; exports.MOTION_MAX_TAKE_MS = MOTION_MAX_TAKE_MS; exports.MOTION_MIN_CHANGE_MS = MOTION_MIN_CHANGE_MS; exports.MOTION_RECORD_GESTURE_MODES = MOTION_RECORD_GESTURE_MODES; exports.MOTION_REPEAT_MODES = MOTION_REPEAT_MODES; exports.MOTION_SPEED_RANGE = MOTION_SPEED_RANGE; exports.MOTION_SPLIT_ORIENTATIONS = MOTION_SPLIT_ORIENTATIONS; exports.MOTION_TEXT_STAGGER = MOTION_TEXT_STAGGER; exports.MOTION_TEXT_UNITS = MOTION_TEXT_UNITS; exports.MOTION_TRIGGERS = MOTION_TRIGGERS; exports.MotionSceneFormatError = MotionSceneFormatError; exports.activeSegment = activeSegment; exports.animationCameraMoveTools = animationCameraMoveTools; exports.applyMotionControlValues = applyMotionControlValues; exports.applyMotionDrivers = applyMotionDrivers; exports.applyMotionEdits = applyMotionEdits; exports.checkMotionCameraMoves = checkMotionCameraMoves; exports.checkMotionScene = checkMotionScene; exports.clipsShapeProblems = clipsShapeProblems; exports.commandShapeProblems = commandShapeProblems; exports.compileMotionScene = compileMotionScene; exports.createAnimationEditorDocument = createAnimationEditorDocument; exports.createAnimationEditorToolProvider = createAnimationEditorToolProvider; exports.createAnimationEffectsToolProvider = createAnimationEffectsToolProvider; exports.createMotionScene = createMotionScene; exports.defaultMotionCommand = defaultMotionCommand; exports.describeMotionElements = describeMotionElements; exports.describeMotionShots = describeMotionShots; exports.driversShapeProblems = driversShapeProblems; exports.duplicateMotionCommandEdit = duplicateMotionCommandEdit; exports.effectsPlayCamera = effectsPlayCamera; exports.fitMotionRect = fitMotionRect; exports.fitMotionScene = fitMotionScene; exports.fitMotionSceneEdits = fitMotionSceneEdits; exports.flairAtLeast = flairAtLeast; exports.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.formatMotionDrivers = formatMotionDrivers; exports.formatMotionNarration = formatMotionNarration; exports.freshShotId = freshShotId; exports.fromFlairSvgMotion = fromFlairSvgMotion; exports.fromFlairVectorEffect = fromFlairVectorEffect; exports.fromPptxAnimation = fromPptxAnimation; exports.highlightMotionSvg = highlightMotionSvg; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.matchMotionNodes = matchMotionNodes; exports.motionAddTrackKey = motionAddTrackKey; exports.motionArtworkSvg = motionArtworkSvg; exports.motionBeatAt = motionBeatAt; exports.motionBeatTime = motionBeatTime; exports.motionBlurTimes = motionBlurTimes; exports.motionCameraBox = motionCameraBox; exports.motionCameraFramed = motionCameraFramed; exports.motionCameraMoves = motionCameraMoves; exports.motionCameraStage = motionCameraStage; exports.motionCameraTransform = motionCameraTransform; exports.motionCameraViewAt = motionCameraViewAt; exports.motionCameraWindows = motionCameraWindows; exports.motionCascade = motionCascade; exports.motionClientToDocument = motionClientToDocument; exports.motionClipAttrs = motionClipAttrs; exports.motionClipLayout = motionClipLayout; exports.motionCommandDuration = motionCommandDuration; exports.motionCommandFields = motionCommandFields; exports.motionCommandRepeat = motionCommandRepeat; exports.motionCommandRows = motionCommandRows; exports.motionCommandSlots = motionCommandSlots; exports.motionCommandSummary = motionCommandSummary; exports.motionCommandsFromEffect = motionCommandsFromEffect; exports.motionContactSheetSvg = motionContactSheetSvg; exports.motionCueChoices = motionCueChoices; exports.motionCueFromKey = motionCueFromKey; exports.motionCueKey = motionCueKey; exports.motionCueTime = motionCueTime; exports.motionCycleDuration = motionCycleDuration; exports.motionDrivenNodes = motionDrivenNodes; exports.motionDriverSources = motionDriverSources; exports.motionEaseKey = motionEaseKey; exports.motionEasingCurve = motionEasingCurve; exports.motionEasingGuides = motionEasingGuides; exports.motionEasingPath = motionEasingPath; exports.motionFieldEdit = motionFieldEdit; exports.motionFieldLabel = motionFieldLabel; exports.motionFlairPrimitive = motionFlairPrimitive; exports.motionFollowRoute = motionFollowRoute; exports.motionFrameAt = motionFrameAt; exports.motionFrameToSvg = motionFrameToSvg; exports.motionGhosts = motionGhosts; exports.motionIssue = _chunkERJA5CGTcjs.motionIssue; exports.motionIssueKey = _chunkERJA5CGTcjs.motionIssueKey; exports.motionIssueLine = _chunkERJA5CGTcjs.motionIssueLine; exports.motionMovingIds = motionMovingIds; exports.motionNodeAtElement = motionNodeAtElement; exports.motionNodeClips = motionNodeClips; exports.motionNodeOffset = motionNodeOffset; exports.motionNodePose = motionNodePose; exports.motionPartsFromVectorEffect = motionPartsFromVectorEffect; exports.motionPath = motionPath; exports.motionPathLength = motionPathLength; exports.motionPathsSvg = motionPathsSvg; exports.motionPropertyValue = motionPropertyValue; exports.motionRestValue = motionRestValue; exports.motionRevealClip = motionRevealClip; exports.motionRevealPadding = motionRevealPadding; exports.motionRulerTicks = motionRulerTicks; exports.motionSceneEffects = motionSceneEffects; exports.motionSceneShapeProblems = motionSceneShapeProblems; exports.motionSceneToJson = motionSceneToJson; exports.motionShotAt = motionShotAt; exports.motionShotCameraMove = motionShotCameraMove; exports.motionShotCueTime = motionShotCueTime; exports.motionShotTimeScale = motionShotTimeScale; exports.motionStageSvg = motionStageSvg; exports.motionTakeProblems = motionTakeProblems; exports.motionTakeShot = motionTakeShot; exports.motionTextLayout = motionTextLayout; exports.motionTextUnits = motionTextUnits; exports.motionTrackKey = motionTrackKey; exports.namedWithSuggestion = _chunkERJA5CGTcjs.namedWithSuggestion; exports.nextMotionEffectInstance = nextMotionEffectInstance; exports.parseMotionDrivers = parseMotionDrivers; exports.parseMotionFieldInput = parseMotionFieldInput; exports.parseMotionNarration = parseMotionNarration; exports.parseMotionScene = parseMotionScene; exports.planAnimationToolPlayback = planAnimationToolPlayback; exports.resolveMotionCamera = resolveMotionCamera; exports.resolveMotionEditRefs = resolveMotionEditRefs; exports.segmentProgress = segmentProgress; exports.segmentValue = segmentValue; exports.shotShapeProblems = shotShapeProblems; exports.simplifyTimedSamples = simplifyTimedSamples; exports.smoothMotionLegs = smoothMotionLegs; exports.smoothMotionTimes = smoothMotionTimes; exports.suggestName = _chunkERJA5CGTcjs.suggestName; exports.toFlairEffectDocument = toFlairEffectDocument; exports.toFlairSvgMotion = toFlairSvgMotion; exports.toFlairVectorEffect = toFlairVectorEffect; exports.toLottie = toLottie; exports.trackValue = trackValue; exports.withAnimationPlayback = withAnimationPlayback; exports.withCameraViewEffects = withCameraViewEffects; exports.withMotionLayers = withMotionLayers; exports.withViewBox = withViewBox; exports.withoutMotionEffect = withoutMotionEffect;
|