@pixerate/editor 0.58.0 → 0.60.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/agent/index.cjs +111 -38
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +30 -2
- package/dist/agent/index.d.ts +30 -2
- package/dist/agent/index.js +96 -23
- package/dist/agent/index.js.map +1 -1
- package/dist/agent-caret-BmYhQF7L.d.cts +106 -0
- package/dist/agent-caret-BmYhQF7L.d.ts +106 -0
- package/dist/animation/index.cjs +9 -3
- package/dist/animation/index.cjs.map +1 -1
- package/dist/animation/index.d.cts +2 -2
- package/dist/animation/index.d.ts +2 -2
- package/dist/animation/index.js +9 -3
- package/dist/animation-editor/index.cjs +535 -124
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +239 -9
- package/dist/animation-editor/index.d.ts +239 -9
- package/dist/animation-editor/index.js +494 -83
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/canvas/index.cjs +35 -29
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +4 -4
- package/dist/canvas/index.d.ts +4 -4
- package/dist/canvas/index.js +9 -3
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-O4ONBPZW.cjs → chunk-2FGRTYJN.cjs} +4 -4
- package/dist/{chunk-O4ONBPZW.cjs.map → chunk-2FGRTYJN.cjs.map} +1 -1
- package/dist/{chunk-XZ4L3R4K.cjs → chunk-2FHLHZAL.cjs} +39 -3
- package/dist/chunk-2FHLHZAL.cjs.map +1 -0
- package/dist/{chunk-PYMV7HLI.js → chunk-3TLL5OID.js} +2 -2
- package/dist/{chunk-LMUDHBWR.js → chunk-4YFMSPBU.js} +2 -2
- package/dist/{chunk-3I6V7PI4.cjs → chunk-7ZSU4MQZ.cjs} +45 -45
- package/dist/{chunk-3I6V7PI4.cjs.map → chunk-7ZSU4MQZ.cjs.map} +1 -1
- package/dist/{chunk-UB2OY7FD.js → chunk-AGR4P4UZ.js} +38 -2
- package/dist/chunk-AGR4P4UZ.js.map +1 -0
- package/dist/{chunk-SHOVAHUB.js → chunk-JK6M6V7G.js} +2 -2
- package/dist/{chunk-WLVZ235X.js → chunk-OK7T2LHK.js} +229 -2
- package/dist/chunk-OK7T2LHK.js.map +1 -0
- package/dist/{chunk-AHCENCU4.cjs → chunk-T4XWVPJK.cjs} +253 -26
- package/dist/chunk-T4XWVPJK.cjs.map +1 -0
- package/dist/{chunk-FKONE6AO.cjs → chunk-YJLCBA7V.cjs} +3 -3
- package/dist/{chunk-FKONE6AO.cjs.map → chunk-YJLCBA7V.cjs.map} +1 -1
- package/dist/{easing-CNGk-W6d.d.ts → easing-lM0Xo9Ni.d.cts} +14 -2
- package/dist/{easing-CNGk-W6d.d.cts → easing-lM0Xo9Ni.d.ts} +14 -2
- package/dist/extensions/index.cjs +27 -3
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +2 -1
- package/dist/extensions/index.d.ts +2 -1
- package/dist/extensions/index.js +26 -2
- package/dist/{index-CTCc3m3C.d.ts → index-B16wbOn_.d.ts} +1 -0
- package/dist/{index-BcHyG0Wq.d.cts → index-BAt14aIU.d.cts} +1 -0
- package/dist/index.cjs +32 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/parameters/index.cjs +2 -2
- package/dist/parameters/index.d.cts +1 -1
- package/dist/parameters/index.d.ts +1 -1
- package/dist/parameters/index.js +1 -1
- package/dist/{player-W-5DX3Go.d.ts → player-DV4Jujdq.d.ts} +1 -1
- package/dist/{player-Dg0FT0UI.d.cts → player-DrcP2xqj.d.cts} +1 -1
- package/dist/vector/index.cjs +472 -472
- package/dist/vector/index.d.cts +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-AHCENCU4.cjs.map +0 -1
- package/dist/chunk-UB2OY7FD.js.map +0 -1
- package/dist/chunk-WLVZ235X.js.map +0 -1
- package/dist/chunk-XZ4L3R4K.cjs.map +0 -1
- /package/dist/{chunk-PYMV7HLI.js.map → chunk-3TLL5OID.js.map} +0 -0
- /package/dist/{chunk-LMUDHBWR.js.map → chunk-4YFMSPBU.js.map} +0 -0
- /package/dist/{chunk-SHOVAHUB.js.map → chunk-JK6M6V7G.js.map} +0 -0
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
var _chunkYJLCBA7Vcjs = require('../chunk-YJLCBA7V.cjs');
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
|
|
@@ -33,7 +34,7 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
|
|
|
33
34
|
var _chunkZCNLBRT6cjs = require('../chunk-ZCNLBRT6.cjs');
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
var
|
|
37
|
+
var _chunk2FGRTYJNcjs = require('../chunk-2FGRTYJN.cjs');
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
var _chunkMR3Z4OQIcjs = require('../chunk-MR3Z4OQI.cjs');
|
|
@@ -47,7 +48,9 @@ var _chunkA6PHCAGXcjs = require('../chunk-A6PHCAGX.cjs');
|
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
var _chunk2FHLHZALcjs = require('../chunk-2FHLHZAL.cjs');
|
|
51
54
|
|
|
52
55
|
// src/animation-editor/types.ts
|
|
53
56
|
var MOTION_COMMAND_TYPES = [
|
|
@@ -71,6 +74,8 @@ var MOTION_COMMAND_TYPES = [
|
|
|
71
74
|
"wait"
|
|
72
75
|
];
|
|
73
76
|
var MOTION_ENTER_STYLES = ["fade", "pop", "grow", "slide", "draw", "zoom", "rise", "wipe", "iris", "split"];
|
|
77
|
+
var MOTION_BLENDS = ["replace", "add"];
|
|
78
|
+
var MOTION_REPEAT_MODES = ["loop", "mirror", "offset"];
|
|
74
79
|
var MOTION_EXIT_STYLES = ["fade", "shrink", "slide", "undraw", "wipe"];
|
|
75
80
|
var MOTION_IRIS_SHAPES = ["circle", "box"];
|
|
76
81
|
var MOTION_SPLIT_ORIENTATIONS = ["horizontal", "vertical"];
|
|
@@ -139,6 +144,7 @@ var MOTION_ISSUE_CODES = {
|
|
|
139
144
|
"exit-hidden": { severity: "warning", wording: "A node exits or animates while it is hidden." },
|
|
140
145
|
"out-of-frame": { severity: "warning", wording: "A node a command animates ends up outside the camera." },
|
|
141
146
|
"too-fast": { severity: "warning", wording: "A change is too quick to follow." },
|
|
147
|
+
"spring-cut-short": { severity: "warning", wording: "A spring is given a duration shorter than it takes to settle, so it jumps to its end." },
|
|
142
148
|
"scene-too-long": { severity: "warning", wording: "The scene runs past its target length." },
|
|
143
149
|
"scene-too-short": { severity: "warning", wording: "The scene ends before its target length." },
|
|
144
150
|
"unknown-control-color": { severity: "warning", wording: "A control stands for a colour the scene never uses." },
|
|
@@ -196,26 +202,26 @@ ${problems.map((p) => `- ${p}`).join("\n")}`);
|
|
|
196
202
|
this.problems = problems;
|
|
197
203
|
}
|
|
198
204
|
};
|
|
199
|
-
var SCENE_KEYS = ["version", "name", "description", "artwork", "shots", "loop", "fps", "target", "controls", "presets"];
|
|
205
|
+
var SCENE_KEYS = ["version", "name", "description", "artwork", "shots", "loop", "fps", "steps", "target", "controls", "presets"];
|
|
200
206
|
var SHOT_KEYS = ["id", "label", "camera", "run", "hold"];
|
|
201
|
-
var CAMERA_KEYS = ["x", "y", "width", "height", "frame", "padding", "ease", "ms"];
|
|
202
|
-
var BASE_KEYS = ["type", "targets", "duration", "delay", "stagger", "with", "ease", "note"];
|
|
207
|
+
var CAMERA_KEYS = ["x", "y", "width", "height", "frame", "padding", "ease", "ms", "geometric"];
|
|
208
|
+
var BASE_KEYS = ["type", "targets", "duration", "delay", "stagger", "with", "ease", "note", "repeat", "repeatMode", "steps"];
|
|
203
209
|
var COMMAND_KEYS = {
|
|
204
210
|
enter: [...BASE_KEYS, "style", "direction", "distance", "scale", "shape", "orientation"],
|
|
205
211
|
exit: [...BASE_KEYS, "style", "direction", "distance"],
|
|
206
212
|
draw: [...BASE_KEYS, "from", "to"],
|
|
207
|
-
move: [...BASE_KEYS, "by", "to"],
|
|
208
|
-
rotate: [...BASE_KEYS, "by", "to"],
|
|
209
|
-
scale: [...BASE_KEYS, "to"],
|
|
213
|
+
move: [...BASE_KEYS, "by", "to", "blend"],
|
|
214
|
+
rotate: [...BASE_KEYS, "by", "to", "blend"],
|
|
215
|
+
scale: [...BASE_KEYS, "to", "geometric", "blend"],
|
|
210
216
|
fade: [...BASE_KEYS, "to"],
|
|
211
217
|
style: [...BASE_KEYS, "fill", "stroke", "strokeWidth"],
|
|
212
218
|
morph: [...BASE_KEYS, "into"],
|
|
213
219
|
follow: [...BASE_KEYS, "path", "rotate", "from", "to"],
|
|
214
|
-
pulse: [...BASE_KEYS, "amount", "count"],
|
|
215
|
-
shake: [...BASE_KEYS, "amount", "count", "axis"],
|
|
216
|
-
teeter: [...BASE_KEYS, "angle", "count"],
|
|
217
|
-
wave: [...BASE_KEYS, "amount", "count"],
|
|
218
|
-
wiggle: [...BASE_KEYS, "amount", "frequency", "octaves", "rotate", "seed"],
|
|
220
|
+
pulse: [...BASE_KEYS, "amount", "count", "blend"],
|
|
221
|
+
shake: [...BASE_KEYS, "amount", "count", "axis", "blend"],
|
|
222
|
+
teeter: [...BASE_KEYS, "angle", "count", "blend"],
|
|
223
|
+
wave: [...BASE_KEYS, "amount", "count", "blend"],
|
|
224
|
+
wiggle: [...BASE_KEYS, "amount", "frequency", "octaves", "rotate", "seed", "blend"],
|
|
219
225
|
"color-pulse": [...BASE_KEYS, "color", "paint", "count"],
|
|
220
226
|
effect: [...BASE_KEYS, "effect", "param", "to"],
|
|
221
227
|
wait: ["type", "duration", "with", "note"]
|
|
@@ -254,7 +260,14 @@ function commandShapeProblems(command2, where) {
|
|
|
254
260
|
nonNegative("duration");
|
|
255
261
|
nonNegative("delay");
|
|
256
262
|
nonNegative("stagger");
|
|
257
|
-
if (command2.ease !== void 0 && !
|
|
263
|
+
if (command2.ease !== void 0 && !_chunk2FHLHZALcjs.isAnimationEasing.call(void 0, command2.ease)) p(`"ease" is not an easing; use a preset such as "ease-in-out" or "spring-bouncy", or { "type": "cubic-bezier", \u2026 } or { "type": "spring", \u2026 }.`);
|
|
264
|
+
if (command2.repeat !== void 0) {
|
|
265
|
+
if (type === "enter" || type === "exit") p(`"repeat" is not for ${type} (it brings things in or out once); repeat an emphasis or a move instead.`);
|
|
266
|
+
else if (!(Number.isInteger(command2.repeat) && command2.repeat >= 1 && command2.repeat <= 1e3)) p(`"repeat" must be a whole number from 1 to 1000.`);
|
|
267
|
+
}
|
|
268
|
+
if (command2.blend !== void 0 && !MOTION_BLENDS.includes(command2.blend)) p(`"blend" must be "replace" (the change takes over) or "add" (a layer on top).`);
|
|
269
|
+
if (command2.repeatMode !== void 0 && !MOTION_REPEAT_MODES.includes(command2.repeatMode)) p(`"repeatMode" must be one of ${MOTION_REPEAT_MODES.join(", ")}.`);
|
|
270
|
+
if (command2.steps !== void 0 && !(isNum(command2.steps) && command2.steps > 0 && command2.steps <= 120)) p(`"steps" must be frames per second from above 0 to 120 (12 holds each pose for two frames at 24 fps).`);
|
|
258
271
|
switch (type) {
|
|
259
272
|
case "enter":
|
|
260
273
|
case "exit": {
|
|
@@ -286,6 +299,7 @@ function commandShapeProblems(command2, where) {
|
|
|
286
299
|
break;
|
|
287
300
|
case "scale":
|
|
288
301
|
if (!(isNum(command2.to) || isPoint(command2.to))) p(`"to" must be a number or { "x": number, "y": number }.`);
|
|
302
|
+
if (command2.geometric !== void 0 && typeof command2.geometric !== "boolean") p(`"geometric" must be true or false.`);
|
|
289
303
|
break;
|
|
290
304
|
case "fade":
|
|
291
305
|
if (!(isNum(command2.to) && command2.to >= 0 && command2.to <= 1)) p(`"to" must be an opacity from 0 to 1.`);
|
|
@@ -349,8 +363,9 @@ function shotShapeProblems(shot, where) {
|
|
|
349
363
|
if (typeof c.frame === "string") {
|
|
350
364
|
if (c.padding !== void 0 && !isNum(c.padding)) problems.push(`${name} camera: "padding" must be a number.`);
|
|
351
365
|
} else if (!isRect) problems.push(`${name} camera: give { x, y, width, height } or { frame: "<node id>" }.`);
|
|
352
|
-
if (c.ease !== void 0 && !
|
|
366
|
+
if (c.ease !== void 0 && !_chunk2FHLHZALcjs.isAnimationEasing.call(void 0, c.ease)) problems.push(`${name} camera: "ease" is not an easing.`);
|
|
353
367
|
if (c.ms !== void 0 && !(isNum(c.ms) && c.ms >= 0)) problems.push(`${name} camera: "ms" must be a number \u2265 0.`);
|
|
368
|
+
if (c.geometric !== void 0 && typeof c.geometric !== "boolean") problems.push(`${name} camera: "geometric" must be true or false.`);
|
|
354
369
|
}
|
|
355
370
|
}
|
|
356
371
|
if (!Array.isArray(shot.run)) problems.push(`${name}: "run" must be a list of commands (it may be empty).`);
|
|
@@ -369,6 +384,7 @@ function motionSceneShapeProblems(input) {
|
|
|
369
384
|
problems.push('Scene: "artwork" must be a vector document { width, height, nodes }.');
|
|
370
385
|
if (input.loop !== void 0 && !["none", "loop", "ping-pong"].includes(input.loop)) problems.push('Scene: "loop" must be "none", "loop" or "ping-pong".');
|
|
371
386
|
if (input.fps !== void 0 && !(isNum(input.fps) && input.fps > 0 && input.fps <= 120)) problems.push('Scene: "fps" must be a number from 1 to 120.');
|
|
387
|
+
if (input.steps !== void 0 && !(isNum(input.steps) && input.steps > 0 && input.steps <= 120)) problems.push('Scene: "steps" must be frames per second from above 0 to 120.');
|
|
372
388
|
if (input.target !== void 0 && !(Array.isArray(input.target) && input.target.length === 2 && input.target.every(isNum) && input.target[0] <= input.target[1]))
|
|
373
389
|
problems.push('Scene: "target" must be [min, max] seconds.');
|
|
374
390
|
if (input.controls !== void 0) {
|
|
@@ -412,21 +428,21 @@ function indexMotionNodes(nodes) {
|
|
|
412
428
|
const out = /* @__PURE__ */ new Map();
|
|
413
429
|
const walk = (list, parentWorld, ancestors) => {
|
|
414
430
|
for (const node of list) {
|
|
415
|
-
const local =
|
|
416
|
-
const bounds =
|
|
431
|
+
const local = _chunkYJLCBA7Vcjs.vectorNodeBounds.call(void 0, node);
|
|
432
|
+
const bounds = _chunkYJLCBA7Vcjs.vectorNodeBounds.call(void 0, node, parentWorld);
|
|
417
433
|
const center = local ? { x: local.x + local.width / 2, y: local.y + local.height / 2 } : { x: 0, y: 0 };
|
|
418
434
|
if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds, box: local });
|
|
419
|
-
if (node.type === "group") walk(node.children,
|
|
435
|
+
if (node.type === "group") walk(node.children, _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
|
|
420
436
|
}
|
|
421
437
|
};
|
|
422
|
-
walk(nodes,
|
|
438
|
+
walk(nodes, _chunkYJLCBA7Vcjs.IDENTITY_MATRIX, []);
|
|
423
439
|
indexCache.set(nodes, out);
|
|
424
440
|
return out;
|
|
425
441
|
}
|
|
426
442
|
var solid = (paint) => typeof paint === "string" && paint !== "none" ? paint : void 0;
|
|
427
443
|
function firstPaint(node, key) {
|
|
428
444
|
if (node.type === "path") return solid(node[key]);
|
|
429
|
-
for (const p of
|
|
445
|
+
for (const p of _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node)) {
|
|
430
446
|
const s = solid(p[key]);
|
|
431
447
|
if (s) return s;
|
|
432
448
|
}
|
|
@@ -434,7 +450,7 @@ function firstPaint(node, key) {
|
|
|
434
450
|
}
|
|
435
451
|
function strokeReach(node) {
|
|
436
452
|
let reach = 0;
|
|
437
|
-
for (const p of node.type === "path" ? [node] :
|
|
453
|
+
for (const p of node.type === "path" ? [node] : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node)) {
|
|
438
454
|
if (p.stroke == null || p.stroke === "none") continue;
|
|
439
455
|
const width = _nullishCoalesce(p.strokeWidth, () => ( 1));
|
|
440
456
|
reach = Math.max(reach, p.strokeAlign === "outside" ? width : p.strokeAlign === "inside" ? 0 : width / 2);
|
|
@@ -504,7 +520,7 @@ function motionRestValue(entry, property, artwork) {
|
|
|
504
520
|
case "stroke":
|
|
505
521
|
return _nullishCoalesce((node && firstPaint(node, property)), () => ( "transparent"));
|
|
506
522
|
case "strokeWidth": {
|
|
507
|
-
const path = _optionalChain([node, 'optionalAccess', _6 => _6.type]) === "path" ? node : node ?
|
|
523
|
+
const path = _optionalChain([node, 'optionalAccess', _6 => _6.type]) === "path" ? node : node ? _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node)[0] : void 0;
|
|
508
524
|
return _nullishCoalesce(_optionalChain([path, 'optionalAccess', _7 => _7.strokeWidth]), () => ( 1));
|
|
509
525
|
}
|
|
510
526
|
case "shape":
|
|
@@ -535,11 +551,33 @@ function interpolateMotionValue(from, to, u) {
|
|
|
535
551
|
}
|
|
536
552
|
function segmentProgress(segment, time) {
|
|
537
553
|
const span = segment.end - segment.start;
|
|
538
|
-
|
|
539
|
-
|
|
554
|
+
let elapsed = time - segment.start;
|
|
555
|
+
if (segment.steps && segment.steps > 0 && elapsed < span) elapsed = Math.floor(elapsed * segment.steps / 1e3 + 1e-9) / segment.steps * 1e3;
|
|
556
|
+
const u = span <= 0 ? 1 : Math.min(1, Math.max(0, elapsed / span));
|
|
557
|
+
return { u, eased: _chunk2FHLHZALcjs.evaluateEasing.call(void 0, segment.ease, segment.reverse ? 1 - u : u, span) };
|
|
558
|
+
}
|
|
559
|
+
function geometricValue(from, to, e) {
|
|
560
|
+
const grow = (a, b) => a > 0 && b > 0 ? a * (b / a) ** e : void 0;
|
|
561
|
+
if (typeof from === "number" && typeof to === "number") return grow(from, to);
|
|
562
|
+
if (Array.isArray(from) && Array.isArray(to) && from.length === 4 && to.length === 4) {
|
|
563
|
+
const [x0, y0, w0, h0] = from;
|
|
564
|
+
const [x1, y1, w1, h1] = to;
|
|
565
|
+
const w = grow(w0, w1);
|
|
566
|
+
const h = grow(h0, h1);
|
|
567
|
+
if (w === void 0 || h === void 0) return void 0;
|
|
568
|
+
const f = Math.abs(w1 - w0) > 1e-9 ? (w - w0) / (w1 - w0) : e;
|
|
569
|
+
const cx = x0 + w0 / 2 + (x1 + w1 / 2 - x0 - w0 / 2) * f;
|
|
570
|
+
const cy = y0 + h0 / 2 + (y1 + h1 / 2 - y0 - h0 / 2) * f;
|
|
571
|
+
return [cx - w / 2, cy - h / 2, w, h];
|
|
572
|
+
}
|
|
573
|
+
return void 0;
|
|
540
574
|
}
|
|
541
575
|
function segmentValue(segment, time, raw = false) {
|
|
542
576
|
const { eased } = segmentProgress(segment, time);
|
|
577
|
+
if (segment.geometric && !segment.behavior) {
|
|
578
|
+
const g = geometricValue(segment.from, segment.to, eased);
|
|
579
|
+
if (g !== void 0) return g;
|
|
580
|
+
}
|
|
543
581
|
if (!segment.behavior || raw) return interpolateMotionValue(segment.from, segment.to, eased);
|
|
544
582
|
const p = _chunkZCNLBRT6cjs.behaviorProgress.call(void 0, segment.behavior, eased, _nullishCoalesce(segment.index, () => ( 0)), segment.end - segment.start);
|
|
545
583
|
return typeof segment.from === "string" ? interpolateMotionValue(segment.from, segment.to, Math.min(1, Math.max(0, p))) : interpolateMotionValue(segment.from, segment.to, p);
|
|
@@ -559,6 +597,20 @@ function trackValue(track, time, raw = false) {
|
|
|
559
597
|
return first.from;
|
|
560
598
|
}
|
|
561
599
|
var motionTrackKey = (node, property) => `${node}\0${property}`;
|
|
600
|
+
var motionAddTrackKey = (node, property) => `${node}\0${property}\0add`;
|
|
601
|
+
var MOTION_ADDITIVE_PROPERTIES = ["x", "y", "rotation", "scaleX", "scaleY"];
|
|
602
|
+
function withMotionLayers(timeline, node, property, base, time, raw = false) {
|
|
603
|
+
const layers = timeline.tracks.get(motionAddTrackKey(node, property));
|
|
604
|
+
if (!layers) return base;
|
|
605
|
+
const scale = property === "scaleX" || property === "scaleY";
|
|
606
|
+
let v = base;
|
|
607
|
+
for (const layer of layers) {
|
|
608
|
+
if (layer.start > time) continue;
|
|
609
|
+
const x = Number(segmentValue(layer, time, raw));
|
|
610
|
+
if (Number.isFinite(x)) v = scale ? v * x : v + x;
|
|
611
|
+
}
|
|
612
|
+
return v;
|
|
613
|
+
}
|
|
562
614
|
function fitMotionRect(rect, aspect) {
|
|
563
615
|
const cx = rect.x + rect.width / 2;
|
|
564
616
|
const cy = rect.y + rect.height / 2;
|
|
@@ -579,20 +631,32 @@ function resolveMotionCamera(camera, scene) {
|
|
|
579
631
|
const r = camera;
|
|
580
632
|
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
581
633
|
}
|
|
582
|
-
function motionPathLength(node, parentWorld =
|
|
634
|
+
function motionPathLength(node, parentWorld = _chunkYJLCBA7Vcjs.IDENTITY_MATRIX) {
|
|
583
635
|
let longest = 0;
|
|
584
|
-
const paths = node.type === "path" ? [node] :
|
|
636
|
+
const paths = node.type === "path" ? [node] : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node);
|
|
585
637
|
for (const p of paths) {
|
|
586
638
|
try {
|
|
587
|
-
longest = Math.max(longest, _chunkO2UH7LZEcjs.bezierPathLength.call(void 0,
|
|
639
|
+
longest = Math.max(longest, _chunkO2UH7LZEcjs.bezierPathLength.call(void 0, _chunkYJLCBA7Vcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
|
|
588
640
|
} catch (e2) {
|
|
589
641
|
}
|
|
590
642
|
}
|
|
591
643
|
return longest;
|
|
592
644
|
}
|
|
645
|
+
function motionCommandRepeat(command2) {
|
|
646
|
+
if (command2.type === "wait" || command2.type === "enter" || command2.type === "exit") return 1;
|
|
647
|
+
const n = _nullishCoalesce(command2.repeat, () => ( 1));
|
|
648
|
+
return Number.isInteger(n) && n >= 1 ? n : 1;
|
|
649
|
+
}
|
|
593
650
|
function motionCommandDuration(command2, scene, target) {
|
|
651
|
+
return motionCycleDuration(command2, scene, target) * motionCommandRepeat(command2);
|
|
652
|
+
}
|
|
653
|
+
function motionCycleDuration(command2, scene, target) {
|
|
594
654
|
if (command2.type === "wait") return command2.duration;
|
|
595
655
|
if (command2.duration !== void 0) return command2.duration;
|
|
656
|
+
if (command2.ease !== void 0) {
|
|
657
|
+
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0, command2.ease);
|
|
658
|
+
if (ease !== "hold" && ease.type === "spring") return _chunk2FHLHZALcjs.springSettleMs.call(void 0, ease);
|
|
659
|
+
}
|
|
596
660
|
if (command2.type === "draw" || command2.type === "enter" && command2.style === "draw" || command2.type === "exit" && command2.style === "undraw") {
|
|
597
661
|
const entry = target ? indexMotionNodes(scene.artwork.nodes).get(target) : void 0;
|
|
598
662
|
const length = entry ? motionPathLength(entry.node) : 0;
|
|
@@ -621,7 +685,7 @@ function compileMotionScene(scene) {
|
|
|
621
685
|
const rect = resolveMotionCamera(shot.camera, scene);
|
|
622
686
|
if (rect && rect.width > 0 && rect.height > 0) {
|
|
623
687
|
const ms = index === 0 ? 0 : _nullishCoalesce(shot.camera.ms, () => ( MOTION_CAMERA_MS));
|
|
624
|
-
cameraMoves.push({ shot: shot.id, start, end: start + ms, to: rect, ease: _nullishCoalesce(shot.camera.ease, () => ( MOTION_EASE_IN_OUT)) });
|
|
688
|
+
cameraMoves.push({ shot: shot.id, start, end: start + ms, to: rect, ease: _nullishCoalesce(shot.camera.ease, () => ( MOTION_EASE_IN_OUT)), geometric: shot.camera.geometric === true });
|
|
625
689
|
cursor = start + ms;
|
|
626
690
|
}
|
|
627
691
|
}
|
|
@@ -650,7 +714,7 @@ function compileMotionScene(scene) {
|
|
|
650
714
|
return _nullishCoalesce(v, () => ( motionRestValue(nodes.get(node), property, artwork)));
|
|
651
715
|
};
|
|
652
716
|
const push = (segment) => {
|
|
653
|
-
const key = motionTrackKey(segment.node, segment.property);
|
|
717
|
+
const key = segment.blend === "add" ? motionAddTrackKey(segment.node, segment.property) : motionTrackKey(segment.node, segment.property);
|
|
654
718
|
let track = tracks.get(key);
|
|
655
719
|
if (!track) tracks.set(key, track = []);
|
|
656
720
|
track.push(segment);
|
|
@@ -662,7 +726,7 @@ function compileMotionScene(scene) {
|
|
|
662
726
|
jobs.push({
|
|
663
727
|
start: move.start,
|
|
664
728
|
order: order++,
|
|
665
|
-
run: () => push({ node: "", property: "camera", start: move.start, end: move.end, from: valueAt("", "camera", move.start), to: [move.to.x, move.to.y, move.to.width, move.to.height], ease: move.ease, shot: move.shot, command: -1 })
|
|
729
|
+
run: () => push({ node: "", property: "camera", start: move.start, end: move.end, from: valueAt("", "camera", move.start), to: [move.to.x, move.to.y, move.to.width, move.to.height], ease: move.ease, shot: move.shot, command: -1, ...move.geometric ? { geometric: true } : {} })
|
|
666
730
|
});
|
|
667
731
|
}
|
|
668
732
|
for (const timing of commands) {
|
|
@@ -673,11 +737,37 @@ function compileMotionScene(scene) {
|
|
|
673
737
|
const entry = nodes.get(target);
|
|
674
738
|
if (!entry) return;
|
|
675
739
|
const start = timing.start + k * (_nullishCoalesce(command2.stagger, () => ( 0)));
|
|
676
|
-
const
|
|
677
|
-
jobs.push({ start, order: order++, run: () =>
|
|
740
|
+
const cycle = motionCycleDuration(command2, scene, target);
|
|
741
|
+
jobs.push({ start, order: order++, run: () => compileRepeated(command2, target, entry, start, cycle, timing) });
|
|
678
742
|
});
|
|
679
743
|
}
|
|
680
744
|
jobs.sort((a, b) => a.start - b.start || a.order - b.order).forEach((job) => job.run());
|
|
745
|
+
function compileRepeated(command2, node, entry, start, cycle, timing) {
|
|
746
|
+
const first = segments.length;
|
|
747
|
+
compileCommand(command2, node, entry, start, cycle, timing);
|
|
748
|
+
const made = segments.slice(first);
|
|
749
|
+
const steps = _nullishCoalesce(command2.steps, () => ( scene.steps));
|
|
750
|
+
if (steps && steps > 0) for (const s of made) s.steps = steps;
|
|
751
|
+
const n = motionCommandRepeat(command2);
|
|
752
|
+
const mode = _nullishCoalesce(command2.repeatMode, () => ( "loop"));
|
|
753
|
+
const shift = (v, by, k) => {
|
|
754
|
+
if (typeof v === "number" && typeof by === "number") return v + by * k;
|
|
755
|
+
if (Array.isArray(v) && Array.isArray(by) && v.length === by.length) return v.map((x, i) => x + by[i] * k);
|
|
756
|
+
return v;
|
|
757
|
+
};
|
|
758
|
+
for (let k = 1; k < n; k++) {
|
|
759
|
+
const at = start + k * cycle;
|
|
760
|
+
for (const s of made) {
|
|
761
|
+
if (mode === "mirror" && k % 2 === 1) {
|
|
762
|
+
push({ ...s, start: at + (start + cycle - s.end), end: at + (start + cycle - s.start), reverse: !s.reverse });
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
const delta = typeof s.from === "number" && typeof s.to === "number" ? s.to - s.from : Array.isArray(s.from) && Array.isArray(s.to) && s.from.length === s.to.length ? s.to.map((x, i) => x - s.from[i]) : 0;
|
|
766
|
+
const by = mode === "offset" ? delta : 0;
|
|
767
|
+
push({ ...s, start: at + (s.start - start), end: at + (s.end - start), from: shift(s.from, by, k), to: shift(s.to, by, k) });
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
681
771
|
function compileCommand(command2, node, entry, start, duration2, timing) {
|
|
682
772
|
const end = start + duration2;
|
|
683
773
|
const where = { shot: timing.shot, command: timing.command };
|
|
@@ -758,22 +848,31 @@ function compileMotionScene(scene) {
|
|
|
758
848
|
let dx = _nullishCoalesce(_optionalChain([command2, 'access', _16 => _16.by, 'optionalAccess', _17 => _17.x]), () => ( 0));
|
|
759
849
|
let dy = _nullishCoalesce(_optionalChain([command2, 'access', _18 => _18.by, 'optionalAccess', _19 => _19.y]), () => ( 0));
|
|
760
850
|
if (command2.to) {
|
|
761
|
-
const inv =
|
|
762
|
-
const target =
|
|
851
|
+
const inv = _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
852
|
+
const target = _chunkYJLCBA7Vcjs.applyMatrix.call(void 0, inv, command2.to);
|
|
763
853
|
dx = target.x - (entry.center.x + num("x"));
|
|
764
854
|
dy = target.y - (entry.center.y + num("y"));
|
|
765
855
|
}
|
|
766
|
-
|
|
767
|
-
|
|
856
|
+
if (command2.blend === "add") {
|
|
857
|
+
seg("x", dx, e, start, end, { from: 0, blend: "add" });
|
|
858
|
+
seg("y", dy, e, start, end, { from: 0, blend: "add" });
|
|
859
|
+
} else {
|
|
860
|
+
seg("x", num("x") + dx, e);
|
|
861
|
+
seg("y", num("y") + dy, e);
|
|
862
|
+
}
|
|
768
863
|
break;
|
|
769
864
|
}
|
|
770
|
-
case "rotate":
|
|
771
|
-
|
|
865
|
+
case "rotate": {
|
|
866
|
+
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
867
|
+
if (command2.blend === "add") seg("rotation", command2.to !== void 0 ? command2.to - num("rotation") : _nullishCoalesce(command2.by, () => ( 0)), e, start, end, { from: 0, blend: "add" });
|
|
868
|
+
else seg("rotation", _nullishCoalesce(command2.to, () => ( num("rotation") + (_nullishCoalesce(command2.by, () => ( 0))))), e);
|
|
772
869
|
break;
|
|
870
|
+
}
|
|
773
871
|
case "scale": {
|
|
774
872
|
const to = typeof command2.to === "number" ? { x: command2.to, y: command2.to } : command2.to;
|
|
775
|
-
|
|
776
|
-
seg("
|
|
873
|
+
const extra = { ...command2.geometric ? { geometric: true } : {}, ...command2.blend === "add" ? { from: 1, blend: "add" } : {} };
|
|
874
|
+
seg("scaleX", to.x, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, extra);
|
|
875
|
+
seg("scaleY", to.y, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, extra);
|
|
777
876
|
break;
|
|
778
877
|
}
|
|
779
878
|
case "fade":
|
|
@@ -791,30 +890,31 @@ function compileMotionScene(scene) {
|
|
|
791
890
|
seg("follow", _nullishCoalesce(command2.to, () => ( 1)), _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, { from: _nullishCoalesce(command2.from, () => ( 0)), path: command2.path, rotate: _nullishCoalesce(command2.rotate, () => ( false)) });
|
|
792
891
|
break;
|
|
793
892
|
// Emphasis: a change toward a peak that a behaviour swings round (as Flair's primitives do).
|
|
794
|
-
case "pulse":
|
|
795
|
-
|
|
796
|
-
const k = 1 + (_nullishCoalesce(command2.amount, () => ( 0.15)));
|
|
797
|
-
seg("scaleX", num("scaleX") * k, _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior });
|
|
798
|
-
seg("scaleY", num("scaleY") * k, _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior });
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
case "shake": {
|
|
802
|
-
const p = command2.axis === "vertical" ? "y" : "x";
|
|
803
|
-
seg(p, num(p) + (_nullishCoalesce(command2.amount, () => ( 8))), _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 3)), decay: 1 } });
|
|
804
|
-
break;
|
|
805
|
-
}
|
|
893
|
+
case "pulse":
|
|
894
|
+
case "shake":
|
|
806
895
|
case "teeter":
|
|
807
|
-
seg("rotation", num("rotation") + (_nullishCoalesce(command2.angle, () => ( 8))), _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 3)), decay: 1 } });
|
|
808
|
-
break;
|
|
809
896
|
case "wave":
|
|
810
|
-
seg("y", num("y") - (_nullishCoalesce(command2.amount, () => ( 6))), _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 2)) } });
|
|
811
|
-
break;
|
|
812
897
|
case "wiggle": {
|
|
813
|
-
const
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
898
|
+
const add = (_nullishCoalesce(command2.blend, () => ( "add"))) === "add";
|
|
899
|
+
const swing = (p, by, extra) => {
|
|
900
|
+
const scale = p === "scaleX" || p === "scaleY";
|
|
901
|
+
if (add) seg(p, by, _nullishCoalesce(ease, () => ( "linear")), start, end, { from: scale ? 1 : 0, blend: "add", ...extra });
|
|
902
|
+
else seg(p, scale ? num(p) * by : num(p) + by, _nullishCoalesce(ease, () => ( "linear")), start, end, extra);
|
|
903
|
+
};
|
|
904
|
+
if (command2.type === "pulse") {
|
|
905
|
+
const behavior = { type: "pulse", count: _nullishCoalesce(command2.count, () => ( 1)) };
|
|
906
|
+
swing("scaleX", 1 + (_nullishCoalesce(command2.amount, () => ( 0.15))), { behavior });
|
|
907
|
+
swing("scaleY", 1 + (_nullishCoalesce(command2.amount, () => ( 0.15))), { behavior });
|
|
908
|
+
} else if (command2.type === "shake") swing(command2.axis === "vertical" ? "y" : "x", _nullishCoalesce(command2.amount, () => ( 8)), { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 3)), decay: 1 } });
|
|
909
|
+
else if (command2.type === "teeter") swing("rotation", _nullishCoalesce(command2.angle, () => ( 8)), { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 3)), decay: 1 } });
|
|
910
|
+
else if (command2.type === "wave") swing("y", -(_nullishCoalesce(command2.amount, () => ( 6))), { behavior: { type: "oscillate", count: _nullishCoalesce(command2.count, () => ( 2)) } });
|
|
911
|
+
else {
|
|
912
|
+
const behavior = { type: "wriggle", frequency: _nullishCoalesce(command2.frequency, () => ( 3)), octaves: _nullishCoalesce(command2.octaves, () => ( 2)), seed: command2.seed || _chunkZCNLBRT6cjs.motionSeedFromId.call(void 0, node) };
|
|
913
|
+
const amount = _nullishCoalesce(command2.amount, () => ( 6));
|
|
914
|
+
swing("x", amount, { behavior, index: 0 });
|
|
915
|
+
swing("y", amount, { behavior, index: 1 });
|
|
916
|
+
if (command2.rotate) swing("rotation", command2.rotate, { behavior, index: 2 });
|
|
917
|
+
}
|
|
818
918
|
break;
|
|
819
919
|
}
|
|
820
920
|
case "color-pulse":
|
|
@@ -877,13 +977,13 @@ function morphBetween(a, b) {
|
|
|
877
977
|
let inner = morphCache.get(a);
|
|
878
978
|
if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
|
|
879
979
|
let morph = inner.get(b);
|
|
880
|
-
if (!morph) inner.set(b, morph =
|
|
980
|
+
if (!morph) inner.set(b, morph = _chunkYJLCBA7Vcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
|
|
881
981
|
return morph;
|
|
882
982
|
}
|
|
883
983
|
function shapeIn(entry, shape) {
|
|
884
984
|
if (shape === entry) return entry.node;
|
|
885
|
-
const m =
|
|
886
|
-
return { ...shape.node, ...
|
|
985
|
+
const m = _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, entry.parentWorld));
|
|
986
|
+
return { ...shape.node, ..._chunkYJLCBA7Vcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
|
|
887
987
|
}
|
|
888
988
|
function shapeAt(entry, timeline, nodes, time) {
|
|
889
989
|
const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
|
|
@@ -903,7 +1003,7 @@ function shapeAt(entry, timeline, nodes, time) {
|
|
|
903
1003
|
function motionFollowRoute(entry, path) {
|
|
904
1004
|
if (!path || path.node.type !== "path") return null;
|
|
905
1005
|
try {
|
|
906
|
-
return _chunkO2UH7LZEcjs.transformBezierPath.call(void 0,
|
|
1006
|
+
return _chunkO2UH7LZEcjs.transformBezierPath.call(void 0, _chunkYJLCBA7Vcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, entry.parentWorld));
|
|
907
1007
|
} catch (e3) {
|
|
908
1008
|
return null;
|
|
909
1009
|
}
|
|
@@ -926,18 +1026,18 @@ function followAt(entry, timeline, nodes, time) {
|
|
|
926
1026
|
function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry.node]), raw = false, follow = true) {
|
|
927
1027
|
const read = (p, rest) => {
|
|
928
1028
|
const v = trackValue(timeline.tracks.get(motionTrackKey(entry.node.id, p)), time, raw);
|
|
929
|
-
return typeof v === "number" ? v : rest;
|
|
1029
|
+
return withMotionLayers(timeline, entry.node.id, p, typeof v === "number" ? v : rest, time, raw);
|
|
930
1030
|
};
|
|
931
|
-
if (!TRANSFORM_PROPS.some((p) => (follow || p !== "follow") && timeline.tracks.has(motionTrackKey(entry.node.id, p)))) return null;
|
|
1031
|
+
if (!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;
|
|
932
1032
|
const dx = read("x", 0);
|
|
933
1033
|
const dy = read("y", 0);
|
|
934
1034
|
const rotation = read("rotation", 0);
|
|
935
1035
|
const scaleX = read("scaleX", 1);
|
|
936
1036
|
const scaleY = read("scaleY", 1);
|
|
937
1037
|
const c = entry.center;
|
|
938
|
-
let matrix =
|
|
1038
|
+
let matrix = _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkYJLCBA7Vcjs.rotateMatrix.call(void 0, rotation, c)), _chunkYJLCBA7Vcjs.translateMatrix.call(void 0, dx, dy));
|
|
939
1039
|
const along = follow ? followAt(entry, timeline, nodes, time) : null;
|
|
940
|
-
if (along) matrix =
|
|
1040
|
+
if (along) matrix = _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, matrix, _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkYJLCBA7Vcjs.rotateMatrix.call(void 0, along.angle)), _chunkYJLCBA7Vcjs.translateMatrix.call(void 0, along.x, along.y)));
|
|
941
1041
|
return { matrix, dx, dy, rotation, scaleX, scaleY, follow: along };
|
|
942
1042
|
}
|
|
943
1043
|
function motionNodeClips(id, timeline, time) {
|
|
@@ -1004,7 +1104,7 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
1004
1104
|
const start = Math.min(1, Math.max(0, typeof drawStart === "number" ? drawStart : 0));
|
|
1005
1105
|
const end = Math.min(1, Math.max(0, typeof drawEnd === "number" ? drawEnd : 1));
|
|
1006
1106
|
if (start > 0 || end < 1) {
|
|
1007
|
-
const trim =
|
|
1107
|
+
const trim = _chunkYJLCBA7Vcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
|
|
1008
1108
|
p = { ...p, effects: [trim, ...(_nullishCoalesce(p.effects, () => ( []))).filter((e) => e.id !== MOTION_DRAW_EFFECT_ID)] };
|
|
1009
1109
|
}
|
|
1010
1110
|
}
|
|
@@ -1018,8 +1118,8 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
1018
1118
|
if (o >= 1) delete out.opacity;
|
|
1019
1119
|
}
|
|
1020
1120
|
const offset = options.offsets === false ? null : motionNodeOffset(entry, timeline, time, nodes);
|
|
1021
|
-
if (offset && !
|
|
1022
|
-
const m =
|
|
1121
|
+
if (offset && !_chunkYJLCBA7Vcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
|
|
1122
|
+
const m = _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _chunkYJLCBA7Vcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
|
|
1023
1123
|
out = { ...out, transform: m };
|
|
1024
1124
|
}
|
|
1025
1125
|
return out;
|
|
@@ -1039,7 +1139,7 @@ function motionFrameToSvg(scene, time, options = {}) {
|
|
|
1039
1139
|
const wrap = { ...options.wrap };
|
|
1040
1140
|
for (const [id, clips] of Object.entries(frame.clips))
|
|
1041
1141
|
wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
|
|
1042
|
-
return withViewBox(
|
|
1142
|
+
return withViewBox(_chunkYJLCBA7Vcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera);
|
|
1043
1143
|
}
|
|
1044
1144
|
function withViewBox(svg, box) {
|
|
1045
1145
|
const f = (n) => String(Math.round(n * 1e3) / 1e3);
|
|
@@ -1079,7 +1179,7 @@ function visibleAt(timeline, id, time, node) {
|
|
|
1079
1179
|
if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
|
|
1080
1180
|
const circle = clip("clipCircle");
|
|
1081
1181
|
if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
|
|
1082
|
-
const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" :
|
|
1182
|
+
const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
|
|
1083
1183
|
return num("drawEnd", 1) > 0.01 || hasFill && num("fillOpacity", 1) > 0.01;
|
|
1084
1184
|
}
|
|
1085
1185
|
function checkMotionScene(scene) {
|
|
@@ -1115,6 +1215,14 @@ function checkMotionScene(scene) {
|
|
|
1115
1215
|
const timing = timeline.commands.find((c) => c.shot === shot.id && c.command === i);
|
|
1116
1216
|
if (timing && timing.duration > 0 && timing.duration < MOTION_MIN_CHANGE_MS)
|
|
1117
1217
|
issues.push(motionIssue("too-fast", `This ${command2.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 }));
|
|
1218
|
+
if (command2.duration !== void 0 && command2.ease !== void 0) {
|
|
1219
|
+
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0, command2.ease);
|
|
1220
|
+
if (ease !== "hold" && ease.type === "spring") {
|
|
1221
|
+
const settle = _chunk2FHLHZALcjs.springSettleMs.call(void 0, ease);
|
|
1222
|
+
if (command2.duration < settle * 0.9)
|
|
1223
|
+
issues.push(motionIssue("spring-cut-short", `This ${command2.type}'s spring takes ${settle} ms to settle but lasts ${command2.duration} ms, so it jumps to its end; leave "duration" out (the spring sets it) or make it at least ${settle} ms.`, { ...where, measured: command2.duration, needed: settle, unit: "ms", ids: targets }));
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1118
1226
|
if (command2.type === "follow" && known(command2.path, "unknown-path", "path", where) && nodes.get(command2.path).node.type !== "path")
|
|
1119
1227
|
issues.push(motionIssue("not-a-path", `"${command2.path}" is a group; follow a single path node.`, { ...where, ids: [command2.path] }));
|
|
1120
1228
|
if (command2.type === "morph") known(command2.into, "unknown-shape", "shape", where);
|
|
@@ -1134,7 +1242,7 @@ function checkMotionScene(scene) {
|
|
|
1134
1242
|
}
|
|
1135
1243
|
for (const id of targets) {
|
|
1136
1244
|
const node = nodes.get(id).node;
|
|
1137
|
-
const paths = node.type === "path" ? [node] :
|
|
1245
|
+
const paths = node.type === "path" ? [node] : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node);
|
|
1138
1246
|
if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
|
|
1139
1247
|
issues.push(motionIssue("paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
|
|
1140
1248
|
}
|
|
@@ -1147,7 +1255,7 @@ function checkMotionScene(scene) {
|
|
|
1147
1255
|
else
|
|
1148
1256
|
for (const id of targets) {
|
|
1149
1257
|
const node = nodes.get(id).node;
|
|
1150
|
-
const paths = node.type === "path" ? [node] :
|
|
1258
|
+
const paths = node.type === "path" ? [node] : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node);
|
|
1151
1259
|
if (paths.some((p) => typeof p[key] !== "string"))
|
|
1152
1260
|
issues.push(motionIssue("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] }));
|
|
1153
1261
|
}
|
|
@@ -1178,6 +1286,7 @@ function checkMotionScene(scene) {
|
|
|
1178
1286
|
});
|
|
1179
1287
|
});
|
|
1180
1288
|
for (const [key, track] of timeline.tracks) {
|
|
1289
|
+
if (key.endsWith("\0add")) continue;
|
|
1181
1290
|
for (let i = 1; i < track.length; i++) {
|
|
1182
1291
|
const a = track[i - 1];
|
|
1183
1292
|
const b = track[i];
|
|
@@ -1272,6 +1381,11 @@ function applyOne(scene, edit) {
|
|
|
1272
1381
|
else if (edit.description !== void 0) next.description = edit.description;
|
|
1273
1382
|
if (edit.loop !== void 0) next.loop = edit.loop;
|
|
1274
1383
|
if (edit.fps !== void 0) next.fps = edit.fps;
|
|
1384
|
+
if (edit.steps === null) delete next.steps;
|
|
1385
|
+
else if (edit.steps !== void 0) {
|
|
1386
|
+
if (!(typeof edit.steps === "number" && edit.steps > 0 && edit.steps <= 120)) fail('"steps" must be frames per second from above 0 to 120 (12 is "on twos" at 24 fps), or null for smooth.');
|
|
1387
|
+
next.steps = edit.steps;
|
|
1388
|
+
}
|
|
1275
1389
|
if (edit.target === null) delete next.target;
|
|
1276
1390
|
else if (edit.target !== void 0) next.target = edit.target;
|
|
1277
1391
|
return next;
|
|
@@ -1407,12 +1521,19 @@ var FLAIR_EASES = {
|
|
|
1407
1521
|
"in-out": (t) => t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2,
|
|
1408
1522
|
out: (t) => 1 - (1 - t) ** 3
|
|
1409
1523
|
};
|
|
1524
|
+
var FLAIR_EXPORT_VERSION = "0.39";
|
|
1525
|
+
function flairAtLeast(version, min) {
|
|
1526
|
+
const a = version.split(".").map((n) => parseInt(n, 10) || 0);
|
|
1527
|
+
const b = min.split(".").map((n) => parseInt(n, 10) || 0);
|
|
1528
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) if ((_nullishCoalesce(a[i], () => ( 0))) !== (_nullishCoalesce(b[i], () => ( 0)))) return (_nullishCoalesce(a[i], () => ( 0))) > (_nullishCoalesce(b[i], () => ( 0)));
|
|
1529
|
+
return true;
|
|
1530
|
+
}
|
|
1410
1531
|
function flairEaseFor(ease) {
|
|
1411
1532
|
for (const name of ["linear", "out", "in-out"]) {
|
|
1412
1533
|
let worst = 0;
|
|
1413
1534
|
for (let i = 1; i < 40; i++) {
|
|
1414
1535
|
const t = i / 40;
|
|
1415
|
-
worst = Math.max(worst, Math.abs(
|
|
1536
|
+
worst = Math.max(worst, Math.abs(_chunk2FHLHZALcjs.evaluateEasing.call(void 0, ease, t, 1e3) - FLAIR_EASES[name](t)));
|
|
1416
1537
|
}
|
|
1417
1538
|
if (worst < 0.01) return name;
|
|
1418
1539
|
}
|
|
@@ -1421,11 +1542,11 @@ function flairEaseFor(ease) {
|
|
|
1421
1542
|
function flairCurveFor(ease, curves = true) {
|
|
1422
1543
|
const name = flairEaseFor(ease);
|
|
1423
1544
|
if (name || !curves) return name;
|
|
1424
|
-
const resolved =
|
|
1545
|
+
const resolved = _chunk2FHLHZALcjs.resolveEasing.call(void 0, ease);
|
|
1425
1546
|
if (resolved === "hold" || resolved.type !== "cubic-bezier") return void 0;
|
|
1426
1547
|
return [resolved.x1, resolved.y1, resolved.x2, resolved.y2];
|
|
1427
1548
|
}
|
|
1428
|
-
var overshoots = (ease) => typeof ease !== "string" && (ease[1] < 0 || ease[1] > 1 || ease[3] < 0 || ease[3] > 1);
|
|
1549
|
+
var overshoots = (ease) => typeof ease !== "string" && ("spring" in ease || ease[1] < 0 || ease[1] > 1 || ease[3] < 0 || ease[3] > 1);
|
|
1429
1550
|
var TRANSFORM_PROPS2 = ["x", "y", "rotation", "scaleX", "scaleY", "follow"];
|
|
1430
1551
|
var LINEAR_TRANSFORM = /* @__PURE__ */ new Set(["x", "y", "rotation", "scaleX", "scaleY"]);
|
|
1431
1552
|
function hex6(color) {
|
|
@@ -1435,9 +1556,24 @@ function hex6(color) {
|
|
|
1435
1556
|
function toFlairSvgMotion(scene, options = {}) {
|
|
1436
1557
|
const fps = _nullishCoalesce(_nullishCoalesce(options.fps, () => ( scene.fps)), () => ( 30));
|
|
1437
1558
|
const precision = _nullishCoalesce(options.precision, () => ( 3));
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1440
|
-
const
|
|
1559
|
+
const flair = _nullishCoalesce(options.flair, () => ( FLAIR_EXPORT_VERSION));
|
|
1560
|
+
const curves = _nullishCoalesce(options.curves, () => ( flairAtLeast(flair, "0.36")));
|
|
1561
|
+
const behaviors = _nullishCoalesce(options.behaviors, () => ( flairAtLeast(flair, "0.38")));
|
|
1562
|
+
const springs = flairAtLeast(flair, "0.39");
|
|
1563
|
+
const strobes = flairAtLeast(flair, "0.39");
|
|
1564
|
+
const writeEase = (ease) => typeof ease === "string" || "spring" in ease ? ease : ease.map(round2);
|
|
1565
|
+
const easeOf = (segment) => {
|
|
1566
|
+
const resolved = _chunk2FHLHZALcjs.resolveEasing.call(void 0, segment.ease);
|
|
1567
|
+
if (resolved !== "hold" && resolved.type === "spring") {
|
|
1568
|
+
if (!springs || segment.reverse) return void 0;
|
|
1569
|
+
const { mass, stiffness, damping, velocity } = resolved;
|
|
1570
|
+
return { spring: { mass, stiffness, damping, velocity } };
|
|
1571
|
+
}
|
|
1572
|
+
if (!segment.reverse) return flairCurveFor(segment.ease, curves);
|
|
1573
|
+
const back = _chunk2FHLHZALcjs.reverseCubicBezier.call(void 0, segment.ease);
|
|
1574
|
+
return back && curves ? flairCurveFor(back, curves) : void 0;
|
|
1575
|
+
};
|
|
1576
|
+
const plays = (s) => (!s.behavior || behaviors) && (!s.steps || strobes) && !s.geometric;
|
|
1441
1577
|
const round2 = (n) => Math.round(n * 10 ** precision) / 10 ** precision;
|
|
1442
1578
|
const f = (n) => String(round2(n));
|
|
1443
1579
|
const timeline = compileMotionScene(scene);
|
|
@@ -1500,7 +1636,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1500
1636
|
if (timeline.tracks.has(motionTrackKey(id, "opacity")))
|
|
1501
1637
|
channels.push({ id, kind: "attr", attr: "opacity", segments: [...track(id, "opacity")], exact: plays, value: (t) => round2(Math.min(1, Math.max(0, Number(trackValue(track(id, "opacity"), t))))) });
|
|
1502
1638
|
const followed = follows.some((x) => x.id === id);
|
|
1503
|
-
const transformSegments = TRANSFORM_PROPS2.flatMap((p) => followed && p === "follow" ? [] : track(id, p));
|
|
1639
|
+
const transformSegments = TRANSFORM_PROPS2.flatMap((p) => followed && p === "follow" ? [] : [...track(id, p), ..._nullishCoalesce(timeline.tracks.get(motionAddTrackKey(id, p)), () => ( []))]);
|
|
1504
1640
|
if (transformSegments.length) {
|
|
1505
1641
|
const base = node.transform ? ` matrix(${node.transform.map(f).join(" ")})` : "";
|
|
1506
1642
|
const c = entry.center;
|
|
@@ -1520,7 +1656,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1520
1656
|
raw: (t) => transformAt(t, true)
|
|
1521
1657
|
});
|
|
1522
1658
|
}
|
|
1523
|
-
const paths = node.type === "path" ? [node] :
|
|
1659
|
+
const paths = node.type === "path" ? [node] : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node);
|
|
1524
1660
|
for (const path of paths) {
|
|
1525
1661
|
if (pathsSeen.has(path.id)) continue;
|
|
1526
1662
|
pathsSeen.add(path.id);
|
|
@@ -1542,7 +1678,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1542
1678
|
if (shapeSegments.length) {
|
|
1543
1679
|
if (node.type !== "path") notes.push(`"${id}" is a group: its morph or effect animation is not exported (Flair tweens one path's "d").`);
|
|
1544
1680
|
else {
|
|
1545
|
-
const inverse =
|
|
1681
|
+
const inverse = _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, _chunkYJLCBA7Vcjs.nodeMatrix.call(void 0, node));
|
|
1546
1682
|
channels.push({
|
|
1547
1683
|
id,
|
|
1548
1684
|
kind: "attr",
|
|
@@ -1551,9 +1687,9 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1551
1687
|
exact: () => false,
|
|
1552
1688
|
value: (t) => {
|
|
1553
1689
|
const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
|
|
1554
|
-
const now =
|
|
1690
|
+
const now = _chunkYJLCBA7Vcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _37 => _37(frame.document.nodes), 'access', _38 => _38.get, 'call', _39 => _39(id), 'optionalAccess', _40 => _40.node]));
|
|
1555
1691
|
if (!now || now.type !== "path") return "";
|
|
1556
|
-
const bezier = _chunkO2UH7LZEcjs.transformBezierPath.call(void 0,
|
|
1692
|
+
const bezier = _chunkO2UH7LZEcjs.transformBezierPath.call(void 0, _chunkYJLCBA7Vcjs.vectorPathWorldBezier.call(void 0, now, _chunkYJLCBA7Vcjs.IDENTITY_MATRIX, { effects: false }), inverse);
|
|
1557
1693
|
return _chunkO2UH7LZEcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
|
|
1558
1694
|
}
|
|
1559
1695
|
});
|
|
@@ -1565,8 +1701,16 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1565
1701
|
const animate = [];
|
|
1566
1702
|
let sampled = 0;
|
|
1567
1703
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
1568
|
-
const emit = (channel, delay, ms, from, to, ease,
|
|
1569
|
-
const
|
|
1704
|
+
const emit = (channel, delay, ms, from, to, ease, segment) => {
|
|
1705
|
+
const written = writeEase(ease);
|
|
1706
|
+
const base = {
|
|
1707
|
+
...channel.id ? { id: channel.id } : {},
|
|
1708
|
+
...delay > 0 ? { delay: round2(delay) } : {},
|
|
1709
|
+
ms: round2(ms),
|
|
1710
|
+
ease: written,
|
|
1711
|
+
..._optionalChain([segment, 'optionalAccess', _41 => _41.behavior]) ? { behavior: segment.behavior } : {},
|
|
1712
|
+
..._optionalChain([segment, 'optionalAccess', _42 => _42.steps]) ? { strobe: segment.steps } : {}
|
|
1713
|
+
};
|
|
1570
1714
|
if (channel.kind === "view") animate.push({ ...base, view: to });
|
|
1571
1715
|
else if (channel.kind === "draw") animate.push({ ...base, draw: [from, to] });
|
|
1572
1716
|
else if (channel.kind === "attrs") {
|
|
@@ -1588,15 +1732,14 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1588
1732
|
const active = channel.segments.filter((s) => s.start < b && s.end > a);
|
|
1589
1733
|
if (!active.length) continue;
|
|
1590
1734
|
const first = active[0];
|
|
1591
|
-
const
|
|
1592
|
-
|
|
1593
|
-
);
|
|
1594
|
-
const curve = together ? flairCurveFor(first.ease, curves) : void 0;
|
|
1735
|
+
const key = (x) => JSON.stringify([x.ease, x.behavior, _nullishCoalesce(x.reverse, () => ( false)), _nullishCoalesce(x.steps, () => ( 0))]);
|
|
1736
|
+
const together = active.every((x) => x.start === a && x.end === b && channel.exact(x) && key(x) === key(first));
|
|
1737
|
+
const curve = together ? easeOf(first) : void 0;
|
|
1595
1738
|
const ease = curve && (!overshoots(curve) || channel.overshoot) ? curve : void 0;
|
|
1596
1739
|
if (ease) {
|
|
1597
1740
|
const from = channel.value(a);
|
|
1598
1741
|
const to = first.behavior ? (_nullishCoalesce(channel.raw, () => ( channel.value)))(b) : channel.value(b);
|
|
1599
|
-
if (!same(from, to) || channel.kind === "view") emit(channel, a, b - a, from, to, ease, first
|
|
1742
|
+
if (!same(from, to) || channel.kind === "view") emit(channel, a, b - a, from, to, ease, first);
|
|
1600
1743
|
continue;
|
|
1601
1744
|
}
|
|
1602
1745
|
const n = Math.max(1, Math.ceil((b - a) * fps / 1e3));
|
|
@@ -1618,9 +1761,10 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1618
1761
|
for (const seg of follow.segments) {
|
|
1619
1762
|
const along = { id: follow.wrapper, along: follow.routes.get(seg.path), ...seg.rotate ? { orient: true } : {} };
|
|
1620
1763
|
const progress = (t) => round2(Math.min(1, Math.max(0, Number(segmentValue(seg, t)))));
|
|
1621
|
-
const curve = seg.end > seg.start ?
|
|
1764
|
+
const curve = seg.end > seg.start ? plays(seg) ? easeOf(seg) : void 0 : "linear";
|
|
1622
1765
|
if (curve && !(overshoots(curve) && seg.rotate)) {
|
|
1623
|
-
|
|
1766
|
+
const ends = seg.reverse ? [Number(seg.to), Number(seg.from)] : [Number(seg.from), Number(seg.to)];
|
|
1767
|
+
animate.push({ ...along, ...seg.start > 0 ? { delay: round2(seg.start) } : {}, ms: round2(seg.end - seg.start), ease: writeEase(curve), ...seg.steps ? { strobe: seg.steps } : {}, at: [round2(ends[0]), round2(ends[1])] });
|
|
1624
1768
|
continue;
|
|
1625
1769
|
}
|
|
1626
1770
|
const until = Math.min(seg.end, ...starts.filter((t) => t > seg.start));
|
|
@@ -1634,11 +1778,11 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1634
1778
|
}
|
|
1635
1779
|
}
|
|
1636
1780
|
animate.sort((x, y) => (_nullishCoalesce(x.delay, () => ( 0))) - (_nullishCoalesce(y.delay, () => ( 0))));
|
|
1637
|
-
let svg =
|
|
1781
|
+
let svg = _chunkYJLCBA7Vcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkYJLCBA7Vcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
|
|
1638
1782
|
if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
|
|
1639
1783
|
const lastChange = animate.reduce((m, a) => Math.max(m, (_nullishCoalesce(a.delay, () => ( 0))) + (_nullishCoalesce(a.ms, () => ( 0)))), 0);
|
|
1640
1784
|
let motion = { svg, animate };
|
|
1641
|
-
if (_optionalChain([scene, 'access',
|
|
1785
|
+
if (_optionalChain([scene, 'access', _43 => _43.controls, 'optionalAccess', _44 => _44.length])) {
|
|
1642
1786
|
const declarations = scene.controls.map((c) => `{{${c.name}: color default=${c.default.toUpperCase()}${c.label ? ` label='${c.label.replace(/'/g, "\u2019")}'` : ""}}}`).join(" ");
|
|
1643
1787
|
const swap = (text) => scene.controls.reduce((s, c) => s.replace(new RegExp(`${c.default}(?![0-9a-fA-F])`, "gi"), `{{${c.name}}}`), text);
|
|
1644
1788
|
svg = svg.replace(/^(<svg[^>]*>)/, `$1<!-- ${declarations} -->`);
|
|
@@ -1660,7 +1804,7 @@ function toFlairVectorEffect(scene, options = {}) {
|
|
|
1660
1804
|
tags: _nullishCoalesce(options.tags, () => ( [])),
|
|
1661
1805
|
motion: out.motion,
|
|
1662
1806
|
hold: out.hold,
|
|
1663
|
-
..._optionalChain([scene, 'access',
|
|
1807
|
+
..._optionalChain([scene, 'access', _45 => _45.presets, 'optionalAccess', _46 => _46.length]) ? { presets: scene.presets } : {},
|
|
1664
1808
|
...options.trigger ? { trigger: options.trigger } : {}
|
|
1665
1809
|
};
|
|
1666
1810
|
}
|
|
@@ -1678,6 +1822,196 @@ function toFlairEffectDocument(scene, options = {}) {
|
|
|
1678
1822
|
};
|
|
1679
1823
|
}
|
|
1680
1824
|
|
|
1825
|
+
// src/animation-editor/flair-import.ts
|
|
1826
|
+
var PLACEHOLDER = /\{\{\s*([A-Za-z_]\w*)\s*(?::\s*([A-Za-z0-9]*)([^}]*))?\}\}/g;
|
|
1827
|
+
function attributeOf(attrs, name) {
|
|
1828
|
+
const m = new RegExp(`(?:^|\\s)${name}=(?:'([^']*)'|(\\S+))`).exec(attrs);
|
|
1829
|
+
return m ? _nullishCoalesce(m[1], () => ( m[2])) : void 0;
|
|
1830
|
+
}
|
|
1831
|
+
function resolvePlaceholders(motion, notes) {
|
|
1832
|
+
const text = JSON.stringify(motion);
|
|
1833
|
+
const declared = /* @__PURE__ */ new Map();
|
|
1834
|
+
for (const m of text.matchAll(PLACEHOLDER)) {
|
|
1835
|
+
if (!m[2] || declared.has(m[1])) continue;
|
|
1836
|
+
const attrs = _nullishCoalesce(m[3], () => ( ""));
|
|
1837
|
+
const value = attributeOf(attrs, "default");
|
|
1838
|
+
const fallback = m[2] === "color" ? "#000000" : "0";
|
|
1839
|
+
declared.set(m[1], { type: m[2], value: m[2] === "color" ? (_nullishCoalesce(value, () => ( fallback))).toLowerCase() : _nullishCoalesce(value, () => ( fallback)), ...attributeOf(attrs, "label") ? { label: attributeOf(attrs, "label") } : {} });
|
|
1840
|
+
}
|
|
1841
|
+
const controls = [];
|
|
1842
|
+
for (const [name, d] of declared) {
|
|
1843
|
+
if (d.type === "color" && /^#[0-9a-fA-F]{6}$/.test(d.value)) controls.push({ name, type: "color", default: d.value.toLowerCase(), ...d.label ? { label: d.label } : {} });
|
|
1844
|
+
else notes.push(`Control "${name}" (${d.type}) is fixed at its default ${d.value}: scenes take colour controls only.`);
|
|
1845
|
+
}
|
|
1846
|
+
const unknown = /* @__PURE__ */ new Set();
|
|
1847
|
+
const filled = text.replace(PLACEHOLDER, (_, name) => {
|
|
1848
|
+
const d = declared.get(name);
|
|
1849
|
+
if (!d) unknown.add(name);
|
|
1850
|
+
return (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _47 => _47.value]), () => ( ""))).replace(/"/g, '\\"');
|
|
1851
|
+
});
|
|
1852
|
+
for (const name of unknown) notes.push(`Placeholder "{{${name}}}" has no declaration, so it was left empty.`);
|
|
1853
|
+
return { motion: JSON.parse(filled), controls };
|
|
1854
|
+
}
|
|
1855
|
+
function easingOf(ease, fallback) {
|
|
1856
|
+
if (ease === void 0) return fallback;
|
|
1857
|
+
if (ease === "linear") return "linear";
|
|
1858
|
+
if (ease === "out") return MOTION_EASE_OUT;
|
|
1859
|
+
if (ease === "in-out") return MOTION_EASE_IN_OUT;
|
|
1860
|
+
if (Array.isArray(ease)) return { type: "cubic-bezier", x1: ease[0], y1: ease[1], x2: ease[2], y2: ease[3] };
|
|
1861
|
+
if (typeof ease === "object" && "spring" in ease) return { type: "spring", ...ease.spring };
|
|
1862
|
+
return fallback;
|
|
1863
|
+
}
|
|
1864
|
+
function poseOf(value, entry) {
|
|
1865
|
+
const t = _chunkYJLCBA7Vcjs.parseSvgTransform.call(void 0, String(value));
|
|
1866
|
+
const o = _chunkYJLCBA7Vcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkYJLCBA7Vcjs.invertMatrix.call(void 0, _chunkYJLCBA7Vcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
|
|
1867
|
+
const sx = Math.hypot(o[0], o[1]);
|
|
1868
|
+
if (!(sx > 1e-9)) return null;
|
|
1869
|
+
const sy = (o[0] * o[3] - o[1] * o[2]) / sx;
|
|
1870
|
+
if (Math.abs(o[2] + o[1] / sx * sy) > 1e-6 || Math.abs(o[3] - o[0] / sx * sy) > 1e-6) return null;
|
|
1871
|
+
const c = entry.center;
|
|
1872
|
+
const moved = _chunkYJLCBA7Vcjs.applyMatrix.call(void 0, o, c);
|
|
1873
|
+
return { dx: moved.x - c.x, dy: moved.y - c.y, rotation: Math.atan2(o[1], o[0]) * 180 / Math.PI, sx, sy };
|
|
1874
|
+
}
|
|
1875
|
+
var near = (a, b, eps = 1e-6) => Math.abs(a - b) < eps;
|
|
1876
|
+
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
1877
|
+
function commandsFor(anim, nodes, entered, notes) {
|
|
1878
|
+
const id = anim.id;
|
|
1879
|
+
const entry = nodes.get(id);
|
|
1880
|
+
const where = `"${id}"`;
|
|
1881
|
+
if (!entry) {
|
|
1882
|
+
notes.push(`A change to ${where} was skipped: the artwork has no element with that id.`);
|
|
1883
|
+
return [];
|
|
1884
|
+
}
|
|
1885
|
+
const targets = [id];
|
|
1886
|
+
const duration = _nullishCoalesce(anim.ms, () => ( 800));
|
|
1887
|
+
const timing = {
|
|
1888
|
+
duration,
|
|
1889
|
+
...anim.strobe ? { steps: anim.strobe } : {},
|
|
1890
|
+
...anim.repeat && anim.repeat > 1 ? { repeat: anim.repeat, ...anim.alternate ? { repeatMode: "mirror" } : {} } : {}
|
|
1891
|
+
};
|
|
1892
|
+
const ease = (fallback) => ({ ease: easingOf(anim.ease, fallback) });
|
|
1893
|
+
const out = [];
|
|
1894
|
+
const behavior = anim.behavior;
|
|
1895
|
+
const unsupported = ["count", "write", "scramble", "solo"].filter((k) => anim[k] !== void 0);
|
|
1896
|
+
if (unsupported.length) notes.push(`${where}: ${unsupported.join(", ")} ${unsupported.length > 1 ? "are" : "is"} not part of scenes and was skipped.`);
|
|
1897
|
+
if (anim.draw !== void 0 && anim.draw !== false) {
|
|
1898
|
+
const [from, to] = anim.draw === true ? [0, 1] : anim.draw;
|
|
1899
|
+
out.push({ type: "draw", targets, from, to, ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
1900
|
+
}
|
|
1901
|
+
if (anim.along) {
|
|
1902
|
+
const path = nodes.get(anim.along);
|
|
1903
|
+
if (!path || path.node.type !== "path") notes.push(`${where} follows "${anim.along}", which is not a path in the artwork; the follow was skipped.`);
|
|
1904
|
+
else out.push({ type: "follow", targets, path: anim.along, from: _nullishCoalesce(_optionalChain([anim, 'access', _48 => _48.at, 'optionalAccess', _49 => _49[0]]), () => ( 0)), to: _nullishCoalesce(_optionalChain([anim, 'access', _50 => _50.at, 'optionalAccess', _51 => _51[1]]), () => ( 1)), ...anim.orient ? { rotate: true } : {}, ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
1905
|
+
}
|
|
1906
|
+
for (const [attr, [a, b]] of Object.entries(_nullishCoalesce(anim.attrs, () => ( {})))) {
|
|
1907
|
+
if (attr === "opacity") {
|
|
1908
|
+
const [from, to] = [Number(a), Number(b)];
|
|
1909
|
+
if (behavior) notes.push(`${where}: an opacity ${behavior.type} became a plain fade.`);
|
|
1910
|
+
if (from === 0 && to > 0 && !entered.has(id)) {
|
|
1911
|
+
entered.add(id);
|
|
1912
|
+
out.push({ type: "enter", targets, style: "fade", ...timing, ...ease(MOTION_EASE_OUT) });
|
|
1913
|
+
} else out.push({ type: "fade", targets, to: Math.min(1, Math.max(0, to)), ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
1914
|
+
} else if (attr === "fill" || attr === "stroke") {
|
|
1915
|
+
if (_optionalChain([behavior, 'optionalAccess', _52 => _52.type]) === "pulse") out.push({ type: "color-pulse", targets, color: String(b), paint: attr, count: _nullishCoalesce(behavior.count, () => ( 1)), ...timing, ...ease("linear") });
|
|
1916
|
+
else {
|
|
1917
|
+
if (behavior) notes.push(`${where}: a ${attr} ${behavior.type} became a plain colour change.`);
|
|
1918
|
+
out.push({ type: "style", targets, [attr]: String(b), ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
1919
|
+
}
|
|
1920
|
+
} else if (attr === "stroke-width") {
|
|
1921
|
+
out.push({ type: "style", targets, strokeWidth: Number(b), ...timing, ...ease(MOTION_EASE_IN_OUT) });
|
|
1922
|
+
} else if (attr === "transform") {
|
|
1923
|
+
const p0 = poseOf(a, entry);
|
|
1924
|
+
const p1 = poseOf(b, entry);
|
|
1925
|
+
if (!p0 || !p1) {
|
|
1926
|
+
notes.push(`${where}: a transform that skews was skipped (scenes move, turn and scale).`);
|
|
1927
|
+
continue;
|
|
1928
|
+
}
|
|
1929
|
+
const d = { x: r3(p1.dx - p0.dx), y: r3(p1.dy - p0.dy), r: r3(p1.rotation - p0.rotation), sx: p1.sx / p0.sx, sy: p1.sy / p0.sy };
|
|
1930
|
+
if (behavior) {
|
|
1931
|
+
const linear = ease("linear");
|
|
1932
|
+
const moves = d.x !== 0 || d.y !== 0;
|
|
1933
|
+
const turns = d.r !== 0;
|
|
1934
|
+
const scales = !near(d.sx, 1) || !near(d.sy, 1);
|
|
1935
|
+
if (behavior.type === "pulse" && scales && !moves && !turns) out.push({ type: "pulse", targets, amount: r3(d.sx - 1), count: _nullishCoalesce(behavior.count, () => ( 1)), ...timing, ...linear });
|
|
1936
|
+
else if (behavior.type === "oscillate" && (_nullishCoalesce(behavior.decay, () => ( 0))) > 0 && turns && !moves && !scales) out.push({ type: "teeter", targets, angle: d.r, count: _nullishCoalesce(behavior.count, () => ( 1)), ...timing, ...linear });
|
|
1937
|
+
else if (behavior.type === "oscillate" && (_nullishCoalesce(behavior.decay, () => ( 0))) > 0 && moves && !turns && !scales && (d.x === 0 || d.y === 0))
|
|
1938
|
+
out.push({ type: "shake", targets, amount: d.x || d.y, count: _nullishCoalesce(behavior.count, () => ( 1)), ...d.x === 0 ? { axis: "vertical" } : {}, ...timing, ...linear });
|
|
1939
|
+
else if (behavior.type === "oscillate" && !behavior.decay && d.x === 0 && d.y !== 0 && !turns && !scales) out.push({ type: "wave", targets, amount: -d.y, count: _nullishCoalesce(behavior.count, () => ( 1)), ...timing, ...linear });
|
|
1940
|
+
else if (behavior.type === "wriggle" && !scales)
|
|
1941
|
+
out.push({ type: "wiggle", targets, amount: Math.max(Math.abs(d.x), Math.abs(d.y)), ...turns ? { rotate: Math.abs(d.r) } : {}, frequency: _nullishCoalesce(behavior.frequency, () => ( 2)), octaves: _nullishCoalesce(behavior.octaves, () => ( 2)), seed: _nullishCoalesce(behavior.seed, () => ( 42)), ...timing, ...linear });
|
|
1942
|
+
else notes.push(`${where}: a transform ${behavior.type} that is not a pulse, shake, teeter, wave or wiggle was skipped.`);
|
|
1943
|
+
continue;
|
|
1944
|
+
}
|
|
1945
|
+
const e = ease(MOTION_EASE_IN_OUT);
|
|
1946
|
+
if (d.x !== 0 || d.y !== 0) out.push({ type: "move", targets, by: { x: d.x, y: d.y }, ...timing, ...e });
|
|
1947
|
+
if (d.r !== 0) out.push({ type: "rotate", targets, to: r3(p1.rotation), ...timing, ...e });
|
|
1948
|
+
if (!near(d.sx, 1) || !near(d.sy, 1)) out.push({ type: "scale", targets, to: near(p1.sx, p1.sy) ? r3(p1.sx) : { x: r3(p1.sx), y: r3(p1.sy) }, ...timing, ...e });
|
|
1949
|
+
} else notes.push(`${where}: changing "${attr}" is not part of scenes and was skipped.`);
|
|
1950
|
+
}
|
|
1951
|
+
return out;
|
|
1952
|
+
}
|
|
1953
|
+
function fromFlairSvgMotion(input, options = {}) {
|
|
1954
|
+
const notes = [];
|
|
1955
|
+
if (!input || typeof input.svg !== "string") throw new Error('Give a Flair SvgMotion: { svg: "<svg \u2026>", animate: [ \u2026 ] }.');
|
|
1956
|
+
const { motion, controls } = resolvePlaceholders(input, notes);
|
|
1957
|
+
const artwork = _chunkYJLCBA7Vcjs.parseVectorSvg.call(void 0, motion.svg);
|
|
1958
|
+
const nodes = indexMotionNodes(artwork.nodes);
|
|
1959
|
+
const byStep = /* @__PURE__ */ new Map();
|
|
1960
|
+
for (const anim of _nullishCoalesce(motion.animate, () => ( []))) {
|
|
1961
|
+
const step = Math.max(0, Math.floor(_nullishCoalesce(anim.step, () => ( 0))));
|
|
1962
|
+
if (!byStep.has(step)) byStep.set(step, []);
|
|
1963
|
+
byStep.get(step).push(anim);
|
|
1964
|
+
}
|
|
1965
|
+
const steps = [...byStep.keys()].sort((a, b) => a - b);
|
|
1966
|
+
if (steps.length > 1) notes.push("Each Flair step became a shot played after the one before (Flair steps wait for clicks or set times).");
|
|
1967
|
+
const entered = /* @__PURE__ */ new Set();
|
|
1968
|
+
const shots = steps.map((step, index) => {
|
|
1969
|
+
const anims = [...byStep.get(step)].sort((a, b) => (_nullishCoalesce(a.delay, () => ( 0))) - (_nullishCoalesce(b.delay, () => ( 0))));
|
|
1970
|
+
let camera;
|
|
1971
|
+
let cameraMs = 0;
|
|
1972
|
+
const run = [];
|
|
1973
|
+
let last = 0;
|
|
1974
|
+
for (const anim of anims) {
|
|
1975
|
+
if (anim.view !== void 0) {
|
|
1976
|
+
if (camera || (_nullishCoalesce(anim.delay, () => ( 0))) > 0) {
|
|
1977
|
+
notes.push(`Step ${step}: a camera move ${camera ? "after the first" : `${anim.delay} ms in`} was dropped; a shot frames the camera once, at its start.`);
|
|
1978
|
+
continue;
|
|
1979
|
+
}
|
|
1980
|
+
const ms = _nullishCoalesce(anim.ms, () => ( 800));
|
|
1981
|
+
const ease = easingOf(anim.ease, MOTION_EASE_IN_OUT);
|
|
1982
|
+
camera = typeof anim.view === "string" ? { frame: anim.view, padding: 0, ms, ease } : { x: anim.view[0], y: anim.view[1], width: anim.view[2], height: anim.view[3], ms, ease };
|
|
1983
|
+
cameraMs = index === 0 ? 0 : ms;
|
|
1984
|
+
continue;
|
|
1985
|
+
}
|
|
1986
|
+
if (!anim.id) continue;
|
|
1987
|
+
const at = Math.max(0, (_nullishCoalesce(anim.delay, () => ( 0))) - cameraMs);
|
|
1988
|
+
if (cameraMs && (_nullishCoalesce(anim.delay, () => ( 0))) < cameraMs) notes.push(`Step ${step}: a change to "${anim.id}" during the camera move now starts after it.`);
|
|
1989
|
+
for (const command2 of commandsFor(anim, nodes, entered, notes)) {
|
|
1990
|
+
const first = run.length === 0;
|
|
1991
|
+
run.push({ ...command2, ...first ? {} : { with: "previous" }, ...at - last > 0 || first ? { delay: first ? at : at - last } : {} });
|
|
1992
|
+
if (first && at === 0) delete run[run.length - 1].delay;
|
|
1993
|
+
last = at;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return { id: `step-${step}`, ...camera ? { camera } : {}, run, ...index === steps.length - 1 ? { hold: _nullishCoalesce(options.hold, () => ( 600)) } : {} };
|
|
1997
|
+
});
|
|
1998
|
+
const scene = { version: 1, name: _nullishCoalesce(options.name, () => ( "from-flair")), artwork, shots, ...controls.length ? { controls } : {} };
|
|
1999
|
+
const problems = motionSceneShapeProblems(scene);
|
|
2000
|
+
if (problems.length) throw new Error(`The imported scene is not well formed:
|
|
2001
|
+
${problems.join("\n")}`);
|
|
2002
|
+
return { scene, notes: [...new Set(notes)], issues: checkMotionScene(scene) };
|
|
2003
|
+
}
|
|
2004
|
+
function fromFlairVectorEffect(effect, options = {}) {
|
|
2005
|
+
if (!effect || effect.kind !== "vector" || !effect.motion) throw new Error('Give a Flair vector effect: { kind: "vector", id, name, motion: { svg, animate } }.');
|
|
2006
|
+
const result = fromFlairSvgMotion(effect.motion, { name: _nullishCoalesce(_nullishCoalesce(options.name, () => ( effect.id)), () => ( effect.name)), hold: _nullishCoalesce(options.hold, () => ( effect.hold)) });
|
|
2007
|
+
const names = new Set((_nullishCoalesce(result.scene.controls, () => ( []))).map((c) => c.name));
|
|
2008
|
+
const presets = (_nullishCoalesce(effect.presets, () => ( []))).map((p) => ({ name: p.name, values: Object.fromEntries(Object.entries(p.values).filter(([k]) => names.has(k))) })).filter((p) => Object.keys(p.values).length);
|
|
2009
|
+
const scene = { ...result.scene, ...effect.description ? { description: effect.description } : {}, ...presets.length ? { presets } : {} };
|
|
2010
|
+
const notes = [...result.notes];
|
|
2011
|
+
if (effect.trigger) notes.push(`The effect plays on ${effect.trigger}; scenes play through, so the trigger is not kept (pass it back to toFlairVectorEffect).`);
|
|
2012
|
+
return { scene, notes, issues: checkMotionScene(scene) };
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1681
2015
|
// src/animation-editor/controller.ts
|
|
1682
2016
|
var BLANK = { width: 800, height: 450, background: "#ffffff", nodes: [] };
|
|
1683
2017
|
var AnimationEditorController = (_class = class {
|
|
@@ -1700,7 +2034,7 @@ var AnimationEditorController = (_class = class {
|
|
|
1700
2034
|
this.issues = checkMotionScene(this.scene);
|
|
1701
2035
|
this.readOnly = _nullishCoalesce(options.readOnly, () => ( false));
|
|
1702
2036
|
this.onChange = options.onChange;
|
|
1703
|
-
this.player = new (0,
|
|
2037
|
+
this.player = new (0, _chunk2FGRTYJNcjs.AnimationPlayer)({ clock: options.clock, duration: () => compileMotionScene(this.scene).duration, loop: _nullishCoalesce(this.scene.loop, () => ( "none")) });
|
|
1704
2038
|
this.state = this.computeState();
|
|
1705
2039
|
this.connect();
|
|
1706
2040
|
}
|
|
@@ -1745,7 +2079,7 @@ var AnimationEditorController = (_class = class {
|
|
|
1745
2079
|
time: p.time,
|
|
1746
2080
|
playing: p.playing,
|
|
1747
2081
|
loop: p.loop,
|
|
1748
|
-
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call',
|
|
2082
|
+
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _53 => _53(timeline, p.time), 'optionalAccess', _54 => _54.id]), () => ( null)),
|
|
1749
2083
|
selection: this.selection,
|
|
1750
2084
|
readOnly: this.readOnly,
|
|
1751
2085
|
error: this.error,
|
|
@@ -1784,7 +2118,7 @@ var AnimationEditorController = (_class = class {
|
|
|
1784
2118
|
this.applying = false;
|
|
1785
2119
|
}
|
|
1786
2120
|
this.notify();
|
|
1787
|
-
_optionalChain([this, 'access',
|
|
2121
|
+
_optionalChain([this, 'access', _55 => _55.onChange, 'optionalCall', _56 => _56(scene)]);
|
|
1788
2122
|
}
|
|
1789
2123
|
commit(label, next) {
|
|
1790
2124
|
const before = this.scene;
|
|
@@ -1924,10 +2258,29 @@ var MS = (what) => ({ type: "number", minimum: 0, description: `${what} in milli
|
|
|
1924
2258
|
var FRACTION = (what) => ({ type: "number", minimum: 0, maximum: 1, description: what });
|
|
1925
2259
|
var POINT = (what) => object({ x: { type: "number", description: "Document units." }, y: { type: "number", description: "Document units." } }, ["x", "y"], what);
|
|
1926
2260
|
var EASE = {
|
|
1927
|
-
description: `Easing: a preset (${
|
|
2261
|
+
description: `Easing: a preset (${_chunk2FHLHZALcjs.ANIMATION_EASING_PRESETS.join(", ")}), { "type": "cubic-bezier", "x1", "y1", "x2", "y2" }, { "type": "spring", \u2026 } or { "type": "elastic", \u2026 }. The spring presets are Figma's: gentle, quick, bouncy, slow. A command with a spring and no "duration" lasts until the spring settles. Default: a cubic ease-out for entrances, cubic ease-in-out for moves.`,
|
|
1928
2262
|
anyOf: [
|
|
1929
|
-
{ type: "string", enum: [...
|
|
1930
|
-
object({ type: { const: "cubic-bezier", description: "Curve kind." }, x1: { type: "number", description: "Out handle x (0\u20131)." }, y1: { type: "number", description: "Out handle y." }, x2: { type: "number", description: "In handle x (0\u20131)." }, y2: { type: "number", description: "In handle y." } }, ["type", "x1", "y1", "x2", "y2"])
|
|
2263
|
+
{ type: "string", enum: [..._chunk2FHLHZALcjs.ANIMATION_EASING_PRESETS] },
|
|
2264
|
+
object({ type: { const: "cubic-bezier", description: "Curve kind." }, x1: { type: "number", description: "Out handle x (0\u20131)." }, y1: { type: "number", description: "Out handle y." }, x2: { type: "number", description: "In handle x (0\u20131)." }, y2: { type: "number", description: "In handle y." } }, ["type", "x1", "y1", "x2", "y2"]),
|
|
2265
|
+
object(
|
|
2266
|
+
{
|
|
2267
|
+
type: { const: "spring", description: "A damped spring (may overshoot)." },
|
|
2268
|
+
stiffness: { type: "number", exclusiveMinimum: 0, description: "Stiffness (default 170; quick 300, bouncy 600)." },
|
|
2269
|
+
damping: { type: "number", minimum: 0, description: "Damping (default 26; lower bounces more)." },
|
|
2270
|
+
mass: { type: "number", exclusiveMinimum: 0, description: "Mass (default 1)." },
|
|
2271
|
+
velocity: { type: "number", description: "Starting speed, in changes per second (default 0)." }
|
|
2272
|
+
},
|
|
2273
|
+
["type"]
|
|
2274
|
+
),
|
|
2275
|
+
object(
|
|
2276
|
+
{
|
|
2277
|
+
type: { const: "elastic", description: "A decaying wobble." },
|
|
2278
|
+
amplitude: { type: "number", minimum: 0, description: "Overshoot factor (default 1)." },
|
|
2279
|
+
period: { type: "number", exclusiveMinimum: 0, description: "Wobble period as a fraction of the length (default 0.3)." },
|
|
2280
|
+
mode: { type: "string", enum: ["out", "in", "in-out"], description: "Where it wobbles (default out)." }
|
|
2281
|
+
},
|
|
2282
|
+
["type"]
|
|
2283
|
+
)
|
|
1931
2284
|
]
|
|
1932
2285
|
};
|
|
1933
2286
|
var BASE = {
|
|
@@ -1937,8 +2290,16 @@ var BASE = {
|
|
|
1937
2290
|
stagger: MS("Start each further target this much later (default 0)"),
|
|
1938
2291
|
with: { type: "string", enum: ["after", "previous"], description: '"after" (default) starts when the commands before it finish; "previous" starts together with the command before.' },
|
|
1939
2292
|
ease: EASE,
|
|
1940
|
-
note: { type: "string", description: "Why this command is here, in a few words." }
|
|
2293
|
+
note: { type: "string", description: "Why this command is here, in a few words." },
|
|
2294
|
+
repeat: { type: "integer", minimum: 1, maximum: 1e3, description: 'Play it this many times (default 1); "duration" is one cycle. Not for enter or exit.' },
|
|
2295
|
+
repeatMode: { type: "string", enum: [...MOTION_REPEAT_MODES], description: "loop (default) restarts each cycle, mirror plays every other one backwards, offset carries on from where the last ended (rotate by 90 with repeat 4 makes a full turn)." },
|
|
2296
|
+
steps: { type: "number", exclusiveMinimum: 0, maximum: 120, description: `Stepped time: hold on a grid of this many frames per second (12 = "on twos"). Default: the scene's steps, else smooth.` }
|
|
1941
2297
|
};
|
|
2298
|
+
var BLEND = (fallback) => ({
|
|
2299
|
+
type: "string",
|
|
2300
|
+
enum: [...MOTION_BLENDS],
|
|
2301
|
+
description: `"add" makes it a layer over the pose that stacks with other changes (a shake on a slide); "replace" makes it a change the next one takes over from (default ${fallback}).`
|
|
2302
|
+
});
|
|
1942
2303
|
var command = (type, description, extra = {}, required = []) => object({ type: { const: type, description }, ...BASE, ...extra }, ["type", "targets", ...required], description);
|
|
1943
2304
|
var MOTION_COMMAND_SCHEMA = {
|
|
1944
2305
|
description: `A command (one of ${MOTION_COMMAND_TYPES.join(", ")}). Commands in a shot play one after another unless "with": "previous".`,
|
|
@@ -1961,9 +2322,9 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
1961
2322
|
distance: { type: "number", description: "For slide: document units (default 40)." }
|
|
1962
2323
|
}),
|
|
1963
2324
|
command("draw", "Draws strokes on (or off) to a fraction of their length.", { to: FRACTION("Fraction drawn at the end (default 1)."), from: FRACTION("Fraction drawn at the start (default: what is drawn now).") }),
|
|
1964
|
-
command("move", "Moves targets by an offset or so their centre lands on a point.", { by: POINT("Offset in document units."), to: POINT("Point (document coordinates) for the centre.") }),
|
|
1965
|
-
command("rotate", "Turns targets about their centre (degrees, clockwise).", { by: { type: "number", description: "Degrees to turn by." }, to: { type: "number", description: "Angle to turn to, in degrees from rest." } }),
|
|
1966
|
-
command("scale", "Scales targets about their centre (1 = rest size).", { to: { description: "A factor, or { x, y } factors.", anyOf: [{ type: "number" }, POINT("Factors per axis.")] } }, ["to"]),
|
|
2325
|
+
command("move", "Moves targets by an offset or so their centre lands on a point.", { blend: BLEND("replace"), by: POINT("Offset in document units."), to: POINT("Point (document coordinates) for the centre.") }),
|
|
2326
|
+
command("rotate", "Turns targets about their centre (degrees, clockwise).", { blend: BLEND("replace"), by: { type: "number", description: "Degrees to turn by." }, to: { type: "number", description: "Angle to turn to, in degrees from rest." } }),
|
|
2327
|
+
command("scale", "Scales targets about their centre (1 = rest size).", { blend: BLEND("replace"), to: { description: "A factor, or { x, y } factors.", anyOf: [{ type: "number" }, POINT("Factors per axis.")] }, geometric: { type: "boolean", description: "Grow by a steady factor, which reads as an even zoom (default false)." } }, ["to"]),
|
|
1967
2328
|
command("fade", "Changes opacity.", { to: FRACTION("Opacity at the end (0\u20131).") }, ["to"]),
|
|
1968
2329
|
command("style", "Blends solid fill / stroke colours (in OKLab) and stroke width. On a group it changes every path in it.", {
|
|
1969
2330
|
fill: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
|
|
@@ -1977,15 +2338,17 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
1977
2338
|
from: FRACTION("Where to start along the path (default 0)."),
|
|
1978
2339
|
to: FRACTION("Where to end along the path (default 1).")
|
|
1979
2340
|
}, ["path"]),
|
|
1980
|
-
command("pulse", "Scales up and back to draw the eye.", { amount: { type: "number", description: "Extra scale at the peak (default 0.15)." }, count: { type: "integer", minimum: 1, description: "Pulses (default 1)." } }),
|
|
2341
|
+
command("pulse", "Scales up and back to draw the eye.", { blend: BLEND("add"), amount: { type: "number", description: "Extra scale at the peak (default 0.15)." }, count: { type: "integer", minimum: 1, description: "Pulses (default 1)." } }),
|
|
1981
2342
|
command("shake", "Shakes side to side (or up and down), settling.", {
|
|
2343
|
+
blend: BLEND("add"),
|
|
1982
2344
|
amount: { type: "number", description: "Document units (default 8)." },
|
|
1983
2345
|
count: { type: "integer", minimum: 1, description: "Shakes (default 3)." },
|
|
1984
2346
|
axis: { type: "string", enum: ["horizontal", "vertical"], description: "Default horizontal." }
|
|
1985
2347
|
}),
|
|
1986
|
-
command("teeter", "Rocks about the centre either way, settling.", { angle: { type: "number", description: "Degrees either way (default 8)." }, count: { type: "integer", minimum: 1, description: "Rocks (default 3)." } }),
|
|
1987
|
-
command("wave", "Bobs up and down without settling, like something floating (default 1000 ms).", { amount: { type: "number", description: "Height in document units (default 6)." }, count: { type: "integer", minimum: 1, description: "Bobs (default 2)." } }),
|
|
2348
|
+
command("teeter", "Rocks about the centre either way, settling.", { blend: BLEND("add"), angle: { type: "number", description: "Degrees either way (default 8)." }, count: { type: "integer", minimum: 1, description: "Rocks (default 3)." } }),
|
|
2349
|
+
command("wave", "Bobs up and down without settling, like something floating (default 1000 ms).", { blend: BLEND("add"), amount: { type: "number", description: "Height in document units (default 6)." }, count: { type: "integer", minimum: 1, description: "Bobs (default 2)." } }),
|
|
1988
2350
|
command("wiggle", "Wanders about its place as smooth seeded noise, easing out of and back to rest (default 1500 ms). The same seed always wanders the same way.", {
|
|
2351
|
+
blend: BLEND("add"),
|
|
1989
2352
|
amount: { type: "number", description: "Up to about this far, in document units (default 6)." },
|
|
1990
2353
|
frequency: { type: "number", exclusiveMinimum: 0, description: "Wanders per second, in Hz (default 3)." },
|
|
1991
2354
|
octaves: { type: "integer", minimum: 1, maximum: 8, description: "Layers of finer detail (default 2)." },
|
|
@@ -2009,11 +2372,12 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
2009
2372
|
)
|
|
2010
2373
|
]
|
|
2011
2374
|
};
|
|
2375
|
+
var GEOMETRIC_CAMERA = { type: "boolean", description: "Zoom at a steady rate, so a big zoom does not rush at the start (default false)." };
|
|
2012
2376
|
var CAMERA = {
|
|
2013
2377
|
description: `Where the camera looks: a rectangle { x, y, width, height } in document units, or { frame: "<node id>", padding } to frame a node (fitted to the artwork's shape). It eases there over "ms" (default 1000); the first shot cuts.`,
|
|
2014
2378
|
anyOf: [
|
|
2015
|
-
object({ x: { type: "number", description: "Left." }, y: { type: "number", description: "Top." }, width: { type: "number", exclusiveMinimum: 0, description: "Width." }, height: { type: "number", exclusiveMinimum: 0, description: "Height." }, ease: EASE, ms: MS("Camera move length") }, ["x", "y", "width", "height"]),
|
|
2016
|
-
object({ frame: { type: "string", minLength: 1, description: "Node id to frame." }, padding: { type: "number", description: "Margin around it (default 24)." }, ease: EASE, ms: MS("Camera move length") }, ["frame"])
|
|
2379
|
+
object({ x: { type: "number", description: "Left." }, y: { type: "number", description: "Top." }, width: { type: "number", exclusiveMinimum: 0, description: "Width." }, height: { type: "number", exclusiveMinimum: 0, description: "Height." }, ease: EASE, ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["x", "y", "width", "height"]),
|
|
2380
|
+
object({ frame: { type: "string", minLength: 1, description: "Node id to frame." }, padding: { type: "number", description: "Margin around it (default 24)." }, ease: EASE, ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["frame"])
|
|
2017
2381
|
]
|
|
2018
2382
|
};
|
|
2019
2383
|
var SHOT_FIELDS = {
|
|
@@ -2039,6 +2403,7 @@ var SETTINGS = {
|
|
|
2039
2403
|
description: { type: ["string", "null"], description: "What it shows; null clears." },
|
|
2040
2404
|
loop: { type: "string", enum: ["none", "loop", "ping-pong"], description: "Playback past the end (default none)." },
|
|
2041
2405
|
fps: { type: "number", minimum: 1, maximum: 120, description: "Sampling rate for exports (default 30)." },
|
|
2406
|
+
steps: { anyOf: [{ type: "number", exclusiveMinimum: 0, maximum: 120 }, { type: "null" }], description: 'Stepped time for every command without its own: changes hold on a grid of this many frames per second (12 = "on twos" at 24 fps) for a hand-drawn look; null makes it smooth again (default).' },
|
|
2042
2407
|
target: { anyOf: [{ type: "array", items: { type: "number", minimum: 0 }, minItems: 2, maxItems: 2 }, { type: "null" }], description: "Wanted length [min, max] in seconds; null clears." }
|
|
2043
2408
|
};
|
|
2044
2409
|
var EDIT_OP = {
|
|
@@ -2217,6 +2582,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2217
2582
|
}
|
|
2218
2583
|
};
|
|
2219
2584
|
const CURVES_DESCRIPTION = "Write cubic-bezier easings (ease, ease-in, ease-out, ease-in-out, back eases, custom curves) as one change with ease: [x1, y1, x2, y2] (default true). Needs Flair 0.36 or later; false samples them into linear steps for older Flair.";
|
|
2585
|
+
const FLAIR_DESCRIPTION = "The Flair version to export for (default 0.39): springs and stepped time need 0.39, behaviours 0.38, cubic-bezier curves 0.36; older versions get those sampled into linear steps.";
|
|
2220
2586
|
const BEHAVIORS_DESCRIPTION = "Write pulses, shakes, teeters, waves, wiggles and colour pulses as one change with a Flair behavior, so they play exactly (default true; needs Flair 0.38 or later). False samples them into linear steps for older Flair.";
|
|
2221
2587
|
const exportFlairMotion = {
|
|
2222
2588
|
name: "export_flair_motion",
|
|
@@ -2225,10 +2591,11 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2225
2591
|
inputSchema: object({
|
|
2226
2592
|
fps: { type: "number", minimum: 1, maximum: 120, description: "Sampling rate for changes Flair cannot express exactly (default: the scene's fps, else 30)." },
|
|
2227
2593
|
curves: { type: "boolean", description: CURVES_DESCRIPTION },
|
|
2228
|
-
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION }
|
|
2594
|
+
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION },
|
|
2595
|
+
flair: { type: "string", pattern: "^\\d+\\.\\d+(\\.\\d+)?$", description: FLAIR_DESCRIPTION }
|
|
2229
2596
|
}),
|
|
2230
2597
|
annotations: { title: "Export as Flair vector motion", ...READ },
|
|
2231
|
-
handler: ({ fps, curves, behaviors }) => controller.toFlairMotion({ ...fps ? { fps } : {}, ...curves === void 0 ? {} : { curves }, ...behaviors === void 0 ? {} : { behaviors } })
|
|
2598
|
+
handler: ({ fps, curves, behaviors, flair }) => controller.toFlairMotion({ ...fps ? { fps } : {}, ...curves === void 0 ? {} : { curves }, ...behaviors === void 0 ? {} : { behaviors }, ...flair ? { flair } : {} })
|
|
2232
2599
|
};
|
|
2233
2600
|
const exportFlairEffect = {
|
|
2234
2601
|
name: "export_flair_effect",
|
|
@@ -2241,7 +2608,8 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2241
2608
|
category: { type: "string", minLength: 1, description: "Flair catalog category, e.g. icon, loader, ui, data, text, morph (default icon)." },
|
|
2242
2609
|
tags: { type: "array", items: { type: "string" }, description: "Search tags (default none)." },
|
|
2243
2610
|
curves: { type: "boolean", description: CURVES_DESCRIPTION },
|
|
2244
|
-
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION }
|
|
2611
|
+
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION },
|
|
2612
|
+
flair: { type: "string", pattern: "^\\d+\\.\\d+(\\.\\d+)?$", description: FLAIR_DESCRIPTION }
|
|
2245
2613
|
}),
|
|
2246
2614
|
annotations: { title: "Export as a Flair effect", ...READ },
|
|
2247
2615
|
handler: (args) => controller.toFlairEffect(args)
|
|
@@ -2255,13 +2623,41 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2255
2623
|
handler: ({ svg }) => {
|
|
2256
2624
|
let artwork;
|
|
2257
2625
|
try {
|
|
2258
|
-
artwork =
|
|
2626
|
+
artwork = _chunkYJLCBA7Vcjs.parseVectorSvg.call(void 0, svg);
|
|
2259
2627
|
} catch (error) {
|
|
2260
2628
|
throw new Error(`The SVG could not be read: ${error.message}. Nothing was changed.`);
|
|
2261
2629
|
}
|
|
2262
2630
|
return apply({ op: "set_artwork", artwork }, "Replace artwork", (s) => ({ elements: describeMotionElements(s) }));
|
|
2263
2631
|
}
|
|
2264
2632
|
};
|
|
2633
|
+
const importFlairEffect = {
|
|
2634
|
+
name: "import_flair_effect",
|
|
2635
|
+
title: "Import a Flair effect",
|
|
2636
|
+
description: "Replaces the whole animation with a Flair vector effect or SvgMotion (one undo step): its SVG becomes the artwork, {{name: color}} placeholders become colour controls, and each Flair step becomes a shot of commands (fade, enter, style, move, rotate, scale, draw, follow, pulse, shake, teeter, wave, wiggle, color-pulse). Returns the shots, the elements, notes on anything not carried over and the issues. With dry_run it only reports what the import would give.",
|
|
2637
|
+
inputSchema: object(
|
|
2638
|
+
{
|
|
2639
|
+
effect: { type: "object", description: 'A Flair catalog vector effect { kind: "vector", id, name, motion: { svg, animate }, hold?, presets? }. Give this or "motion".' },
|
|
2640
|
+
motion: { type: "object", description: 'A Flair SvgMotion { svg, animate }. Give this or "effect".' },
|
|
2641
|
+
name: { type: "string", minLength: 1, description: `Name for the scene (default: the effect's id, else "from-flair").` },
|
|
2642
|
+
dry_run: { type: "boolean", description: "Report without replacing anything (default false)." }
|
|
2643
|
+
},
|
|
2644
|
+
[]
|
|
2645
|
+
),
|
|
2646
|
+
annotations: { title: "Import a Flair effect", ...DESTRUCTIVE },
|
|
2647
|
+
handler: ({ effect, motion, name, dry_run = false }) => {
|
|
2648
|
+
if (effect === void 0 === (motion === void 0)) throw new Error('Give exactly one of "effect" (a Flair vector effect) or "motion" (a Flair SvgMotion). Nothing was changed.');
|
|
2649
|
+
let result;
|
|
2650
|
+
try {
|
|
2651
|
+
result = effect !== void 0 ? fromFlairVectorEffect(effect, name ? { name } : {}) : fromFlairSvgMotion(motion, name ? { name } : {});
|
|
2652
|
+
} catch (error) {
|
|
2653
|
+
throw new Error(`The Flair effect could not be imported: ${error.message} Nothing was changed.`);
|
|
2654
|
+
}
|
|
2655
|
+
const report = { notes: result.notes, issues: issueSummary(result.issues), shots: describeMotionShots(result.scene).map(({ id, start, end, commands }) => ({ id, start, end, commands: commands.length })) };
|
|
2656
|
+
if (dry_run) return { dry_run: true, ...report, hint: "Nothing was replaced; call again without dry_run to import." };
|
|
2657
|
+
const applied = controller.apply({ op: "replace_scene", scene: result.scene }, "Import Flair effect");
|
|
2658
|
+
return outcome(applied, applied.ok ? { ...report, elements: describeMotionElements(result.scene) } : {});
|
|
2659
|
+
}
|
|
2660
|
+
};
|
|
2265
2661
|
const insertShots = {
|
|
2266
2662
|
name: "insert_shots",
|
|
2267
2663
|
title: "Add shots",
|
|
@@ -2308,7 +2704,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2308
2704
|
inputSchema: object({ shot: SHOT_ID, commands: { type: "array", items: MOTION_COMMAND_SCHEMA, minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the run (default: the end)." } }, ["shot", "commands"]),
|
|
2309
2705
|
annotations: { title: "Add commands to a shot", ...WRITE },
|
|
2310
2706
|
handler: ({ shot, commands, at }) => {
|
|
2311
|
-
const before = _nullishCoalesce(_optionalChain([scene, 'call',
|
|
2707
|
+
const before = _nullishCoalesce(_optionalChain([scene, 'call', _57 => _57(), 'access', _58 => _58.shots, 'access', _59 => _59.find, 'call', _60 => _60((s) => s.id === shot), 'optionalAccess', _61 => _61.run, 'access', _62 => _62.length]), () => ( 0));
|
|
2312
2708
|
const first = _nullishCoalesce(at, () => ( before));
|
|
2313
2709
|
return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
|
|
2314
2710
|
const shots = describeMotionShots(s);
|
|
@@ -2344,7 +2740,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2344
2740
|
const setSettings = {
|
|
2345
2741
|
name: "set_animation_settings",
|
|
2346
2742
|
title: "Change animation settings",
|
|
2347
|
-
description: "Sets the name, description, loop mode, export frame rate or target length. Returns the timing.",
|
|
2743
|
+
description: "Sets the name, description, loop mode, export frame rate, stepped time or target length. Returns the timing.",
|
|
2348
2744
|
inputSchema: object(SETTINGS),
|
|
2349
2745
|
annotations: { title: "Change animation settings", ...WRITE_IDEMPOTENT },
|
|
2350
2746
|
handler: (args) => apply({ op: "set_settings", ...args }, "Change settings")
|
|
@@ -2423,7 +2819,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
2423
2819
|
}
|
|
2424
2820
|
};
|
|
2425
2821
|
const reads = [getAnimation, getShot, findElements, checkAnimation, renderFrame, exportFlairMotion, exportFlairEffect, seekAnimation];
|
|
2426
|
-
const writes = [setArtworkSvg, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, setSettings, setControls, editAnimation, writeAnimation, undo, redo];
|
|
2822
|
+
const writes = [setArtworkSvg, importFlairEffect, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, setSettings, setControls, editAnimation, writeAnimation, undo, redo];
|
|
2427
2823
|
return {
|
|
2428
2824
|
id: _nullishCoalesce(options.id, () => ( "animation")),
|
|
2429
2825
|
namespace: options.namespace,
|
|
@@ -2458,11 +2854,15 @@ Commands
|
|
|
2458
2854
|
- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting "scale".
|
|
2459
2855
|
- morph turns a shape into another node's shape (keep the target hidden); follow moves along a path node (with "rotate", moves made meanwhile turn with the path).
|
|
2460
2856
|
- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or "axis": "vertical"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).
|
|
2857
|
+
- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale "blend": "add" to stack them too (what they add stays); "blend": "replace" makes a change take over instead.
|
|
2858
|
+
- Any command but enter and exit can "repeat" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); "duration" is one cycle.
|
|
2859
|
+
- Springs ("spring-gentle", "spring-quick", "spring-bouncy", "spring-slow" or { "type": "spring", \u2026 }) feel physical; leave "duration" out and the spring sets it.
|
|
2860
|
+
- "steps": 12 (on a command, or for the whole scene with set_animation_settings) holds poses "on twos" for a hand-drawn look. "geometric": true on scale or a camera zooms at an even rate.
|
|
2461
2861
|
- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's "flairPrimitive"), and emphasis, reveals and follows export to Flair exactly.
|
|
2462
2862
|
- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).
|
|
2463
2863
|
|
|
2464
2864
|
Working method
|
|
2465
|
-
1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id).
|
|
2865
|
+
1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).
|
|
2466
2866
|
2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).
|
|
2467
2867
|
3. check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result.
|
|
2468
2868
|
4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.
|
|
@@ -2540,5 +2940,16 @@ Keep motion purposeful: one thing moving at a time reads best, ease-out for arri
|
|
|
2540
2940
|
|
|
2541
2941
|
|
|
2542
2942
|
|
|
2543
|
-
|
|
2943
|
+
|
|
2944
|
+
|
|
2945
|
+
|
|
2946
|
+
|
|
2947
|
+
|
|
2948
|
+
|
|
2949
|
+
|
|
2950
|
+
|
|
2951
|
+
|
|
2952
|
+
|
|
2953
|
+
|
|
2954
|
+
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_COMMAND_SCHEMA = MOTION_COMMAND_SCHEMA; exports.MOTION_COMMAND_TYPES = MOTION_COMMAND_TYPES; 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_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 = MOTION_ISSUE_CODES; exports.MOTION_MIN_CHANGE_MS = MOTION_MIN_CHANGE_MS; exports.MOTION_REPEAT_MODES = MOTION_REPEAT_MODES; exports.MOTION_SPLIT_ORIENTATIONS = MOTION_SPLIT_ORIENTATIONS; exports.MotionSceneFormatError = MotionSceneFormatError; exports.activeSegment = activeSegment; exports.applyMotionControlValues = applyMotionControlValues; exports.applyMotionEdits = applyMotionEdits; exports.checkMotionScene = checkMotionScene; exports.commandShapeProblems = commandShapeProblems; exports.compileMotionScene = compileMotionScene; exports.createAnimationEditorToolProvider = createAnimationEditorToolProvider; exports.createMotionScene = createMotionScene; exports.describeMotionElements = describeMotionElements; exports.describeMotionShots = describeMotionShots; exports.fitMotionRect = fitMotionRect; exports.flairAtLeast = flairAtLeast; exports.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.freshShotId = freshShotId; exports.fromFlairSvgMotion = fromFlairSvgMotion; exports.fromFlairVectorEffect = fromFlairVectorEffect; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.motionAddTrackKey = motionAddTrackKey; exports.motionClipAttrs = motionClipAttrs; exports.motionCommandDuration = motionCommandDuration; exports.motionCommandRepeat = motionCommandRepeat; exports.motionCycleDuration = motionCycleDuration; exports.motionFlairPrimitive = motionFlairPrimitive; exports.motionFollowRoute = motionFollowRoute; exports.motionFrameAt = motionFrameAt; exports.motionFrameToSvg = motionFrameToSvg; exports.motionIssue = motionIssue; exports.motionIssueKey = motionIssueKey; exports.motionIssueLine = motionIssueLine; exports.motionNodeClips = motionNodeClips; exports.motionNodeOffset = motionNodeOffset; exports.motionPathLength = motionPathLength; exports.motionRestValue = motionRestValue; exports.motionRevealClip = motionRevealClip; exports.motionRevealPadding = motionRevealPadding; exports.motionSceneShapeProblems = motionSceneShapeProblems; exports.motionSceneToJson = motionSceneToJson; exports.motionShotAt = motionShotAt; exports.motionTrackKey = motionTrackKey; exports.namedWithSuggestion = namedWithSuggestion; exports.parseMotionScene = parseMotionScene; exports.resolveMotionCamera = resolveMotionCamera; exports.segmentProgress = segmentProgress; exports.segmentValue = segmentValue; exports.shotShapeProblems = shotShapeProblems; exports.suggestName = suggestName; exports.toFlairEffectDocument = toFlairEffectDocument; exports.toFlairSvgMotion = toFlairSvgMotion; exports.toFlairVectorEffect = toFlairVectorEffect; exports.trackValue = trackValue; exports.withMotionLayers = withMotionLayers; exports.withViewBox = withViewBox;
|
|
2544
2955
|
//# sourceMappingURL=index.cjs.map
|