@pixerate/editor 0.56.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/index.cjs +15 -1
- package/dist/animation/index.cjs.map +1 -1
- package/dist/animation/index.d.cts +1 -0
- package/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.js +14 -0
- package/dist/animation-editor/index.cjs +452 -129
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +315 -35
- package/dist/animation-editor/index.d.ts +315 -35
- package/dist/animation-editor/index.js +411 -88
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/behavior-Ymbld6jL.d.cts +60 -0
- package/dist/behavior-Ymbld6jL.d.ts +60 -0
- package/dist/chunk-3NYXDBBW.js +122 -0
- package/dist/chunk-3NYXDBBW.js.map +1 -0
- package/dist/{chunk-XCXQDPID.cjs → chunk-FKONE6AO.cjs} +23 -8
- package/dist/chunk-FKONE6AO.cjs.map +1 -0
- package/dist/{chunk-NONDTTH7.js → chunk-PYMV7HLI.js} +16 -1
- package/dist/{chunk-NONDTTH7.js.map → chunk-PYMV7HLI.js.map} +1 -1
- package/dist/chunk-ZCNLBRT6.cjs +122 -0
- package/dist/chunk-ZCNLBRT6.cjs.map +1 -0
- package/dist/{svg-CPK82TtU.d.ts → svg-Dh17jCyA.d.ts} +22 -1
- package/dist/{svg-CLg2zqZA.d.cts → svg-ymShkNtu.d.cts} +22 -1
- package/dist/vector/index.cjs +471 -471
- package/dist/vector/index.d.cts +2 -2
- package/dist/vector/index.d.ts +2 -2
- package/dist/vector/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-XCXQDPID.cjs.map +0 -1
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
var
|
|
20
|
+
var _chunkFKONE6AOcjs = require('../chunk-FKONE6AO.cjs');
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
@@ -29,6 +29,10 @@ var _chunkO2UH7LZEcjs = require('../chunk-O2UH7LZE.cjs');
|
|
|
29
29
|
var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
|
|
33
|
+
var _chunkZCNLBRT6cjs = require('../chunk-ZCNLBRT6.cjs');
|
|
34
|
+
|
|
35
|
+
|
|
32
36
|
var _chunkO4ONBPZWcjs = require('../chunk-O4ONBPZW.cjs');
|
|
33
37
|
|
|
34
38
|
|
|
@@ -42,6 +46,7 @@ var _chunkA6PHCAGXcjs = require('../chunk-A6PHCAGX.cjs');
|
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
|
|
49
|
+
|
|
45
50
|
var _chunkXZ4L3R4Kcjs = require('../chunk-XZ4L3R4K.cjs');
|
|
46
51
|
|
|
47
52
|
// src/animation-editor/types.ts
|
|
@@ -58,11 +63,17 @@ var MOTION_COMMAND_TYPES = [
|
|
|
58
63
|
"follow",
|
|
59
64
|
"pulse",
|
|
60
65
|
"shake",
|
|
66
|
+
"teeter",
|
|
67
|
+
"wave",
|
|
68
|
+
"wiggle",
|
|
69
|
+
"color-pulse",
|
|
61
70
|
"effect",
|
|
62
71
|
"wait"
|
|
63
72
|
];
|
|
64
|
-
var MOTION_ENTER_STYLES = ["fade", "pop", "grow", "slide", "draw"];
|
|
65
|
-
var MOTION_EXIT_STYLES = ["fade", "shrink", "slide", "undraw"];
|
|
73
|
+
var MOTION_ENTER_STYLES = ["fade", "pop", "grow", "slide", "draw", "zoom", "rise", "wipe", "iris", "split"];
|
|
74
|
+
var MOTION_EXIT_STYLES = ["fade", "shrink", "slide", "undraw", "wipe"];
|
|
75
|
+
var MOTION_IRIS_SHAPES = ["circle", "box"];
|
|
76
|
+
var MOTION_SPLIT_ORIENTATIONS = ["horizontal", "vertical"];
|
|
66
77
|
var MOTION_DIRECTIONS = ["up", "down", "left", "right"];
|
|
67
78
|
var MOTION_DEFAULT_DURATIONS = {
|
|
68
79
|
enter: 600,
|
|
@@ -76,12 +87,37 @@ var MOTION_DEFAULT_DURATIONS = {
|
|
|
76
87
|
follow: 1400,
|
|
77
88
|
pulse: 600,
|
|
78
89
|
shake: 500,
|
|
90
|
+
teeter: 600,
|
|
91
|
+
wave: 1e3,
|
|
92
|
+
wiggle: 1500,
|
|
93
|
+
"color-pulse": 600,
|
|
79
94
|
effect: 900
|
|
80
95
|
};
|
|
81
96
|
var MOTION_DEFAULT_HOLD = 600;
|
|
82
97
|
var MOTION_CAMERA_MS = 1e3;
|
|
83
98
|
var MOTION_DRAW_MS_PER_UNIT = 1.5;
|
|
84
99
|
var MOTION_DRAW_RANGE = [500, 2500];
|
|
100
|
+
function motionFlairPrimitive(command2) {
|
|
101
|
+
switch (command2.type) {
|
|
102
|
+
case "enter":
|
|
103
|
+
return `entrance.${_nullishCoalesce(command2.style, () => ( "fade"))}`;
|
|
104
|
+
case "exit":
|
|
105
|
+
return `exit.${_nullishCoalesce(command2.style, () => ( "fade"))}`;
|
|
106
|
+
case "pulse":
|
|
107
|
+
case "shake":
|
|
108
|
+
case "teeter":
|
|
109
|
+
case "wave":
|
|
110
|
+
case "wiggle":
|
|
111
|
+
case "color-pulse":
|
|
112
|
+
return `emphasis.${command2.type}`;
|
|
113
|
+
case "rotate":
|
|
114
|
+
return command2.by !== void 0 ? "emphasis.spin" : void 0;
|
|
115
|
+
case "follow":
|
|
116
|
+
return "path.follow";
|
|
117
|
+
default:
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
85
121
|
|
|
86
122
|
// src/animation-editor/issues.ts
|
|
87
123
|
var MOTION_ISSUE_CODES = {
|
|
@@ -90,13 +126,14 @@ var MOTION_ISSUE_CODES = {
|
|
|
90
126
|
"unknown-target": { severity: "error", wording: "A command names a node the artwork does not have." },
|
|
91
127
|
"unknown-path": { severity: "error", wording: "A follow command names a path the artwork does not have." },
|
|
92
128
|
"not-a-path": { severity: "error", wording: "A follow path must be a path node, not a group." },
|
|
129
|
+
"reveal-no-box": { severity: "warning", wording: "A wipe, iris or split cannot clip a node with no width or height (a lone straight line), so it fades instead." },
|
|
93
130
|
"unknown-shape": { severity: "error", wording: "A morph names a shape the artwork does not have." },
|
|
94
131
|
"unknown-effect": { severity: "error", wording: "An effect command names an effect the node does not have." },
|
|
95
132
|
"unknown-effect-param": { severity: "error", wording: "An effect command names a parameter that is not a number of that effect." },
|
|
96
133
|
"unknown-frame": { severity: "error", wording: "A camera frames a node the artwork does not have." },
|
|
97
134
|
"invalid-camera": { severity: "error", wording: "A camera rectangle has no area." },
|
|
98
135
|
"invalid-color": { severity: "error", wording: "A colour cannot be read." },
|
|
99
|
-
"paint-not-color": { severity: "warning", wording: "A style command recolours a gradient or empty paint, which only switches at the end." },
|
|
136
|
+
"paint-not-color": { severity: "warning", wording: "A style command recolours a gradient or empty paint, which only switches at the end, or a colour pulse has no solid paint to tint." },
|
|
100
137
|
"overlap": { severity: "warning", wording: "Two commands change the same property of a node at the same time; the later one wins." },
|
|
101
138
|
"enter-visible": { severity: "warning", wording: "A node enters while it is already showing, so it blinks out first." },
|
|
102
139
|
"exit-hidden": { severity: "warning", wording: "A node exits or animates while it is hidden." },
|
|
@@ -164,7 +201,7 @@ var SHOT_KEYS = ["id", "label", "camera", "run", "hold"];
|
|
|
164
201
|
var CAMERA_KEYS = ["x", "y", "width", "height", "frame", "padding", "ease", "ms"];
|
|
165
202
|
var BASE_KEYS = ["type", "targets", "duration", "delay", "stagger", "with", "ease", "note"];
|
|
166
203
|
var COMMAND_KEYS = {
|
|
167
|
-
enter: [...BASE_KEYS, "style", "direction", "distance"],
|
|
204
|
+
enter: [...BASE_KEYS, "style", "direction", "distance", "scale", "shape", "orientation"],
|
|
168
205
|
exit: [...BASE_KEYS, "style", "direction", "distance"],
|
|
169
206
|
draw: [...BASE_KEYS, "from", "to"],
|
|
170
207
|
move: [...BASE_KEYS, "by", "to"],
|
|
@@ -175,7 +212,11 @@ var COMMAND_KEYS = {
|
|
|
175
212
|
morph: [...BASE_KEYS, "into"],
|
|
176
213
|
follow: [...BASE_KEYS, "path", "rotate", "from", "to"],
|
|
177
214
|
pulse: [...BASE_KEYS, "amount", "count"],
|
|
178
|
-
shake: [...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"],
|
|
219
|
+
"color-pulse": [...BASE_KEYS, "color", "paint", "count"],
|
|
179
220
|
effect: [...BASE_KEYS, "effect", "param", "to"],
|
|
180
221
|
wait: ["type", "duration", "with", "note"]
|
|
181
222
|
};
|
|
@@ -222,6 +263,9 @@ function commandShapeProblems(command2, where) {
|
|
|
222
263
|
p(`"style" must be one of ${styles.join(", ")}${typeof command2.style === "string" ? ` (got ${namedWithSuggestion(command2.style, styles)})` : ""}.`);
|
|
223
264
|
if (command2.direction !== void 0 && !MOTION_DIRECTIONS.includes(command2.direction)) p(`"direction" must be one of ${MOTION_DIRECTIONS.join(", ")}.`);
|
|
224
265
|
optionalNumber("distance");
|
|
266
|
+
if (command2.scale !== void 0 && !(isNum(command2.scale) && command2.scale >= 0)) p(`"scale" must be a number \u2265 0 (the starting scale for pop and zoom).`);
|
|
267
|
+
if (command2.shape !== void 0 && !MOTION_IRIS_SHAPES.includes(command2.shape)) p(`"shape" must be one of ${MOTION_IRIS_SHAPES.join(", ")} (the opening of an iris).`);
|
|
268
|
+
if (command2.orientation !== void 0 && !MOTION_SPLIT_ORIENTATIONS.includes(command2.orientation)) p(`"orientation" must be one of ${MOTION_SPLIT_ORIENTATIONS.join(", ")} (the line a split opens from).`);
|
|
225
269
|
break;
|
|
226
270
|
}
|
|
227
271
|
case "draw":
|
|
@@ -263,8 +307,22 @@ function commandShapeProblems(command2, where) {
|
|
|
263
307
|
break;
|
|
264
308
|
case "pulse":
|
|
265
309
|
case "shake":
|
|
310
|
+
case "teeter":
|
|
311
|
+
case "wave":
|
|
312
|
+
case "color-pulse":
|
|
266
313
|
optionalNumber("amount");
|
|
314
|
+
optionalNumber("angle");
|
|
267
315
|
if (command2.count !== void 0 && !(Number.isInteger(command2.count) && command2.count >= 1)) p(`"count" must be a whole number \u2265 1.`);
|
|
316
|
+
if (command2.axis !== void 0 && command2.axis !== "horizontal" && command2.axis !== "vertical") p(`"axis" must be "horizontal" or "vertical".`);
|
|
317
|
+
if (command2.color !== void 0 && typeof command2.color !== "string") p(`"color" must be a CSS colour.`);
|
|
318
|
+
if (command2.paint !== void 0 && command2.paint !== "fill" && command2.paint !== "stroke") p(`"paint" must be "fill" or "stroke".`);
|
|
319
|
+
break;
|
|
320
|
+
case "wiggle":
|
|
321
|
+
optionalNumber("amount");
|
|
322
|
+
optionalNumber("rotate");
|
|
323
|
+
if (command2.frequency !== void 0 && !(isNum(command2.frequency) && command2.frequency > 0)) p(`"frequency" must be a number of Hz > 0.`);
|
|
324
|
+
if (command2.octaves !== void 0 && !(Number.isInteger(command2.octaves) && command2.octaves >= 1 && command2.octaves <= 8)) p(`"octaves" must be a whole number from 1 to 8.`);
|
|
325
|
+
if (command2.seed !== void 0 && !(Number.isInteger(command2.seed) && command2.seed >= 0)) p(`"seed" must be a whole number \u2265 0.`);
|
|
268
326
|
break;
|
|
269
327
|
case "effect":
|
|
270
328
|
if (typeof command2.effect !== "string" || !command2.effect) p(`"effect" must be the id of one of the node's effects.`);
|
|
@@ -354,26 +412,76 @@ function indexMotionNodes(nodes) {
|
|
|
354
412
|
const out = /* @__PURE__ */ new Map();
|
|
355
413
|
const walk = (list, parentWorld, ancestors) => {
|
|
356
414
|
for (const node of list) {
|
|
357
|
-
const local =
|
|
358
|
-
const bounds =
|
|
415
|
+
const local = _chunkFKONE6AOcjs.vectorNodeBounds.call(void 0, node);
|
|
416
|
+
const bounds = _chunkFKONE6AOcjs.vectorNodeBounds.call(void 0, node, parentWorld);
|
|
359
417
|
const center = local ? { x: local.x + local.width / 2, y: local.y + local.height / 2 } : { x: 0, y: 0 };
|
|
360
|
-
if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds });
|
|
361
|
-
if (node.type === "group") walk(node.children,
|
|
418
|
+
if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds, box: local });
|
|
419
|
+
if (node.type === "group") walk(node.children, _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
|
|
362
420
|
}
|
|
363
421
|
};
|
|
364
|
-
walk(nodes,
|
|
422
|
+
walk(nodes, _chunkFKONE6AOcjs.IDENTITY_MATRIX, []);
|
|
365
423
|
indexCache.set(nodes, out);
|
|
366
424
|
return out;
|
|
367
425
|
}
|
|
368
426
|
var solid = (paint) => typeof paint === "string" && paint !== "none" ? paint : void 0;
|
|
369
427
|
function firstPaint(node, key) {
|
|
370
428
|
if (node.type === "path") return solid(node[key]);
|
|
371
|
-
for (const p of
|
|
429
|
+
for (const p of _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node)) {
|
|
372
430
|
const s = solid(p[key]);
|
|
373
431
|
if (s) return s;
|
|
374
432
|
}
|
|
375
433
|
return void 0;
|
|
376
434
|
}
|
|
435
|
+
function strokeReach(node) {
|
|
436
|
+
let reach = 0;
|
|
437
|
+
for (const p of node.type === "path" ? [node] : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node)) {
|
|
438
|
+
if (p.stroke == null || p.stroke === "none") continue;
|
|
439
|
+
const width = _nullishCoalesce(p.strokeWidth, () => ( 1));
|
|
440
|
+
reach = Math.max(reach, p.strokeAlign === "outside" ? width : p.strokeAlign === "inside" ? 0 : width / 2);
|
|
441
|
+
}
|
|
442
|
+
return reach;
|
|
443
|
+
}
|
|
444
|
+
function motionRevealPadding(entry) {
|
|
445
|
+
const box = entry.box;
|
|
446
|
+
if (!box || !(box.width > 0) || !(box.height > 0)) return null;
|
|
447
|
+
const s = strokeReach(entry.node);
|
|
448
|
+
return [Math.min(1, s / box.width + 0.02), Math.min(1, s / box.height + 0.02)];
|
|
449
|
+
}
|
|
450
|
+
var clipRound = (n) => Math.round(n * 1e4) / 1e4 || 0;
|
|
451
|
+
function revealFull(property, [px, py]) {
|
|
452
|
+
return (property === "clipRect" ? [-px, -py, 1 + 2 * px, 1 + 2 * py] : [0.5, 0.5, Math.hypot(0.5 + px, 0.5 + py)]).map(clipRound);
|
|
453
|
+
}
|
|
454
|
+
var OPPOSITE = { up: "down", down: "up", left: "right", right: "left" };
|
|
455
|
+
function motionRevealClip(entry, reveal) {
|
|
456
|
+
const pad = motionRevealPadding(entry);
|
|
457
|
+
if (!pad) return null;
|
|
458
|
+
const [px, py] = pad;
|
|
459
|
+
const [w, h] = [1 + 2 * px, 1 + 2 * py];
|
|
460
|
+
const rect = (from, to) => ({ property: "clipRect", from: from.map(clipRound), to: to.map(clipRound) });
|
|
461
|
+
if (reveal.style === "iris") {
|
|
462
|
+
if (reveal.shape === "box") return rect([0.5, 0.5, 0, 0], [-px, -py, w, h]);
|
|
463
|
+
return { property: "clipCircle", from: [0.5, 0.5, 0], to: revealFull("clipCircle", pad) };
|
|
464
|
+
}
|
|
465
|
+
if (reveal.style === "split") {
|
|
466
|
+
if (reveal.orientation === "vertical") return rect([0.5, -py, 0, h], [-px, -py, w, h]);
|
|
467
|
+
return rect([-px, 0.5, w, 0], [-px, -py, w, h]);
|
|
468
|
+
}
|
|
469
|
+
const direction = _nullishCoalesce(reveal.direction, () => ( "right"));
|
|
470
|
+
if (reveal.hide) {
|
|
471
|
+
const shown = motionRevealClip(entry, { style: "wipe", direction: OPPOSITE[direction] });
|
|
472
|
+
return { ...shown, from: shown.to, to: shown.from };
|
|
473
|
+
}
|
|
474
|
+
switch (direction) {
|
|
475
|
+
case "right":
|
|
476
|
+
return rect([-px, -py, 0, h], [-px, -py, w, h]);
|
|
477
|
+
case "left":
|
|
478
|
+
return rect([1 + px, -py, 0, h], [-px, -py, w, h]);
|
|
479
|
+
case "down":
|
|
480
|
+
return rect([-px, -py, w, 0], [-px, -py, w, h]);
|
|
481
|
+
case "up":
|
|
482
|
+
return rect([-px, 1 + py, w, 0], [-px, -py, w, h]);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
377
485
|
function motionRestValue(entry, property, artwork) {
|
|
378
486
|
const node = _optionalChain([entry, 'optionalAccess', _4 => _4.node]);
|
|
379
487
|
switch (property) {
|
|
@@ -396,11 +504,16 @@ function motionRestValue(entry, property, artwork) {
|
|
|
396
504
|
case "stroke":
|
|
397
505
|
return _nullishCoalesce((node && firstPaint(node, property)), () => ( "transparent"));
|
|
398
506
|
case "strokeWidth": {
|
|
399
|
-
const path = _optionalChain([node, 'optionalAccess', _6 => _6.type]) === "path" ? node : node ?
|
|
507
|
+
const path = _optionalChain([node, 'optionalAccess', _6 => _6.type]) === "path" ? node : node ? _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node)[0] : void 0;
|
|
400
508
|
return _nullishCoalesce(_optionalChain([path, 'optionalAccess', _7 => _7.strokeWidth]), () => ( 1));
|
|
401
509
|
}
|
|
402
510
|
case "shape":
|
|
403
511
|
return _nullishCoalesce(_optionalChain([node, 'optionalAccess', _8 => _8.id]), () => ( ""));
|
|
512
|
+
case "clipRect":
|
|
513
|
+
case "clipCircle": {
|
|
514
|
+
const pad = entry && motionRevealPadding(entry);
|
|
515
|
+
return pad ? revealFull(property, pad) : [];
|
|
516
|
+
}
|
|
404
517
|
case "camera":
|
|
405
518
|
return [0, 0, artwork.width, artwork.height];
|
|
406
519
|
}
|
|
@@ -423,15 +536,13 @@ function interpolateMotionValue(from, to, u) {
|
|
|
423
536
|
function segmentProgress(segment, time) {
|
|
424
537
|
const span = segment.end - segment.start;
|
|
425
538
|
const u = span <= 0 ? 1 : Math.min(1, Math.max(0, (time - segment.start) / span));
|
|
426
|
-
return { u, eased:
|
|
539
|
+
return { u, eased: _chunkXZ4L3R4Kcjs.evaluateEasing.call(void 0, segment.ease, u, span) };
|
|
427
540
|
}
|
|
428
|
-
function segmentValue(segment, time) {
|
|
429
|
-
const {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if (kind === "pulse") return v * (1 + amount * Math.sin(Math.PI * u * count) ** 2);
|
|
434
|
-
return v + amount * Math.sin(2 * Math.PI * u * count) * (1 - u);
|
|
541
|
+
function segmentValue(segment, time, raw = false) {
|
|
542
|
+
const { eased } = segmentProgress(segment, time);
|
|
543
|
+
if (!segment.behavior || raw) return interpolateMotionValue(segment.from, segment.to, eased);
|
|
544
|
+
const p = _chunkZCNLBRT6cjs.behaviorProgress.call(void 0, segment.behavior, eased, _nullishCoalesce(segment.index, () => ( 0)), segment.end - segment.start);
|
|
545
|
+
return typeof segment.from === "string" ? interpolateMotionValue(segment.from, segment.to, Math.min(1, Math.max(0, p))) : interpolateMotionValue(segment.from, segment.to, p);
|
|
435
546
|
}
|
|
436
547
|
function activeSegment(track, time) {
|
|
437
548
|
if (!_optionalChain([track, 'optionalAccess', _12 => _12.length])) return void 0;
|
|
@@ -439,10 +550,10 @@ function activeSegment(track, time) {
|
|
|
439
550
|
for (const s of track) if (s.start <= time && (!found || s.start >= found.start)) found = s;
|
|
440
551
|
return found;
|
|
441
552
|
}
|
|
442
|
-
function trackValue(track, time) {
|
|
553
|
+
function trackValue(track, time, raw = false) {
|
|
443
554
|
if (!_optionalChain([track, 'optionalAccess', _13 => _13.length])) return void 0;
|
|
444
555
|
const s = activeSegment(track, time);
|
|
445
|
-
if (s) return segmentValue(s, time);
|
|
556
|
+
if (s) return segmentValue(s, time, raw);
|
|
446
557
|
let first = track[0];
|
|
447
558
|
for (const t of track) if (t.start < first.start) first = t;
|
|
448
559
|
return first.from;
|
|
@@ -468,12 +579,12 @@ function resolveMotionCamera(camera, scene) {
|
|
|
468
579
|
const r = camera;
|
|
469
580
|
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
470
581
|
}
|
|
471
|
-
function motionPathLength(node, parentWorld =
|
|
582
|
+
function motionPathLength(node, parentWorld = _chunkFKONE6AOcjs.IDENTITY_MATRIX) {
|
|
472
583
|
let longest = 0;
|
|
473
|
-
const paths = node.type === "path" ? [node] :
|
|
584
|
+
const paths = node.type === "path" ? [node] : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node);
|
|
474
585
|
for (const p of paths) {
|
|
475
586
|
try {
|
|
476
|
-
longest = Math.max(longest, _chunkO2UH7LZEcjs.bezierPathLength.call(void 0,
|
|
587
|
+
longest = Math.max(longest, _chunkO2UH7LZEcjs.bezierPathLength.call(void 0, _chunkFKONE6AOcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
|
|
477
588
|
} catch (e2) {
|
|
478
589
|
}
|
|
479
590
|
}
|
|
@@ -581,15 +692,27 @@ function compileMotionScene(scene) {
|
|
|
581
692
|
case "enter": {
|
|
582
693
|
const style = _nullishCoalesce(command2.style, () => ( "fade"));
|
|
583
694
|
const opacity = rest("opacity");
|
|
695
|
+
const reveal = style === "wipe" ? motionRevealClip(entry, { style, direction: command2.direction }) : style === "iris" ? motionRevealClip(entry, { style, shape: command2.shape }) : style === "split" ? motionRevealClip(entry, { style, orientation: command2.orientation }) : null;
|
|
696
|
+
for (const p of ["clipRect", "clipCircle"]) if (p !== _optionalChain([reveal, 'optionalAccess', _15 => _15.property]) && tracks.has(motionTrackKey(node, p))) seg(p, rest(p), "linear", start, start);
|
|
697
|
+
if (reveal) {
|
|
698
|
+
seg("opacity", opacity, "linear", start, start);
|
|
699
|
+
seg(reveal.property, reveal.to, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: reveal.from });
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
584
702
|
if (style === "draw") {
|
|
585
703
|
seg("drawEnd", 1, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, start + duration2 * 0.75, { from: 0 });
|
|
586
704
|
seg("fillOpacity", 1, MOTION_EASE_OUT, start + duration2 * 0.6, end, { from: 0 });
|
|
587
705
|
break;
|
|
588
706
|
}
|
|
589
|
-
if (style === "pop") {
|
|
590
|
-
|
|
591
|
-
seg("
|
|
592
|
-
seg("
|
|
707
|
+
if (style === "pop" || style === "zoom") {
|
|
708
|
+
const from = _nullishCoalesce(command2.scale, () => ( (style === "pop" ? 0.5 : 1.6)));
|
|
709
|
+
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * (style === "pop" ? 0.4 : 0.5), { from: 0 });
|
|
710
|
+
seg("scaleX", 1, _nullishCoalesce(ease, () => ( (style === "pop" ? "ease-out-back" : MOTION_EASE_OUT))), start, end, { from });
|
|
711
|
+
seg("scaleY", 1, _nullishCoalesce(ease, () => ( (style === "pop" ? "ease-out-back" : MOTION_EASE_OUT))), start, end, { from });
|
|
712
|
+
} else if (style === "rise") {
|
|
713
|
+
const y = num("y");
|
|
714
|
+
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * 0.5, { from: 0 });
|
|
715
|
+
seg("y", y, _nullishCoalesce(ease, () => ( "ease-out-back")), start, end, { from: y + (_nullishCoalesce(command2.distance, () => ( 20))) });
|
|
593
716
|
} else if (style === "grow") {
|
|
594
717
|
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * 0.3, { from: 0 });
|
|
595
718
|
seg("scaleX", 1, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: 0 });
|
|
@@ -607,7 +730,9 @@ function compileMotionScene(scene) {
|
|
|
607
730
|
}
|
|
608
731
|
case "exit": {
|
|
609
732
|
const style = _nullishCoalesce(command2.style, () => ( "fade"));
|
|
610
|
-
|
|
733
|
+
const wipe = style === "wipe" ? motionRevealClip(entry, { style, direction: command2.direction, hide: true }) : null;
|
|
734
|
+
if (wipe) seg(wipe.property, wipe.to, _nullishCoalesce(ease, () => ( "ease-in")), start, end, { from: wipe.from });
|
|
735
|
+
else if (style === "undraw") {
|
|
611
736
|
seg("fillOpacity", 0, "ease-in", start, start + duration2 * 0.4);
|
|
612
737
|
seg("drawEnd", 0, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
613
738
|
} else if (style === "shrink") {
|
|
@@ -623,20 +748,18 @@ function compileMotionScene(scene) {
|
|
|
623
748
|
} else seg("opacity", 0, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
624
749
|
break;
|
|
625
750
|
}
|
|
626
|
-
case "draw":
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
seg("drawEnd", _nullishCoalesce(command2.to, () => ( 1)), _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, command2.from !== void 0 ? { from: command2.from } : drawn ? {} : { from: 0 });
|
|
630
|
-
break;
|
|
631
|
-
}
|
|
751
|
+
case "draw": {
|
|
752
|
+
const drawn = tracks.has(motionTrackKey(node, "drawEnd"));
|
|
753
|
+
seg("drawEnd", _nullishCoalesce(command2.to, () => ( 1)), _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, command2.from !== void 0 ? { from: command2.from } : drawn ? {} : { from: 0 });
|
|
632
754
|
break;
|
|
755
|
+
}
|
|
633
756
|
case "move": {
|
|
634
757
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
635
|
-
let dx = _nullishCoalesce(_optionalChain([command2, 'access',
|
|
636
|
-
let dy = _nullishCoalesce(_optionalChain([command2, 'access',
|
|
758
|
+
let dx = _nullishCoalesce(_optionalChain([command2, 'access', _16 => _16.by, 'optionalAccess', _17 => _17.x]), () => ( 0));
|
|
759
|
+
let dy = _nullishCoalesce(_optionalChain([command2, 'access', _18 => _18.by, 'optionalAccess', _19 => _19.y]), () => ( 0));
|
|
637
760
|
if (command2.to) {
|
|
638
|
-
const inv =
|
|
639
|
-
const target =
|
|
761
|
+
const inv = _chunkFKONE6AOcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
762
|
+
const target = _chunkFKONE6AOcjs.applyMatrix.call(void 0, inv, command2.to);
|
|
640
763
|
dx = target.x - (entry.center.x + num("x"));
|
|
641
764
|
dy = target.y - (entry.center.y + num("y"));
|
|
642
765
|
}
|
|
@@ -667,14 +790,35 @@ function compileMotionScene(scene) {
|
|
|
667
790
|
case "follow":
|
|
668
791
|
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)) });
|
|
669
792
|
break;
|
|
793
|
+
// Emphasis: a change toward a peak that a behaviour swings round (as Flair's primitives do).
|
|
670
794
|
case "pulse": {
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
seg("
|
|
795
|
+
const behavior = { type: "pulse", count: _nullishCoalesce(command2.count, () => ( 1)) };
|
|
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 });
|
|
674
799
|
break;
|
|
675
800
|
}
|
|
676
|
-
case "shake":
|
|
677
|
-
|
|
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
|
+
}
|
|
806
|
+
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
|
+
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
|
+
case "wiggle": {
|
|
813
|
+
const behavior = { type: "wriggle", frequency: _nullishCoalesce(command2.frequency, () => ( 3)), octaves: _nullishCoalesce(command2.octaves, () => ( 2)), seed: command2.seed || _chunkZCNLBRT6cjs.motionSeedFromId.call(void 0, node) };
|
|
814
|
+
const amount = _nullishCoalesce(command2.amount, () => ( 6));
|
|
815
|
+
seg("x", num("x") + amount, _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior, index: 0 });
|
|
816
|
+
seg("y", num("y") + amount, _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior, index: 1 });
|
|
817
|
+
if (command2.rotate) seg("rotation", num("rotation") + command2.rotate, _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior, index: 2 });
|
|
818
|
+
break;
|
|
819
|
+
}
|
|
820
|
+
case "color-pulse":
|
|
821
|
+
seg(_nullishCoalesce(command2.paint, () => ( "fill")), _nullishCoalesce(command2.color, () => ( "#f59e0b")), _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior: { type: "pulse", count: _nullishCoalesce(command2.count, () => ( 1)) } });
|
|
678
822
|
break;
|
|
679
823
|
case "effect":
|
|
680
824
|
seg(`effect:${command2.effect}:${command2.param}`, command2.to, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
@@ -697,7 +841,7 @@ var MOTION_DRAW_EFFECT_ID = "~draw";
|
|
|
697
841
|
var TRANSFORM_PROPS = ["x", "y", "rotation", "scaleX", "scaleY", "follow"];
|
|
698
842
|
var tidy = (v) => Math.round(v * 1e6) / 1e6 || 0;
|
|
699
843
|
function applyMotionControlValues(scene, values) {
|
|
700
|
-
if (!values || !_optionalChain([scene, 'access',
|
|
844
|
+
if (!values || !_optionalChain([scene, 'access', _20 => _20.controls, 'optionalAccess', _21 => _21.length])) return scene;
|
|
701
845
|
const map = /* @__PURE__ */ new Map();
|
|
702
846
|
for (const control of scene.controls) {
|
|
703
847
|
const value = values[control.name];
|
|
@@ -733,17 +877,17 @@ function morphBetween(a, b) {
|
|
|
733
877
|
let inner = morphCache.get(a);
|
|
734
878
|
if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
|
|
735
879
|
let morph = inner.get(b);
|
|
736
|
-
if (!morph) inner.set(b, morph =
|
|
880
|
+
if (!morph) inner.set(b, morph = _chunkFKONE6AOcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
|
|
737
881
|
return morph;
|
|
738
882
|
}
|
|
739
883
|
function shapeIn(entry, shape) {
|
|
740
884
|
if (shape === entry) return entry.node;
|
|
741
|
-
const m =
|
|
742
|
-
return { ...shape.node, ...
|
|
885
|
+
const m = _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkFKONE6AOcjs.invertMatrix.call(void 0, entry.parentWorld));
|
|
886
|
+
return { ...shape.node, ..._chunkFKONE6AOcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
|
|
743
887
|
}
|
|
744
888
|
function shapeAt(entry, timeline, nodes, time) {
|
|
745
889
|
const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
|
|
746
|
-
if (!_optionalChain([track, 'optionalAccess',
|
|
890
|
+
if (!_optionalChain([track, 'optionalAccess', _22 => _22.length])) return null;
|
|
747
891
|
const s = activeSegment(track, time);
|
|
748
892
|
const fromId = String(s ? s.from : track[0].from);
|
|
749
893
|
if (!s) return fromId === entry.node.id ? null : nodes.get(fromId) ? shapeIn(entry, nodes.get(fromId)) : null;
|
|
@@ -756,44 +900,53 @@ function shapeAt(entry, timeline, nodes, time) {
|
|
|
756
900
|
if (u >= 1) return b === entry ? null : shapeIn(entry, b);
|
|
757
901
|
return morphBetween(shapeIn(entry, a), shapeIn(entry, b)).at(u);
|
|
758
902
|
}
|
|
903
|
+
function motionFollowRoute(entry, path) {
|
|
904
|
+
if (!path || path.node.type !== "path") return null;
|
|
905
|
+
try {
|
|
906
|
+
return _chunkO2UH7LZEcjs.transformBezierPath.call(void 0, _chunkFKONE6AOcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkFKONE6AOcjs.invertMatrix.call(void 0, entry.parentWorld));
|
|
907
|
+
} catch (e3) {
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
759
911
|
function followAt(entry, timeline, nodes, time) {
|
|
760
912
|
const track = timeline.tracks.get(motionTrackKey(entry.node.id, "follow"));
|
|
761
|
-
const s = _nullishCoalesce(activeSegment(track, time), () => ( _optionalChain([track, 'optionalAccess',
|
|
762
|
-
if (!_optionalChain([s, 'optionalAccess',
|
|
763
|
-
const
|
|
764
|
-
if (!path || path.node.type !== "path") return null;
|
|
913
|
+
const s = _nullishCoalesce(activeSegment(track, time), () => ( _optionalChain([track, 'optionalAccess', _23 => _23[0]])));
|
|
914
|
+
if (!_optionalChain([s, 'optionalAccess', _24 => _24.path])) return null;
|
|
915
|
+
const route = motionFollowRoute(entry, nodes.get(s.path));
|
|
765
916
|
const progress = Number(trackValue(track, time));
|
|
766
|
-
if (!(progress >= 0)) return null;
|
|
917
|
+
if (!route || !(progress >= 0)) return null;
|
|
767
918
|
try {
|
|
768
|
-
const
|
|
769
|
-
const at = _chunkO2UH7LZEcjs.bezierPathPointAtLength.call(void 0, bezier, Math.min(1, Math.max(0, progress)) * _chunkO2UH7LZEcjs.bezierPathLength.call(void 0, bezier));
|
|
919
|
+
const at = _chunkO2UH7LZEcjs.bezierPathPointAtLength.call(void 0, route, Math.min(1, Math.max(0, progress)) * _chunkO2UH7LZEcjs.bezierPathLength.call(void 0, route));
|
|
770
920
|
if (!at) return null;
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
} catch (e3) {
|
|
921
|
+
return { x: at.point[0], y: at.point[1], angle: s.rotate ? at.angle * 180 / Math.PI : 0 };
|
|
922
|
+
} catch (e4) {
|
|
774
923
|
return null;
|
|
775
924
|
}
|
|
776
925
|
}
|
|
777
|
-
function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry.node])) {
|
|
926
|
+
function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry.node]), raw = false, follow = true) {
|
|
778
927
|
const read = (p, rest) => {
|
|
779
|
-
const v = trackValue(timeline.tracks.get(motionTrackKey(entry.node.id, p)), time);
|
|
928
|
+
const v = trackValue(timeline.tracks.get(motionTrackKey(entry.node.id, p)), time, raw);
|
|
780
929
|
return typeof v === "number" ? v : rest;
|
|
781
930
|
};
|
|
782
|
-
if (!TRANSFORM_PROPS.some((p) => timeline.tracks.has(motionTrackKey(entry.node.id, p)))) return null;
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
931
|
+
if (!TRANSFORM_PROPS.some((p) => (follow || p !== "follow") && timeline.tracks.has(motionTrackKey(entry.node.id, p)))) return null;
|
|
932
|
+
const dx = read("x", 0);
|
|
933
|
+
const dy = read("y", 0);
|
|
934
|
+
const rotation = read("rotation", 0);
|
|
786
935
|
const scaleX = read("scaleX", 1);
|
|
787
936
|
const scaleY = read("scaleY", 1);
|
|
788
|
-
const follow = followAt(entry, timeline, nodes, time);
|
|
789
|
-
if (follow) {
|
|
790
|
-
dx += follow.x - entry.center.x;
|
|
791
|
-
dy += follow.y - entry.center.y;
|
|
792
|
-
rotation += follow.angle;
|
|
793
|
-
}
|
|
794
937
|
const c = entry.center;
|
|
795
|
-
|
|
796
|
-
|
|
938
|
+
let matrix = _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkFKONE6AOcjs.rotateMatrix.call(void 0, rotation, c)), _chunkFKONE6AOcjs.translateMatrix.call(void 0, dx, dy));
|
|
939
|
+
const along = follow ? followAt(entry, timeline, nodes, time) : null;
|
|
940
|
+
if (along) matrix = _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, matrix, _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkFKONE6AOcjs.rotateMatrix.call(void 0, along.angle)), _chunkFKONE6AOcjs.translateMatrix.call(void 0, along.x, along.y)));
|
|
941
|
+
return { matrix, dx, dy, rotation, scaleX, scaleY, follow: along };
|
|
942
|
+
}
|
|
943
|
+
function motionNodeClips(id, timeline, time) {
|
|
944
|
+
const out = [];
|
|
945
|
+
const rect = trackValue(timeline.tracks.get(motionTrackKey(id, "clipRect")), time);
|
|
946
|
+
if (Array.isArray(rect) && rect.length === 4) out.push({ shape: "rect", x: tidy(rect[0]), y: tidy(rect[1]), width: Math.max(0, tidy(rect[2])), height: Math.max(0, tidy(rect[3])) });
|
|
947
|
+
const circle = trackValue(timeline.tracks.get(motionTrackKey(id, "clipCircle")), time);
|
|
948
|
+
if (Array.isArray(circle) && circle.length === 3) out.push({ shape: "circle", cx: tidy(circle[0]), cy: tidy(circle[1]), r: Math.max(0, tidy(circle[2])) });
|
|
949
|
+
return out;
|
|
797
950
|
}
|
|
798
951
|
function motionFrameAt(scene, time, options = {}) {
|
|
799
952
|
const s = applyMotionControlValues(scene, options.values);
|
|
@@ -802,12 +955,15 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
802
955
|
const drawOn = options.draw !== false;
|
|
803
956
|
const value = (id, p) => trackValue(timeline.tracks.get(motionTrackKey(id, p)), time);
|
|
804
957
|
const animated = new Set(timeline.segments.map((seg) => seg.node));
|
|
958
|
+
const clips = {};
|
|
805
959
|
const visit = (node) => {
|
|
806
960
|
let out = node.type === "group" ? { ...node, children: node.children.map(visit) } : node;
|
|
807
961
|
if (!animated.has(node.id)) return out;
|
|
808
962
|
const entry = nodes.get(node.id);
|
|
809
963
|
if (!entry) return out;
|
|
810
964
|
const id = node.id;
|
|
965
|
+
const clip = motionNodeClips(id, timeline, time);
|
|
966
|
+
if (clip.length) clips[id] = clip;
|
|
811
967
|
const shape = shapeAt(entry, timeline, nodes, time);
|
|
812
968
|
if (shape) {
|
|
813
969
|
const { name, visible, opacity: opacity2, locked } = node;
|
|
@@ -815,7 +971,7 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
815
971
|
if (out.visible === void 0) delete out.visible;
|
|
816
972
|
}
|
|
817
973
|
const effectTracks = [...timeline.tracks.keys()].filter((k) => k.startsWith(`${id}\0effect:`));
|
|
818
|
-
if (effectTracks.length && _optionalChain([out, 'access',
|
|
974
|
+
if (effectTracks.length && _optionalChain([out, 'access', _25 => _25.effects, 'optionalAccess', _26 => _26.length])) {
|
|
819
975
|
out = {
|
|
820
976
|
...out,
|
|
821
977
|
effects: out.effects.map((effect) => {
|
|
@@ -848,7 +1004,7 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
848
1004
|
const start = Math.min(1, Math.max(0, typeof drawStart === "number" ? drawStart : 0));
|
|
849
1005
|
const end = Math.min(1, Math.max(0, typeof drawEnd === "number" ? drawEnd : 1));
|
|
850
1006
|
if (start > 0 || end < 1) {
|
|
851
|
-
const trim =
|
|
1007
|
+
const trim = _chunkFKONE6AOcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
|
|
852
1008
|
p = { ...p, effects: [trim, ...(_nullishCoalesce(p.effects, () => ( []))).filter((e) => e.id !== MOTION_DRAW_EFFECT_ID)] };
|
|
853
1009
|
}
|
|
854
1010
|
}
|
|
@@ -862,8 +1018,8 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
862
1018
|
if (o >= 1) delete out.opacity;
|
|
863
1019
|
}
|
|
864
1020
|
const offset = options.offsets === false ? null : motionNodeOffset(entry, timeline, time, nodes);
|
|
865
|
-
if (offset && !
|
|
866
|
-
const m =
|
|
1021
|
+
if (offset && !_chunkFKONE6AOcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
|
|
1022
|
+
const m = _chunkFKONE6AOcjs.multiplyMatrices.call(void 0, _chunkFKONE6AOcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
|
|
867
1023
|
out = { ...out, transform: m };
|
|
868
1024
|
}
|
|
869
1025
|
return out;
|
|
@@ -871,11 +1027,19 @@ function motionFrameAt(scene, time, options = {}) {
|
|
|
871
1027
|
const document = { ...s.artwork, nodes: s.artwork.nodes.map(visit) };
|
|
872
1028
|
const cam = trackValue(timeline.tracks.get(motionTrackKey("", "camera")), time);
|
|
873
1029
|
const box = Array.isArray(cam) ? cam : [0, 0, s.artwork.width, s.artwork.height];
|
|
874
|
-
return { time, document, camera: { x: tidy(box[0]), y: tidy(box[1]), width: tidy(box[2]), height: tidy(box[3]) } };
|
|
1030
|
+
return { time, document, camera: { x: tidy(box[0]), y: tidy(box[1]), width: tidy(box[2]), height: tidy(box[3]) }, clips };
|
|
1031
|
+
}
|
|
1032
|
+
function motionClipAttrs(clip) {
|
|
1033
|
+
const { shape: _shape, ...attrs } = clip;
|
|
1034
|
+
return attrs;
|
|
875
1035
|
}
|
|
876
1036
|
function motionFrameToSvg(scene, time, options = {}) {
|
|
877
1037
|
const frame = motionFrameAt(scene, time, options);
|
|
878
|
-
|
|
1038
|
+
const prefix = _nullishCoalesce(options.idPrefix, () => ( "vg-"));
|
|
1039
|
+
const wrap = { ...options.wrap };
|
|
1040
|
+
for (const [id, clips] of Object.entries(frame.clips))
|
|
1041
|
+
wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
|
|
1042
|
+
return withViewBox(_chunkFKONE6AOcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera);
|
|
879
1043
|
}
|
|
880
1044
|
function withViewBox(svg, box) {
|
|
881
1045
|
const f = (n) => String(Math.round(n * 1e3) / 1e3);
|
|
@@ -885,7 +1049,7 @@ function withViewBox(svg, box) {
|
|
|
885
1049
|
// src/animation-editor/check.ts
|
|
886
1050
|
var MOTION_MIN_CHANGE_MS = 120;
|
|
887
1051
|
var NUMERIC_PARAMS = (node, effectId) => {
|
|
888
|
-
const effect = _optionalChain([node, 'access',
|
|
1052
|
+
const effect = _optionalChain([node, 'access', _27 => _27.effects, 'optionalAccess', _28 => _28.find, 'call', _29 => _29((e) => e.id === effectId)]);
|
|
889
1053
|
if (!effect) return null;
|
|
890
1054
|
return Object.entries(effect.params).filter(([, v]) => typeof v === "number").map(([k]) => k);
|
|
891
1055
|
};
|
|
@@ -910,7 +1074,12 @@ function visibleAt(timeline, id, time, node) {
|
|
|
910
1074
|
if (node.visible === false) return false;
|
|
911
1075
|
if (num("opacity", _nullishCoalesce(node.opacity, () => ( 1))) <= 0.01) return false;
|
|
912
1076
|
if (Math.abs(num("scaleX", 1) * num("scaleY", 1)) <= 1e-4) return false;
|
|
913
|
-
const
|
|
1077
|
+
const clip = (p) => trackValue(timeline.tracks.get(motionTrackKey(id, p)), time);
|
|
1078
|
+
const rect = clip("clipRect");
|
|
1079
|
+
if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
|
|
1080
|
+
const circle = clip("clipCircle");
|
|
1081
|
+
if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
|
|
1082
|
+
const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
|
|
914
1083
|
return num("drawEnd", 1) > 0.01 || hasFill && num("fillOpacity", 1) > 0.01;
|
|
915
1084
|
}
|
|
916
1085
|
function checkMotionScene(scene) {
|
|
@@ -949,6 +1118,12 @@ function checkMotionScene(scene) {
|
|
|
949
1118
|
if (command2.type === "follow" && known(command2.path, "unknown-path", "path", where) && nodes.get(command2.path).node.type !== "path")
|
|
950
1119
|
issues.push(motionIssue("not-a-path", `"${command2.path}" is a group; follow a single path node.`, { ...where, ids: [command2.path] }));
|
|
951
1120
|
if (command2.type === "morph") known(command2.into, "unknown-shape", "shape", where);
|
|
1121
|
+
const style = command2.type === "enter" || command2.type === "exit" ? command2.style : void 0;
|
|
1122
|
+
if (style === "wipe" || style === "iris" || style === "split") {
|
|
1123
|
+
for (const id of targets)
|
|
1124
|
+
if (!motionRevealPadding(nodes.get(id)))
|
|
1125
|
+
issues.push(motionIssue("reveal-no-box", `"${id}" has no width or height (a straight line), so a ${style} cannot clip it and it fades instead; use style "${command2.type === "enter" ? "draw" : "undraw"}" for a line.`, { ...where, ids: [id] }));
|
|
1126
|
+
}
|
|
952
1127
|
if (command2.type === "style") {
|
|
953
1128
|
for (const key of ["fill", "stroke"]) {
|
|
954
1129
|
const color = command2[key];
|
|
@@ -959,12 +1134,24 @@ function checkMotionScene(scene) {
|
|
|
959
1134
|
}
|
|
960
1135
|
for (const id of targets) {
|
|
961
1136
|
const node = nodes.get(id).node;
|
|
962
|
-
const paths = node.type === "path" ? [node] :
|
|
1137
|
+
const paths = node.type === "path" ? [node] : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node);
|
|
963
1138
|
if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
|
|
964
1139
|
issues.push(motionIssue("paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
|
|
965
1140
|
}
|
|
966
1141
|
}
|
|
967
1142
|
}
|
|
1143
|
+
if (command2.type === "color-pulse") {
|
|
1144
|
+
const key = _nullishCoalesce(command2.paint, () => ( "fill"));
|
|
1145
|
+
const color = _nullishCoalesce(command2.color, () => ( "#f59e0b"));
|
|
1146
|
+
if (_chunkA6PHCAGXcjs.normalizeTokenColor.call(void 0, color) === null) issues.push(motionIssue("invalid-color", `color "${color}" is not a colour this editor reads; use hex ("#0ea5e9"), rgb() or rgba().`, where));
|
|
1147
|
+
else
|
|
1148
|
+
for (const id of targets) {
|
|
1149
|
+
const node = nodes.get(id).node;
|
|
1150
|
+
const paths = node.type === "path" ? [node] : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node);
|
|
1151
|
+
if (paths.some((p) => typeof p[key] !== "string"))
|
|
1152
|
+
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
|
+
}
|
|
1154
|
+
}
|
|
968
1155
|
if (command2.type === "effect") {
|
|
969
1156
|
for (const id of targets) {
|
|
970
1157
|
const node = nodes.get(id).node;
|
|
@@ -1015,7 +1202,7 @@ function checkMotionScene(scene) {
|
|
|
1015
1202
|
const cam = frame.camera;
|
|
1016
1203
|
const docIndex = indexMotionNodes(frame.document.nodes);
|
|
1017
1204
|
for (const id of command2.targets) {
|
|
1018
|
-
const b = _optionalChain([docIndex, 'access',
|
|
1205
|
+
const b = _optionalChain([docIndex, 'access', _30 => _30.get, 'call', _31 => _31(id), 'optionalAccess', _32 => _32.bounds]);
|
|
1019
1206
|
if (!b || reported.has(id) || !visibleAt(timeline, id, timing.end, nodes.get(id).node)) continue;
|
|
1020
1207
|
const outside = b.x + b.width < cam.x || b.y + b.height < cam.y || b.x > cam.x + cam.width || b.y > cam.y + cam.height;
|
|
1021
1208
|
if (outside) {
|
|
@@ -1192,9 +1379,9 @@ function applyMotionEdits(scene, edits) {
|
|
|
1192
1379
|
let next = scene;
|
|
1193
1380
|
for (let i = 0; i < list.length; i++) {
|
|
1194
1381
|
const edit = list[i];
|
|
1195
|
-
const prefix = list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess',
|
|
1382
|
+
const prefix = list.length > 1 ? `op ${i + 1} (${_optionalChain([edit, 'optionalAccess', _33 => _33.op])}): ` : "";
|
|
1196
1383
|
if (!edit || !MOTION_EDIT_OPS.includes(edit.op))
|
|
1197
|
-
return { ok: false, error: `${prefix}Unknown op ${namedWithSuggestion(String(_optionalChain([edit, 'optionalAccess',
|
|
1384
|
+
return { ok: false, error: `${prefix}Unknown op ${namedWithSuggestion(String(_optionalChain([edit, 'optionalAccess', _34 => _34.op])), MOTION_EDIT_OPS)}. Nothing was changed.` };
|
|
1198
1385
|
try {
|
|
1199
1386
|
next = applyOne(next, edit);
|
|
1200
1387
|
} catch (error) {
|
|
@@ -1231,6 +1418,14 @@ function flairEaseFor(ease) {
|
|
|
1231
1418
|
}
|
|
1232
1419
|
return void 0;
|
|
1233
1420
|
}
|
|
1421
|
+
function flairCurveFor(ease, curves = true) {
|
|
1422
|
+
const name = flairEaseFor(ease);
|
|
1423
|
+
if (name || !curves) return name;
|
|
1424
|
+
const resolved = _chunkXZ4L3R4Kcjs.resolveEasing.call(void 0, ease);
|
|
1425
|
+
if (resolved === "hold" || resolved.type !== "cubic-bezier") return void 0;
|
|
1426
|
+
return [resolved.x1, resolved.y1, resolved.x2, resolved.y2];
|
|
1427
|
+
}
|
|
1428
|
+
var overshoots = (ease) => typeof ease !== "string" && (ease[1] < 0 || ease[1] > 1 || ease[3] < 0 || ease[3] > 1);
|
|
1234
1429
|
var TRANSFORM_PROPS2 = ["x", "y", "rotation", "scaleX", "scaleY", "follow"];
|
|
1235
1430
|
var LINEAR_TRANSFORM = /* @__PURE__ */ new Set(["x", "y", "rotation", "scaleX", "scaleY"]);
|
|
1236
1431
|
function hex6(color) {
|
|
@@ -1240,6 +1435,9 @@ function hex6(color) {
|
|
|
1240
1435
|
function toFlairSvgMotion(scene, options = {}) {
|
|
1241
1436
|
const fps = _nullishCoalesce(_nullishCoalesce(options.fps, () => ( scene.fps)), () => ( 30));
|
|
1242
1437
|
const precision = _nullishCoalesce(options.precision, () => ( 3));
|
|
1438
|
+
const curves = _nullishCoalesce(options.curves, () => ( true));
|
|
1439
|
+
const behaviors = _nullishCoalesce(options.behaviors, () => ( true));
|
|
1440
|
+
const plays = (s) => !s.behavior || behaviors;
|
|
1243
1441
|
const round2 = (n) => Math.round(n * 10 ** precision) / 10 ** precision;
|
|
1244
1442
|
const f = (n) => String(round2(n));
|
|
1245
1443
|
const timeline = compileMotionScene(scene);
|
|
@@ -1254,34 +1452,81 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1254
1452
|
};
|
|
1255
1453
|
const animatedNodes = new Set(timeline.segments.map((s) => s.node).filter(Boolean));
|
|
1256
1454
|
const pathsSeen = /* @__PURE__ */ new Set();
|
|
1455
|
+
const wrap = {};
|
|
1456
|
+
const routes = [];
|
|
1457
|
+
const follows = [];
|
|
1458
|
+
const usedIds = new Set(nodes.keys());
|
|
1459
|
+
const freshId = (base) => {
|
|
1460
|
+
let id = base;
|
|
1461
|
+
for (let n = 2; usedIds.has(id); n++) id = `${base}-${n}`;
|
|
1462
|
+
usedIds.add(id);
|
|
1463
|
+
return id;
|
|
1464
|
+
};
|
|
1257
1465
|
for (const id of animatedNodes) {
|
|
1258
1466
|
const entry = nodes.get(id);
|
|
1259
1467
|
const node = entry.node;
|
|
1468
|
+
const drawn = [...entry.ancestors.map((a) => nodes.get(a).node), node].every((n) => n.visible !== false);
|
|
1469
|
+
for (const [p, name] of [["clipRect", "reveal"], ["clipCircle", "iris"]]) {
|
|
1470
|
+
if (!drawn || !timeline.tracks.has(motionTrackKey(id, p))) continue;
|
|
1471
|
+
const wrapper = freshId(`${id}--${name}`);
|
|
1472
|
+
const clipId = freshId(`${wrapper}-clip`);
|
|
1473
|
+
const shapeId = freshId(`${wrapper}-clip-shape`);
|
|
1474
|
+
const clipAt = (t) => motionNodeClips(id, timeline, t).find((c) => c.shape === (p === "clipRect" ? "rect" : "circle"));
|
|
1475
|
+
const rest = clipAt(0);
|
|
1476
|
+
(wrap[id] ??= []).push({ id: wrapper, clip: { id: clipId, shapeId, shape: rest.shape, attrs: motionClipAttrs(rest) } });
|
|
1477
|
+
channels.push({ id: shapeId, kind: "attrs", attrs: Object.keys(motionClipAttrs(rest)), segments: [...track(id, p)], exact: () => true, value: (t) => Object.values(motionClipAttrs(clipAt(t))).map((v) => Math.round(v * 1e4) / 1e4) });
|
|
1478
|
+
}
|
|
1479
|
+
const followSegments = track(id, "follow");
|
|
1480
|
+
if (drawn && followSegments.length) {
|
|
1481
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1482
|
+
for (const seg of followSegments) {
|
|
1483
|
+
if (!seg.path || ids.has(seg.path)) continue;
|
|
1484
|
+
const route = motionFollowRoute(entry, nodes.get(seg.path));
|
|
1485
|
+
if (!route) continue;
|
|
1486
|
+
const routeId = freshId(`${id}--follow-route`);
|
|
1487
|
+
ids.set(seg.path, routeId);
|
|
1488
|
+
routes.push(`<path id="${routeId}" d="${_chunkO2UH7LZEcjs.bezierPathToSvg.call(void 0, route, { precision })}" fill="none"/>`);
|
|
1489
|
+
}
|
|
1490
|
+
if (ids.size) {
|
|
1491
|
+
const wrapper = freshId(`${id}--follow`);
|
|
1492
|
+
const centre = freshId(`${id}--follow-centre`);
|
|
1493
|
+
const c = entry.center;
|
|
1494
|
+
const at = _optionalChain([motionNodeOffset, 'call', _35 => _35(entry, timeline, 0, nodes), 'optionalAccess', _36 => _36.follow]);
|
|
1495
|
+
const placed = at ? `translate(${f(at.x)} ${f(at.y)})${at.angle ? ` rotate(${f(at.angle)})` : ""}` : void 0;
|
|
1496
|
+
(wrap[id] ??= []).push({ id: wrapper, ...placed ? { transform: placed } : {} }, { id: centre, transform: `translate(${f(-c.x)} ${f(-c.y)})` });
|
|
1497
|
+
follows.push({ id, wrapper, routes: ids, segments: followSegments.filter((seg) => seg.path && ids.has(seg.path)) });
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1260
1500
|
if (timeline.tracks.has(motionTrackKey(id, "opacity")))
|
|
1261
|
-
channels.push({ id, kind: "attr", attr: "opacity", segments: [...track(id, "opacity")], exact:
|
|
1262
|
-
const
|
|
1501
|
+
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
|
+
const followed = follows.some((x) => x.id === id);
|
|
1503
|
+
const transformSegments = TRANSFORM_PROPS2.flatMap((p) => followed && p === "follow" ? [] : track(id, p));
|
|
1263
1504
|
if (transformSegments.length) {
|
|
1264
1505
|
const base = node.transform ? ` matrix(${node.transform.map(f).join(" ")})` : "";
|
|
1265
1506
|
const c = entry.center;
|
|
1507
|
+
const transformAt = (t, raw) => {
|
|
1508
|
+
const o = motionNodeOffset(entry, timeline, t, nodes, raw, !followed);
|
|
1509
|
+
return `translate(${f(o.dx)} ${f(o.dy)}) rotate(${f(o.rotation)} ${f(c.x)} ${f(c.y)}) translate(${f(c.x)} ${f(c.y)}) scale(${f(o.scaleX)} ${f(o.scaleY)}) translate(${f(-c.x)} ${f(-c.y)})${base}`;
|
|
1510
|
+
};
|
|
1266
1511
|
channels.push({
|
|
1267
1512
|
id,
|
|
1268
1513
|
kind: "attr",
|
|
1269
1514
|
attr: "transform",
|
|
1270
1515
|
segments: transformSegments,
|
|
1271
|
-
exact: (s) => LINEAR_TRANSFORM.has(s.property) &&
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1516
|
+
exact: (s) => LINEAR_TRANSFORM.has(s.property) && plays(s),
|
|
1517
|
+
overshoot: true,
|
|
1518
|
+
// x, y and the angle are the transform's numbers 0, 1 and 2 (`MotionSegment.index`).
|
|
1519
|
+
value: (t) => transformAt(t, false),
|
|
1520
|
+
raw: (t) => transformAt(t, true)
|
|
1276
1521
|
});
|
|
1277
1522
|
}
|
|
1278
|
-
const paths = node.type === "path" ? [node] :
|
|
1523
|
+
const paths = node.type === "path" ? [node] : _chunkFKONE6AOcjs.collectPathNodes.call(void 0, node);
|
|
1279
1524
|
for (const path of paths) {
|
|
1280
1525
|
if (pathsSeen.has(path.id)) continue;
|
|
1281
1526
|
pathsSeen.add(path.id);
|
|
1282
1527
|
const paint = (p, attr) => {
|
|
1283
1528
|
const from = owner(path, p);
|
|
1284
|
-
if (from) channels.push({ id: path.id, kind: "attr", attr, segments: [...track(from, p)], exact: () =>
|
|
1529
|
+
if (from) channels.push({ id: path.id, kind: "attr", attr, segments: [...track(from, p)], exact: plays, value: (t) => hex6(trackValue(track(from, p), t)), raw: (t) => hex6(trackValue(track(from, p), t, true)) });
|
|
1285
1530
|
};
|
|
1286
1531
|
paint("fill", "fill");
|
|
1287
1532
|
paint("stroke", "stroke");
|
|
@@ -1297,7 +1542,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1297
1542
|
if (shapeSegments.length) {
|
|
1298
1543
|
if (node.type !== "path") notes.push(`"${id}" is a group: its morph or effect animation is not exported (Flair tweens one path's "d").`);
|
|
1299
1544
|
else {
|
|
1300
|
-
const inverse =
|
|
1545
|
+
const inverse = _chunkFKONE6AOcjs.invertMatrix.call(void 0, _chunkFKONE6AOcjs.nodeMatrix.call(void 0, node));
|
|
1301
1546
|
channels.push({
|
|
1302
1547
|
id,
|
|
1303
1548
|
kind: "attr",
|
|
@@ -1306,9 +1551,9 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1306
1551
|
exact: () => false,
|
|
1307
1552
|
value: (t) => {
|
|
1308
1553
|
const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
|
|
1309
|
-
const now =
|
|
1554
|
+
const now = _chunkFKONE6AOcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _37 => _37(frame.document.nodes), 'access', _38 => _38.get, 'call', _39 => _39(id), 'optionalAccess', _40 => _40.node]));
|
|
1310
1555
|
if (!now || now.type !== "path") return "";
|
|
1311
|
-
const bezier = _chunkO2UH7LZEcjs.transformBezierPath.call(void 0,
|
|
1556
|
+
const bezier = _chunkO2UH7LZEcjs.transformBezierPath.call(void 0, _chunkFKONE6AOcjs.vectorPathWorldBezier.call(void 0, now, _chunkFKONE6AOcjs.IDENTITY_MATRIX, { effects: false }), inverse);
|
|
1312
1557
|
return _chunkO2UH7LZEcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
|
|
1313
1558
|
}
|
|
1314
1559
|
});
|
|
@@ -1316,19 +1561,26 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1316
1561
|
}
|
|
1317
1562
|
}
|
|
1318
1563
|
const camera = track("", "camera");
|
|
1319
|
-
if (camera.length) channels.push({ id: "", kind: "view", segments: [...camera], exact: () => true, value: (t) => trackValue(camera, t).map(round2) });
|
|
1564
|
+
if (camera.length) channels.push({ id: "", kind: "view", segments: [...camera], exact: () => true, overshoot: true, value: (t) => trackValue(camera, t).map(round2) });
|
|
1320
1565
|
const animate = [];
|
|
1321
1566
|
let sampled = 0;
|
|
1322
1567
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
1323
|
-
const emit = (channel, delay, ms, from, to, ease) => {
|
|
1324
|
-
const base = { ...channel.id ? { id: channel.id } : {}, ...delay > 0 ? { delay: round2(delay) } : {}, ms: round2(ms), ease };
|
|
1568
|
+
const emit = (channel, delay, ms, from, to, ease, behavior) => {
|
|
1569
|
+
const base = { ...channel.id ? { id: channel.id } : {}, ...delay > 0 ? { delay: round2(delay) } : {}, ms: round2(ms), ease: typeof ease === "string" ? ease : ease.map(round2), ...behavior ? { behavior } : {} };
|
|
1325
1570
|
if (channel.kind === "view") animate.push({ ...base, view: to });
|
|
1326
1571
|
else if (channel.kind === "draw") animate.push({ ...base, draw: [from, to] });
|
|
1327
|
-
else
|
|
1572
|
+
else if (channel.kind === "attrs") {
|
|
1573
|
+
const [a, b] = [from, to];
|
|
1574
|
+
const attrs = Object.fromEntries(channel.attrs.flatMap((name, k) => a[k] !== b[k] ? [[name, [a[k], b[k]]]] : []));
|
|
1575
|
+
animate.push({ ...base, attrs });
|
|
1576
|
+
} else animate.push({ ...base, attrs: { [channel.attr]: [from, to] } });
|
|
1328
1577
|
};
|
|
1329
1578
|
for (const channel of channels) {
|
|
1330
1579
|
const cuts = channel.segments.filter((s) => s.end <= s.start);
|
|
1331
|
-
for (const cut of cuts)
|
|
1580
|
+
for (const cut of cuts) {
|
|
1581
|
+
const [from, to] = [channel.value(Math.max(0, cut.start - 1e-3)), channel.value(cut.start)];
|
|
1582
|
+
if (cut.start <= 0 || !same(from, to) || channel.kind === "view") emit(channel, cut.start, 0, from, to, "linear");
|
|
1583
|
+
}
|
|
1332
1584
|
const times = [...new Set(channel.segments.flatMap((s) => [s.start, s.end]))].sort((a, b) => a - b);
|
|
1333
1585
|
for (let i = 0; i + 1 < times.length; i++) {
|
|
1334
1586
|
const a = times[i];
|
|
@@ -1336,12 +1588,15 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1336
1588
|
const active = channel.segments.filter((s) => s.start < b && s.end > a);
|
|
1337
1589
|
if (!active.length) continue;
|
|
1338
1590
|
const first = active[0];
|
|
1339
|
-
const together = active.every(
|
|
1340
|
-
|
|
1591
|
+
const together = active.every(
|
|
1592
|
+
(x) => x.start === a && x.end === b && channel.exact(x) && JSON.stringify(x.ease) === JSON.stringify(first.ease) && JSON.stringify(x.behavior) === JSON.stringify(first.behavior)
|
|
1593
|
+
);
|
|
1594
|
+
const curve = together ? flairCurveFor(first.ease, curves) : void 0;
|
|
1595
|
+
const ease = curve && (!overshoots(curve) || channel.overshoot) ? curve : void 0;
|
|
1341
1596
|
if (ease) {
|
|
1342
1597
|
const from = channel.value(a);
|
|
1343
|
-
const to = channel.value(b);
|
|
1344
|
-
if (!same(from, to) || channel.kind === "view") emit(channel, a, b - a, from, to, ease);
|
|
1598
|
+
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.behavior);
|
|
1345
1600
|
continue;
|
|
1346
1601
|
}
|
|
1347
1602
|
const n = Math.max(1, Math.ceil((b - a) * fps / 1e3));
|
|
@@ -1358,11 +1613,32 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
1358
1613
|
}
|
|
1359
1614
|
}
|
|
1360
1615
|
}
|
|
1616
|
+
for (const follow of follows) {
|
|
1617
|
+
const starts = follow.segments.map((seg) => seg.start);
|
|
1618
|
+
for (const seg of follow.segments) {
|
|
1619
|
+
const along = { id: follow.wrapper, along: follow.routes.get(seg.path), ...seg.rotate ? { orient: true } : {} };
|
|
1620
|
+
const progress = (t) => round2(Math.min(1, Math.max(0, Number(segmentValue(seg, t)))));
|
|
1621
|
+
const curve = seg.end > seg.start ? flairCurveFor(seg.ease, curves) : "linear";
|
|
1622
|
+
if (curve && !(overshoots(curve) && seg.rotate)) {
|
|
1623
|
+
animate.push({ ...along, ...seg.start > 0 ? { delay: round2(seg.start) } : {}, ms: round2(seg.end - seg.start), ease: typeof curve === "string" ? curve : curve.map(round2), at: [round2(Number(seg.from)), round2(Number(seg.to))] });
|
|
1624
|
+
continue;
|
|
1625
|
+
}
|
|
1626
|
+
const until = Math.min(seg.end, ...starts.filter((t) => t > seg.start));
|
|
1627
|
+
const n = Math.max(1, Math.ceil((until - seg.start) * fps / 1e3));
|
|
1628
|
+
for (let k = 1; k <= n; k++) {
|
|
1629
|
+
const t0 = seg.start + (until - seg.start) * (k - 1) / n;
|
|
1630
|
+
const t1 = seg.start + (until - seg.start) * k / n;
|
|
1631
|
+
animate.push({ ...along, ...t0 > 0 ? { delay: round2(t0) } : {}, ms: round2(t1 - t0), ease: "linear", at: [progress(t0), progress(t1)] });
|
|
1632
|
+
sampled++;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1361
1636
|
animate.sort((x, y) => (_nullishCoalesce(x.delay, () => ( 0))) - (_nullishCoalesce(y.delay, () => ( 0))));
|
|
1362
|
-
let svg =
|
|
1637
|
+
let svg = _chunkFKONE6AOcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkFKONE6AOcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
|
|
1638
|
+
if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
|
|
1363
1639
|
const lastChange = animate.reduce((m, a) => Math.max(m, (_nullishCoalesce(a.delay, () => ( 0))) + (_nullishCoalesce(a.ms, () => ( 0)))), 0);
|
|
1364
1640
|
let motion = { svg, animate };
|
|
1365
|
-
if (_optionalChain([scene, 'access',
|
|
1641
|
+
if (_optionalChain([scene, 'access', _41 => _41.controls, 'optionalAccess', _42 => _42.length])) {
|
|
1366
1642
|
const declarations = scene.controls.map((c) => `{{${c.name}: color default=${c.default.toUpperCase()}${c.label ? ` label='${c.label.replace(/'/g, "\u2019")}'` : ""}}}`).join(" ");
|
|
1367
1643
|
const swap = (text) => scene.controls.reduce((s, c) => s.replace(new RegExp(`${c.default}(?![0-9a-fA-F])`, "gi"), `{{${c.name}}}`), text);
|
|
1368
1644
|
svg = svg.replace(/^(<svg[^>]*>)/, `$1<!-- ${declarations} -->`);
|
|
@@ -1384,7 +1660,7 @@ function toFlairVectorEffect(scene, options = {}) {
|
|
|
1384
1660
|
tags: _nullishCoalesce(options.tags, () => ( [])),
|
|
1385
1661
|
motion: out.motion,
|
|
1386
1662
|
hold: out.hold,
|
|
1387
|
-
..._optionalChain([scene, 'access',
|
|
1663
|
+
..._optionalChain([scene, 'access', _43 => _43.presets, 'optionalAccess', _44 => _44.length]) ? { presets: scene.presets } : {},
|
|
1388
1664
|
...options.trigger ? { trigger: options.trigger } : {}
|
|
1389
1665
|
};
|
|
1390
1666
|
}
|
|
@@ -1469,7 +1745,7 @@ var AnimationEditorController = (_class = class {
|
|
|
1469
1745
|
time: p.time,
|
|
1470
1746
|
playing: p.playing,
|
|
1471
1747
|
loop: p.loop,
|
|
1472
|
-
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call',
|
|
1748
|
+
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _45 => _45(timeline, p.time), 'optionalAccess', _46 => _46.id]), () => ( null)),
|
|
1473
1749
|
selection: this.selection,
|
|
1474
1750
|
readOnly: this.readOnly,
|
|
1475
1751
|
error: this.error,
|
|
@@ -1508,7 +1784,7 @@ var AnimationEditorController = (_class = class {
|
|
|
1508
1784
|
this.applying = false;
|
|
1509
1785
|
}
|
|
1510
1786
|
this.notify();
|
|
1511
|
-
_optionalChain([this, 'access',
|
|
1787
|
+
_optionalChain([this, 'access', _47 => _47.onChange, 'optionalCall', _48 => _48(scene)]);
|
|
1512
1788
|
}
|
|
1513
1789
|
commit(label, next) {
|
|
1514
1790
|
const before = this.scene;
|
|
@@ -1668,13 +1944,20 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
1668
1944
|
description: `A command (one of ${MOTION_COMMAND_TYPES.join(", ")}). Commands in a shot play one after another unless "with": "previous".`,
|
|
1669
1945
|
oneOf: [
|
|
1670
1946
|
command("enter", "Brings hidden targets in; they are hidden before this shot.", {
|
|
1671
|
-
style: {
|
|
1672
|
-
|
|
1673
|
-
|
|
1947
|
+
style: {
|
|
1948
|
+
type: "string",
|
|
1949
|
+
enum: [...MOTION_ENTER_STYLES],
|
|
1950
|
+
description: "fade (default), pop (scales up past full size and settles), grow (from nothing), slide, draw (outline drawn on, then the fill fades in), zoom (settles from larger), rise (rises a short way, overshooting a touch), or a reveal through a clip over the target's box: wipe (behind a travelling edge), iris (from the centre outwards) or split (from a line through the middle). Reveals need a box with a width and a height (not a lone straight line)."
|
|
1951
|
+
},
|
|
1952
|
+
direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default up). For wipe: the way the edge travels (default right, revealing from the left)." },
|
|
1953
|
+
distance: { type: "number", description: "For slide (default 40) and rise (default 20): document units." },
|
|
1954
|
+
scale: { type: "number", minimum: 0, description: "For pop (default 0.5) and zoom (default 1.6): the starting scale (1 = rest size)." },
|
|
1955
|
+
shape: { type: "string", enum: [...MOTION_IRIS_SHAPES], description: "For iris: open through a circle (default; an ellipse on a box that is not square) or a box." },
|
|
1956
|
+
orientation: { type: "string", enum: [...MOTION_SPLIT_ORIENTATIONS], description: "For split: horizontal (default) opens up and down from a horizontal line through the middle; vertical opens left and right." }
|
|
1674
1957
|
}),
|
|
1675
1958
|
command("exit", "Takes targets out.", {
|
|
1676
|
-
style: { type: "string", enum: [...MOTION_EXIT_STYLES], description: "fade (default), shrink, slide or
|
|
1677
|
-
direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default down)." },
|
|
1959
|
+
style: { type: "string", enum: [...MOTION_EXIT_STYLES], description: "fade (default), shrink, slide, undraw, or wipe (hides behind a travelling edge through a clip over the target's box: a wipe in, reversed)." },
|
|
1960
|
+
direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default down). For wipe: the way the edge travels (default right, hiding from the left)." },
|
|
1678
1961
|
distance: { type: "number", description: "For slide: document units (default 40)." }
|
|
1679
1962
|
}),
|
|
1680
1963
|
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).") }),
|
|
@@ -1690,12 +1973,30 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
1690
1973
|
command("morph", "Morphs each target into the shape (and paint) of another node, which usually stays hidden.", { into: { type: "string", minLength: 1, description: "Id of the node whose shape to take." } }, ["into"]),
|
|
1691
1974
|
command("follow", "Moves targets along a path node, centre on the path.", {
|
|
1692
1975
|
path: { type: "string", minLength: 1, description: "Id of a path node (it can be hidden)." },
|
|
1693
|
-
rotate: { type: "boolean", description: "Turn with the path (default false)." },
|
|
1976
|
+
rotate: { type: "boolean", description: "Turn with the path (default false); moves and shakes made meanwhile turn with it too." },
|
|
1694
1977
|
from: FRACTION("Where to start along the path (default 0)."),
|
|
1695
1978
|
to: FRACTION("Where to end along the path (default 1).")
|
|
1696
1979
|
}, ["path"]),
|
|
1697
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)." } }),
|
|
1698
|
-
command("shake", "Shakes side to side
|
|
1981
|
+
command("shake", "Shakes side to side (or up and down), settling.", {
|
|
1982
|
+
amount: { type: "number", description: "Document units (default 8)." },
|
|
1983
|
+
count: { type: "integer", minimum: 1, description: "Shakes (default 3)." },
|
|
1984
|
+
axis: { type: "string", enum: ["horizontal", "vertical"], description: "Default horizontal." }
|
|
1985
|
+
}),
|
|
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)." } }),
|
|
1988
|
+
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.", {
|
|
1989
|
+
amount: { type: "number", description: "Up to about this far, in document units (default 6)." },
|
|
1990
|
+
frequency: { type: "number", exclusiveMinimum: 0, description: "Wanders per second, in Hz (default 3)." },
|
|
1991
|
+
octaves: { type: "integer", minimum: 1, maximum: 8, description: "Layers of finer detail (default 2)." },
|
|
1992
|
+
rotate: { type: "number", description: "Also turns about the centre by up to about this many degrees (default 0)." },
|
|
1993
|
+
seed: { type: "integer", minimum: 0, description: "Default: one picked from the target id, so each target wanders its own way." }
|
|
1994
|
+
}),
|
|
1995
|
+
command("color-pulse", "Tints solid paint toward a colour and back (mixed in OKLab). On a group it tints every path in it.", {
|
|
1996
|
+
color: { type: "string", description: 'The tint, a CSS colour (default "#f59e0b").' },
|
|
1997
|
+
paint: { type: "string", enum: ["fill", "stroke"], description: "Which paint (default fill)." },
|
|
1998
|
+
count: { type: "integer", minimum: 1, description: "Pulses (default 1)." }
|
|
1999
|
+
}),
|
|
1699
2000
|
command("effect", "Tweens a numeric parameter of a live path effect on the targets (twist angle, wiggle time, zig zag size, trim offset\u2026).", {
|
|
1700
2001
|
effect: { type: "string", minLength: 1, description: `Effect id from get_animation's element "effects".` },
|
|
1701
2002
|
param: { type: "string", minLength: 1, description: "A numeric parameter of that effect (listed with it)." },
|
|
@@ -1792,7 +2093,8 @@ function describeMotionShots(scene) {
|
|
|
1792
2093
|
...shot.hold !== void 0 ? { hold: shot.hold } : {},
|
|
1793
2094
|
commands: shot.run.map((c, index) => {
|
|
1794
2095
|
const ct = timeline.commands.find((x) => x.shotIndex === i && x.command === index);
|
|
1795
|
-
|
|
2096
|
+
const primitive = motionFlairPrimitive(c);
|
|
2097
|
+
return { index, ...c, start: ct.start, end: ct.end, ...primitive ? { flairPrimitive: primitive } : {} };
|
|
1796
2098
|
})
|
|
1797
2099
|
};
|
|
1798
2100
|
});
|
|
@@ -1828,7 +2130,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
1828
2130
|
const getAnimation = {
|
|
1829
2131
|
name: "get_animation",
|
|
1830
2132
|
title: "Read the animation",
|
|
1831
|
-
description:
|
|
2133
|
+
description: `Returns the vector animation: its name, artwork size, length (ms), loop mode, the artwork's elements (id, type, name, parent, bounds, solid paints, live effects with their numeric parameters), every shot with its commands and their start/end times (and, where Flair has one, the Flair motion primitive a command plays as "flairPrimitive", e.g. "entrance.pop"), Flair controls, and a summary of issues. Use the ids it returns with the write tools.`,
|
|
1832
2134
|
inputSchema: object({ includeElements: { type: "boolean", description: "Include the artwork's elements (default true)." } }),
|
|
1833
2135
|
annotations: { title: "Read the animation", ...READ },
|
|
1834
2136
|
handler: ({ includeElements = true }) => {
|
|
@@ -1914,13 +2216,19 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
1914
2216
|
return { time: t, svg };
|
|
1915
2217
|
}
|
|
1916
2218
|
};
|
|
2219
|
+
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.";
|
|
2220
|
+
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.";
|
|
1917
2221
|
const exportFlairMotion = {
|
|
1918
2222
|
name: "export_flair_motion",
|
|
1919
2223
|
title: "Export as Flair vector motion",
|
|
1920
2224
|
description: "Returns the animation as a Flair SvgMotion ({ svg, animate }) that Flair's SvgPlayer plays, plus its hold, how many changes were sampled into linear steps, and notes on anything not carried over.",
|
|
1921
|
-
inputSchema: object({
|
|
2225
|
+
inputSchema: object({
|
|
2226
|
+
fps: { type: "number", minimum: 1, maximum: 120, description: "Sampling rate for changes Flair cannot express exactly (default: the scene's fps, else 30)." },
|
|
2227
|
+
curves: { type: "boolean", description: CURVES_DESCRIPTION },
|
|
2228
|
+
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION }
|
|
2229
|
+
}),
|
|
1922
2230
|
annotations: { title: "Export as Flair vector motion", ...READ },
|
|
1923
|
-
handler: ({ fps }) => controller.toFlairMotion(fps ? { fps } : {})
|
|
2231
|
+
handler: ({ fps, curves, behaviors }) => controller.toFlairMotion({ ...fps ? { fps } : {}, ...curves === void 0 ? {} : { curves }, ...behaviors === void 0 ? {} : { behaviors } })
|
|
1924
2232
|
};
|
|
1925
2233
|
const exportFlairEffect = {
|
|
1926
2234
|
name: "export_flair_effect",
|
|
@@ -1931,7 +2239,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
1931
2239
|
name: { type: "string", minLength: 1, description: "Display name (default: the scene's name)." },
|
|
1932
2240
|
description: { type: "string", description: "One sentence (default: the scene's description)." },
|
|
1933
2241
|
category: { type: "string", minLength: 1, description: "Flair catalog category, e.g. icon, loader, ui, data, text, morph (default icon)." },
|
|
1934
|
-
tags: { type: "array", items: { type: "string" }, description: "Search tags (default none)." }
|
|
2242
|
+
tags: { type: "array", items: { type: "string" }, description: "Search tags (default none)." },
|
|
2243
|
+
curves: { type: "boolean", description: CURVES_DESCRIPTION },
|
|
2244
|
+
behaviors: { type: "boolean", description: BEHAVIORS_DESCRIPTION }
|
|
1935
2245
|
}),
|
|
1936
2246
|
annotations: { title: "Export as a Flair effect", ...READ },
|
|
1937
2247
|
handler: (args) => controller.toFlairEffect(args)
|
|
@@ -1945,7 +2255,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
1945
2255
|
handler: ({ svg }) => {
|
|
1946
2256
|
let artwork;
|
|
1947
2257
|
try {
|
|
1948
|
-
artwork =
|
|
2258
|
+
artwork = _chunkFKONE6AOcjs.parseVectorSvg.call(void 0, svg);
|
|
1949
2259
|
} catch (error) {
|
|
1950
2260
|
throw new Error(`The SVG could not be read: ${error.message}. Nothing was changed.`);
|
|
1951
2261
|
}
|
|
@@ -1998,7 +2308,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
1998
2308
|
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"]),
|
|
1999
2309
|
annotations: { title: "Add commands to a shot", ...WRITE },
|
|
2000
2310
|
handler: ({ shot, commands, at }) => {
|
|
2001
|
-
const before = _nullishCoalesce(_optionalChain([scene, 'call',
|
|
2311
|
+
const before = _nullishCoalesce(_optionalChain([scene, 'call', _49 => _49(), 'access', _50 => _50.shots, 'access', _51 => _51.find, 'call', _52 => _52((s) => s.id === shot), 'optionalAccess', _53 => _53.run, 'access', _54 => _54.length]), () => ( 0));
|
|
2002
2312
|
const first = _nullishCoalesce(at, () => ( before));
|
|
2003
2313
|
return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
|
|
2004
2314
|
const shots = describeMotionShots(s);
|
|
@@ -2143,8 +2453,12 @@ How it plays
|
|
|
2143
2453
|
|
|
2144
2454
|
Commands
|
|
2145
2455
|
- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.
|
|
2456
|
+
- enter also reveals through a clip over the target's box: wipe (behind an edge travelling "direction", default right), iris (from the centre; "shape": circle or box) and split (from a line through the middle; "orientation": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.
|
|
2146
2457
|
- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.
|
|
2147
|
-
-
|
|
2458
|
+
- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting "scale".
|
|
2459
|
+
- 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
|
+
- 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).
|
|
2461
|
+
- 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.
|
|
2148
2462
|
- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).
|
|
2149
2463
|
|
|
2150
2464
|
Working method
|
|
@@ -2217,5 +2531,14 @@ Keep motion purposeful: one thing moving at a time reads best, ease-out for arri
|
|
|
2217
2531
|
|
|
2218
2532
|
|
|
2219
2533
|
|
|
2220
|
-
|
|
2534
|
+
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
|
|
2543
|
+
exports.ANIMATION_EDITOR_AGENT_INSTRUCTIONS = ANIMATION_EDITOR_AGENT_INSTRUCTIONS; exports.AnimationEditorController = AnimationEditorController; exports.FLAIR_EASES = FLAIR_EASES; 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_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.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.freshShotId = freshShotId; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.motionClipAttrs = motionClipAttrs; exports.motionCommandDuration = motionCommandDuration; 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.withViewBox = withViewBox;
|
|
2221
2544
|
//# sourceMappingURL=index.cjs.map
|