@pixerate/editor 0.73.0 → 0.74.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/THIRD_PARTY_NOTICES.md +1 -0
- package/dist/animation-editor/index.cjs +708 -298
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +36 -2
- package/dist/animation-editor/index.d.ts +36 -2
- package/dist/animation-editor/index.js +693 -283
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/chart/index.cjs +11 -9
- package/dist/chart/index.cjs.map +1 -1
- package/dist/chart/index.js +5 -3
- package/dist/chart/index.js.map +1 -1
- package/dist/{chunk-3S72F46R.js → chunk-2GFUA4X5.js} +2 -322
- package/dist/chunk-2GFUA4X5.js.map +1 -0
- package/dist/chunk-33AHNSEB.js +323 -0
- package/dist/chunk-33AHNSEB.js.map +1 -0
- package/dist/{chunk-NN3JGUSX.cjs → chunk-5PTR7HTL.cjs} +3 -323
- package/dist/chunk-5PTR7HTL.cjs.map +1 -0
- package/dist/{chunk-4YFMSPBU.js → chunk-EIXXBKUB.js} +6 -4
- package/dist/{chunk-4YFMSPBU.js.map → chunk-EIXXBKUB.js.map} +1 -1
- package/dist/chunk-EMQWJA3G.cjs +323 -0
- package/dist/chunk-EMQWJA3G.cjs.map +1 -0
- package/dist/{chunk-BQQZ6MOI.js → chunk-FGW5OWJ4.js} +6 -4
- package/dist/{chunk-BQQZ6MOI.js.map → chunk-FGW5OWJ4.js.map} +1 -1
- package/dist/{chunk-YZZMX6V7.cjs → chunk-FV5AXTSF.cjs} +11 -9
- package/dist/chunk-FV5AXTSF.cjs.map +1 -0
- package/dist/{chunk-7ZSU4MQZ.cjs → chunk-PL3MPFPA.cjs} +10 -8
- package/dist/chunk-PL3MPFPA.cjs.map +1 -0
- package/dist/export/index.cjs +4 -3
- package/dist/export/index.cjs.map +1 -1
- package/dist/export/index.js +3 -2
- package/dist/extensions/index.cjs +4 -3
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +3 -2
- package/dist/index.cjs +19 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-3S72F46R.js.map +0 -1
- package/dist/chunk-7ZSU4MQZ.cjs.map +0 -1
- package/dist/chunk-NN3JGUSX.cjs.map +0 -1
- package/dist/chunk-YZZMX6V7.cjs.map +0 -1
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
var _chunkYJLCBA7Vcjs = require('../chunk-YJLCBA7V.cjs');
|
|
22
24
|
|
|
@@ -28,6 +30,9 @@ var _chunkYJLCBA7Vcjs = require('../chunk-YJLCBA7V.cjs');
|
|
|
28
30
|
var _chunkO2UH7LZEcjs = require('../chunk-O2UH7LZE.cjs');
|
|
29
31
|
|
|
30
32
|
|
|
33
|
+
var _chunkEMQWJA3Gcjs = require('../chunk-EMQWJA3G.cjs');
|
|
34
|
+
|
|
35
|
+
|
|
31
36
|
var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
|
|
32
37
|
|
|
33
38
|
|
|
@@ -112,21 +117,21 @@ var MOTION_DEFAULT_HOLD = 600;
|
|
|
112
117
|
var MOTION_CAMERA_MS = 1e3;
|
|
113
118
|
var MOTION_DRAW_MS_PER_UNIT = 1.5;
|
|
114
119
|
var MOTION_DRAW_RANGE = [500, 2500];
|
|
115
|
-
function motionFlairPrimitive(
|
|
116
|
-
switch (
|
|
120
|
+
function motionFlairPrimitive(command3) {
|
|
121
|
+
switch (command3.type) {
|
|
117
122
|
case "enter":
|
|
118
|
-
return `entrance.${_nullishCoalesce(
|
|
123
|
+
return `entrance.${_nullishCoalesce(command3.style, () => ( "fade"))}`;
|
|
119
124
|
case "exit":
|
|
120
|
-
return `exit.${_nullishCoalesce(
|
|
125
|
+
return `exit.${_nullishCoalesce(command3.style, () => ( "fade"))}`;
|
|
121
126
|
case "pulse":
|
|
122
127
|
case "shake":
|
|
123
128
|
case "teeter":
|
|
124
129
|
case "wave":
|
|
125
130
|
case "wiggle":
|
|
126
131
|
case "color-pulse":
|
|
127
|
-
return `emphasis.${
|
|
132
|
+
return `emphasis.${command3.type}`;
|
|
128
133
|
case "rotate":
|
|
129
|
-
return
|
|
134
|
+
return command3.by !== void 0 ? "emphasis.spin" : void 0;
|
|
130
135
|
case "follow":
|
|
131
136
|
return "path.follow";
|
|
132
137
|
default:
|
|
@@ -254,108 +259,108 @@ var isPoint = (v) => isObject(v) && isNum(v.x) && isNum(v.y);
|
|
|
254
259
|
function unknownKeys(value, known, where, problems) {
|
|
255
260
|
for (const key of Object.keys(value)) if (!known.includes(key)) problems.push(`${where}: unknown field ${namedWithSuggestion(key, known)}.`);
|
|
256
261
|
}
|
|
257
|
-
function commandShapeProblems(
|
|
262
|
+
function commandShapeProblems(command3, where) {
|
|
258
263
|
const problems = [];
|
|
259
|
-
if (!isObject(
|
|
260
|
-
const type =
|
|
264
|
+
if (!isObject(command3)) return [`${where} must be an object.`];
|
|
265
|
+
const type = command3.type;
|
|
261
266
|
if (typeof type !== "string" || !MOTION_COMMAND_TYPES.includes(type)) {
|
|
262
267
|
return [`${where}: unknown type ${typeof type === "string" ? namedWithSuggestion(type, MOTION_COMMAND_TYPES) : String(type)}; use one of ${MOTION_COMMAND_TYPES.join(", ")}.`];
|
|
263
268
|
}
|
|
264
|
-
unknownKeys(
|
|
269
|
+
unknownKeys(command3, COMMAND_KEYS[type], `${where} (${type})`, problems);
|
|
265
270
|
const p = (msg) => problems.push(`${where} (${type}): ${msg}`);
|
|
266
271
|
const nonNegative = (key) => {
|
|
267
|
-
if (
|
|
272
|
+
if (command3[key] !== void 0 && !(isNum(command3[key]) && command3[key] >= 0)) p(`"${key}" must be a number of milliseconds \u2265 0.`);
|
|
268
273
|
};
|
|
269
274
|
const fraction = (key) => {
|
|
270
|
-
if (
|
|
275
|
+
if (command3[key] !== void 0 && !(isNum(command3[key]) && command3[key] >= 0 && command3[key] <= 1)) p(`"${key}" must be a fraction from 0 to 1.`);
|
|
271
276
|
};
|
|
272
277
|
const optionalNumber = (key) => {
|
|
273
|
-
if (
|
|
278
|
+
if (command3[key] !== void 0 && !isNum(command3[key])) p(`"${key}" must be a number.`);
|
|
274
279
|
};
|
|
275
|
-
if (
|
|
276
|
-
if (DRAW_ORDER_KEYS.some((k) =>
|
|
277
|
-
if (type === "enter" &&
|
|
278
|
-
if (
|
|
279
|
-
if (
|
|
280
|
-
if (
|
|
281
|
-
if (
|
|
282
|
-
if (
|
|
280
|
+
if (command3.with !== void 0 && command3.with !== "after" && command3.with !== "previous") p(`"with" must be "after" or "previous".`);
|
|
281
|
+
if (DRAW_ORDER_KEYS.some((k) => command3[k] !== void 0)) {
|
|
282
|
+
if (type === "enter" && command3.style !== "draw" || type === "exit" && command3.style !== "undraw") p(`"order", "pace", "align", "sortBy" and "origin" go with drawing: style "${type === "enter" ? "draw" : "undraw"}".`);
|
|
283
|
+
if (command3.order !== void 0 && command3.order !== "together" && command3.order !== "sequence") p(`"order" must be "together" or "sequence" (one stroke after another).`);
|
|
284
|
+
if (command3.pace !== void 0 && command3.pace !== "time" && command3.pace !== "speed") p(`"pace" must be "time" (each stroke takes the whole time) or "speed" (all at one speed).`);
|
|
285
|
+
if (command3.align !== void 0 && command3.align !== "start" && command3.align !== "end") p(`"align" must be "start" or "end".`);
|
|
286
|
+
if (command3.sortBy !== void 0 && command3.sortBy !== "document" && command3.sortBy !== "distance") p(`"sortBy" must be "document" or "distance".`);
|
|
287
|
+
if (command3.origin !== void 0 && !isPoint(command3.origin)) p(`"origin" must be { "x": number, "y": number } (document units).`);
|
|
283
288
|
}
|
|
284
|
-
if (
|
|
289
|
+
if (command3.note !== void 0 && typeof command3.note !== "string") p(`"note" must be a string.`);
|
|
285
290
|
if (type === "wait") {
|
|
286
|
-
if (!isNum(
|
|
291
|
+
if (!isNum(command3.duration) || command3.duration < 0) p(`"duration" must be a number of milliseconds \u2265 0.`);
|
|
287
292
|
return problems;
|
|
288
293
|
}
|
|
289
|
-
if (!Array.isArray(
|
|
294
|
+
if (!Array.isArray(command3.targets) || command3.targets.length === 0 || !command3.targets.every((t) => typeof t === "string" && t.length > 0)) p(`"targets" must be a non-empty list of node ids.`);
|
|
290
295
|
nonNegative("duration");
|
|
291
296
|
nonNegative("delay");
|
|
292
297
|
nonNegative("stagger");
|
|
293
|
-
if (
|
|
294
|
-
if (
|
|
298
|
+
if (command3.ease !== void 0 && !_chunk2FHLHZALcjs.isAnimationEasing.call(void 0, command3.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 }.`);
|
|
299
|
+
if (command3.repeat !== void 0) {
|
|
295
300
|
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.`);
|
|
296
|
-
else if (!(Number.isInteger(
|
|
301
|
+
else if (!(Number.isInteger(command3.repeat) && command3.repeat >= 1 && command3.repeat <= 1e3)) p(`"repeat" must be a whole number from 1 to 1000.`);
|
|
297
302
|
}
|
|
298
|
-
if (
|
|
299
|
-
if (
|
|
300
|
-
if (
|
|
303
|
+
if (command3.blend !== void 0 && !MOTION_BLENDS.includes(command3.blend)) p(`"blend" must be "replace" (the change takes over) or "add" (a layer on top).`);
|
|
304
|
+
if (command3.repeatMode !== void 0 && !MOTION_REPEAT_MODES.includes(command3.repeatMode)) p(`"repeatMode" must be one of ${MOTION_REPEAT_MODES.join(", ")}.`);
|
|
305
|
+
if (command3.steps !== void 0 && !(isNum(command3.steps) && command3.steps > 0 && command3.steps <= 120)) p(`"steps" must be frames per second from above 0 to 120 (12 holds each pose for two frames at 24 fps).`);
|
|
301
306
|
switch (type) {
|
|
302
307
|
case "enter":
|
|
303
308
|
case "exit": {
|
|
304
309
|
const styles = type === "enter" ? MOTION_ENTER_STYLES : MOTION_EXIT_STYLES;
|
|
305
|
-
if (
|
|
306
|
-
p(`"style" must be one of ${styles.join(", ")}${typeof
|
|
307
|
-
if (
|
|
310
|
+
if (command3.style !== void 0 && !(typeof command3.style === "string" && styles.includes(command3.style)))
|
|
311
|
+
p(`"style" must be one of ${styles.join(", ")}${typeof command3.style === "string" ? ` (got ${namedWithSuggestion(command3.style, styles)})` : ""}.`);
|
|
312
|
+
if (command3.direction !== void 0 && !MOTION_DIRECTIONS.includes(command3.direction)) p(`"direction" must be one of ${MOTION_DIRECTIONS.join(", ")}.`);
|
|
308
313
|
optionalNumber("distance");
|
|
309
|
-
if (
|
|
310
|
-
if (
|
|
311
|
-
if (
|
|
314
|
+
if (command3.scale !== void 0 && !(isNum(command3.scale) && command3.scale >= 0)) p(`"scale" must be a number \u2265 0 (the starting scale for pop and zoom).`);
|
|
315
|
+
if (command3.shape !== void 0 && !MOTION_IRIS_SHAPES.includes(command3.shape)) p(`"shape" must be one of ${MOTION_IRIS_SHAPES.join(", ")} (the opening of an iris).`);
|
|
316
|
+
if (command3.orientation !== void 0 && !MOTION_SPLIT_ORIENTATIONS.includes(command3.orientation)) p(`"orientation" must be one of ${MOTION_SPLIT_ORIENTATIONS.join(", ")} (the line a split opens from).`);
|
|
312
317
|
break;
|
|
313
318
|
}
|
|
314
319
|
case "draw":
|
|
315
320
|
fraction("from");
|
|
316
321
|
fraction("to");
|
|
317
322
|
fraction("comet");
|
|
318
|
-
if (
|
|
323
|
+
if (command3.comet !== void 0 && (command3.from !== void 0 || command3.to !== void 0)) p(`"comet" runs the whole path; leave out "from" and "to".`);
|
|
319
324
|
break;
|
|
320
325
|
case "move":
|
|
321
|
-
if (
|
|
322
|
-
if (
|
|
323
|
-
if (
|
|
324
|
-
if (
|
|
325
|
-
if (
|
|
326
|
-
if (
|
|
327
|
-
if (
|
|
326
|
+
if (command3.by === void 0 && command3.to === void 0) p(`give "by" (an offset) or "to" (a point).`);
|
|
327
|
+
if (command3.by !== void 0 && command3.to !== void 0) p(`give "by" or "to", not both.`);
|
|
328
|
+
if (command3.by !== void 0 && !isPoint(command3.by)) p(`"by" must be { "x": number, "y": number }.`);
|
|
329
|
+
if (command3.to !== void 0 && !isPoint(command3.to)) p(`"to" must be { "x": number, "y": number }.`);
|
|
330
|
+
if (command3.via !== void 0 && !(Array.isArray(command3.via) && command3.via.length > 0 && command3.via.length <= 64 && command3.via.every(isPoint))) p(`"via" must be a list of 1 to 64 points { "x": number, "y": number } (document units).`);
|
|
331
|
+
if (command3.pacing !== void 0 && command3.pacing !== "even" && command3.pacing !== "equal") p(`"pacing" must be "even" (steady speed) or "equal" (each leg the same time).`);
|
|
332
|
+
if (command3.pacing !== void 0 && command3.via === void 0) p(`"pacing" goes with "via".`);
|
|
328
333
|
break;
|
|
329
334
|
case "rotate":
|
|
330
|
-
if (
|
|
331
|
-
if (
|
|
335
|
+
if (command3.by === void 0 && command3.to === void 0) p(`give "by" or "to" (degrees).`);
|
|
336
|
+
if (command3.by !== void 0 && command3.to !== void 0) p(`give "by" or "to", not both.`);
|
|
332
337
|
optionalNumber("by");
|
|
333
338
|
optionalNumber("to");
|
|
334
339
|
break;
|
|
335
340
|
case "scale":
|
|
336
|
-
if (!(isNum(
|
|
337
|
-
if (
|
|
341
|
+
if (!(isNum(command3.to) || isPoint(command3.to))) p(`"to" must be a number or { "x": number, "y": number }.`);
|
|
342
|
+
if (command3.geometric !== void 0 && typeof command3.geometric !== "boolean") p(`"geometric" must be true or false.`);
|
|
338
343
|
break;
|
|
339
344
|
case "fade":
|
|
340
|
-
if (!(isNum(
|
|
345
|
+
if (!(isNum(command3.to) && command3.to >= 0 && command3.to <= 1)) p(`"to" must be an opacity from 0 to 1.`);
|
|
341
346
|
break;
|
|
342
347
|
case "style":
|
|
343
|
-
if (
|
|
344
|
-
if (
|
|
345
|
-
if (
|
|
346
|
-
if (
|
|
348
|
+
if (command3.fill === void 0 && command3.stroke === void 0 && command3.strokeWidth === void 0) p(`give at least one of "fill", "stroke" or "strokeWidth".`);
|
|
349
|
+
if (command3.fill !== void 0 && typeof command3.fill !== "string") p(`"fill" must be a CSS colour.`);
|
|
350
|
+
if (command3.stroke !== void 0 && typeof command3.stroke !== "string") p(`"stroke" must be a CSS colour.`);
|
|
351
|
+
if (command3.strokeWidth !== void 0 && !(isNum(command3.strokeWidth) && command3.strokeWidth >= 0)) p(`"strokeWidth" must be a number \u2265 0.`);
|
|
347
352
|
break;
|
|
348
353
|
case "play":
|
|
349
|
-
if (typeof
|
|
350
|
-
if (
|
|
354
|
+
if (typeof command3.clip !== "string" || !command3.clip) p(`"clip" must be the name of one of the scene's clips.`);
|
|
355
|
+
if (command3.speed !== void 0 && !(isNum(command3.speed) && command3.speed >= 0.05 && command3.speed <= 20)) p(`"speed" must be a number from 0.05 to 20 (2 plays the clip twice as fast).`);
|
|
351
356
|
break;
|
|
352
357
|
case "morph":
|
|
353
358
|
case "match":
|
|
354
|
-
if (typeof
|
|
359
|
+
if (typeof command3.into !== "string" || !command3.into) p(`"into" must be the id of a ${type === "match" ? "group to become" : "node whose shape to take"}.`);
|
|
355
360
|
break;
|
|
356
361
|
case "follow":
|
|
357
|
-
if (typeof
|
|
358
|
-
if (
|
|
362
|
+
if (typeof command3.path !== "string" || !command3.path) p(`"path" must be the id of a path node.`);
|
|
363
|
+
if (command3.rotate !== void 0 && typeof command3.rotate !== "boolean") p(`"rotate" must be true or false.`);
|
|
359
364
|
fraction("from");
|
|
360
365
|
fraction("to");
|
|
361
366
|
break;
|
|
@@ -366,22 +371,22 @@ function commandShapeProblems(command2, where) {
|
|
|
366
371
|
case "color-pulse":
|
|
367
372
|
optionalNumber("amount");
|
|
368
373
|
optionalNumber("angle");
|
|
369
|
-
if (
|
|
370
|
-
if (
|
|
371
|
-
if (
|
|
372
|
-
if (
|
|
374
|
+
if (command3.count !== void 0 && !(Number.isInteger(command3.count) && command3.count >= 1)) p(`"count" must be a whole number \u2265 1.`);
|
|
375
|
+
if (command3.axis !== void 0 && command3.axis !== "horizontal" && command3.axis !== "vertical") p(`"axis" must be "horizontal" or "vertical".`);
|
|
376
|
+
if (command3.color !== void 0 && typeof command3.color !== "string") p(`"color" must be a CSS colour.`);
|
|
377
|
+
if (command3.paint !== void 0 && command3.paint !== "fill" && command3.paint !== "stroke") p(`"paint" must be "fill" or "stroke".`);
|
|
373
378
|
break;
|
|
374
379
|
case "wiggle":
|
|
375
380
|
optionalNumber("amount");
|
|
376
381
|
optionalNumber("rotate");
|
|
377
|
-
if (
|
|
378
|
-
if (
|
|
379
|
-
if (
|
|
382
|
+
if (command3.frequency !== void 0 && !(isNum(command3.frequency) && command3.frequency > 0)) p(`"frequency" must be a number of Hz > 0.`);
|
|
383
|
+
if (command3.octaves !== void 0 && !(Number.isInteger(command3.octaves) && command3.octaves >= 1 && command3.octaves <= 8)) p(`"octaves" must be a whole number from 1 to 8.`);
|
|
384
|
+
if (command3.seed !== void 0 && !(Number.isInteger(command3.seed) && command3.seed >= 0)) p(`"seed" must be a whole number \u2265 0.`);
|
|
380
385
|
break;
|
|
381
386
|
case "effect":
|
|
382
|
-
if (typeof
|
|
383
|
-
if (typeof
|
|
384
|
-
if (!isNum(
|
|
387
|
+
if (typeof command3.effect !== "string" || !command3.effect) p(`"effect" must be the id of one of the node's effects.`);
|
|
388
|
+
if (typeof command3.param !== "string" || !command3.param) p(`"param" must name a numeric parameter of the effect.`);
|
|
389
|
+
if (!isNum(command3.to)) p(`"to" must be a number.`);
|
|
385
390
|
break;
|
|
386
391
|
}
|
|
387
392
|
return problems;
|
|
@@ -398,9 +403,9 @@ function clipsShapeProblems(clips) {
|
|
|
398
403
|
}
|
|
399
404
|
unknownKeys(clip, ["description", "run"], where, problems);
|
|
400
405
|
if (clip.description !== void 0 && typeof clip.description !== "string") problems.push(`${where}: "description" must be a string.`);
|
|
401
|
-
clip.run.forEach((
|
|
402
|
-
if (isObject(
|
|
403
|
-
else problems.push(...commandShapeProblems(
|
|
406
|
+
clip.run.forEach((command3, i) => {
|
|
407
|
+
if (isObject(command3) && command3.type === "play") problems.push(`${where}, command ${i + 1}: a clip cannot play another clip; copy its commands in instead.`);
|
|
408
|
+
else problems.push(...commandShapeProblems(command3, `${where}, command ${i + 1}`));
|
|
404
409
|
});
|
|
405
410
|
}
|
|
406
411
|
return problems;
|
|
@@ -456,7 +461,7 @@ function shotShapeProblems(shot, where) {
|
|
|
456
461
|
}
|
|
457
462
|
}
|
|
458
463
|
if (!Array.isArray(shot.run)) problems.push(`${name}: "run" must be a list of commands (it may be empty).`);
|
|
459
|
-
else shot.run.forEach((
|
|
464
|
+
else shot.run.forEach((command3, i) => problems.push(...commandShapeProblems(command3, `${name}, command ${i + 1}`)));
|
|
460
465
|
return problems;
|
|
461
466
|
}
|
|
462
467
|
function motionSceneShapeProblems(input) {
|
|
@@ -523,7 +528,7 @@ function motionSceneToJson(scene, space = 2) {
|
|
|
523
528
|
return JSON.stringify(scene, null, space);
|
|
524
529
|
}
|
|
525
530
|
var isMotionShot = (shot) => shotShapeProblems(shot, "Shot").length === 0;
|
|
526
|
-
var isMotionCommand = (
|
|
531
|
+
var isMotionCommand = (command3) => commandShapeProblems(command3, "Command").length === 0;
|
|
527
532
|
|
|
528
533
|
// src/animation-editor/match.ts
|
|
529
534
|
var SEPARATOR = /[-_/.:]/;
|
|
@@ -886,13 +891,13 @@ function motionDriverSources(timeline, node, properties, seen = /* @__PURE__ */
|
|
|
886
891
|
}
|
|
887
892
|
return out;
|
|
888
893
|
}
|
|
889
|
-
function motionCommandRepeat(
|
|
890
|
-
if (
|
|
891
|
-
const n = _nullishCoalesce(
|
|
894
|
+
function motionCommandRepeat(command3) {
|
|
895
|
+
if (command3.type === "wait" || command3.type === "enter" || command3.type === "exit") return 1;
|
|
896
|
+
const n = _nullishCoalesce(command3.repeat, () => ( 1));
|
|
892
897
|
return Number.isInteger(n) && n >= 1 ? n : 1;
|
|
893
898
|
}
|
|
894
|
-
function motionCommandDuration(
|
|
895
|
-
return motionCycleDuration(
|
|
899
|
+
function motionCommandDuration(command3, scene, target) {
|
|
900
|
+
return motionCycleDuration(command3, scene, target) * motionCommandRepeat(command3);
|
|
896
901
|
}
|
|
897
902
|
function motionClipLayout(scene, clip, target, speed = 1) {
|
|
898
903
|
const run = _optionalChain([scene, 'access', _28 => _28.clips, 'optionalAccess', _29 => _29[clip], 'optionalAccess', _30 => _30.run]);
|
|
@@ -909,36 +914,36 @@ function motionClipLayout(scene, clip, target, speed = 1) {
|
|
|
909
914
|
return;
|
|
910
915
|
}
|
|
911
916
|
if (raw.type === "play") return;
|
|
912
|
-
const
|
|
913
|
-
const begin = base + (_nullishCoalesce(
|
|
917
|
+
const command3 = { ...raw, targets: raw.targets.map((t) => t === MOTION_CLIP_TARGET ? target : t) };
|
|
918
|
+
const begin = base + (_nullishCoalesce(command3.delay, () => ( 0))) * f;
|
|
914
919
|
let end = begin;
|
|
915
|
-
|
|
916
|
-
const cycle = motionCycleDuration(
|
|
917
|
-
const s = begin + k * (_nullishCoalesce(
|
|
918
|
-
items.push({ command:
|
|
919
|
-
end = Math.max(end, s + cycle * motionCommandRepeat(
|
|
920
|
+
command3.targets.forEach((t, k) => {
|
|
921
|
+
const cycle = motionCycleDuration(command3, scene, t) * f;
|
|
922
|
+
const s = begin + k * (_nullishCoalesce(command3.stagger, () => ( 0))) * f;
|
|
923
|
+
items.push({ command: command3, target: t, start: s, cycle });
|
|
924
|
+
end = Math.max(end, s + cycle * motionCommandRepeat(command3));
|
|
920
925
|
});
|
|
921
926
|
prevStart = begin;
|
|
922
927
|
runEnd = Math.max(runEnd, end);
|
|
923
928
|
});
|
|
924
929
|
return { items, length: runEnd };
|
|
925
930
|
}
|
|
926
|
-
function motionCycleDuration(
|
|
927
|
-
if (
|
|
928
|
-
if (
|
|
929
|
-
if (
|
|
930
|
-
if (
|
|
931
|
-
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0,
|
|
931
|
+
function motionCycleDuration(command3, scene, target) {
|
|
932
|
+
if (command3.type === "wait") return command3.duration;
|
|
933
|
+
if (command3.type === "play") return motionClipLayout(scene, command3.clip, _nullishCoalesce(target, () => ( MOTION_CLIP_TARGET)), command3.speed).length;
|
|
934
|
+
if (command3.duration !== void 0) return command3.duration;
|
|
935
|
+
if (command3.ease !== void 0) {
|
|
936
|
+
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0, command3.ease);
|
|
932
937
|
if (ease !== "hold" && ease.type === "spring") return _chunk2FHLHZALcjs.springSettleMs.call(void 0, ease);
|
|
933
938
|
}
|
|
934
|
-
if (
|
|
939
|
+
if (command3.type === "draw" || command3.type === "enter" && command3.style === "draw" || command3.type === "exit" && command3.style === "undraw") {
|
|
935
940
|
const entry = target ? indexMotionNodes(scene.artwork.nodes).get(target) : void 0;
|
|
936
941
|
const length = entry ? motionPathLength(entry.node) : 0;
|
|
937
942
|
const ms = length * MOTION_DRAW_MS_PER_UNIT;
|
|
938
943
|
return Math.round(Math.min(MOTION_DRAW_RANGE[1], Math.max(MOTION_DRAW_RANGE[0], ms)));
|
|
939
944
|
}
|
|
940
|
-
if (
|
|
941
|
-
return MOTION_DEFAULT_DURATIONS[
|
|
945
|
+
if (command3.type === "move" && _optionalChain([command3, 'access', _31 => _31.via, 'optionalAccess', _32 => _32.length])) return MOTION_DEFAULT_DURATIONS.move + 400 * command3.via.length;
|
|
946
|
+
return MOTION_DEFAULT_DURATIONS[command3.type];
|
|
942
947
|
}
|
|
943
948
|
var MOTION_EASE_OUT = { type: "cubic-bezier", x1: 1 / 3, y1: 1, x2: 2 / 3, y2: 1 };
|
|
944
949
|
var MOTION_EASE_IN_OUT = { type: "cubic-bezier", x1: 0.65, y1: 0, x2: 0.35, y2: 1 };
|
|
@@ -974,14 +979,14 @@ function compileMotionScene(scene) {
|
|
|
974
979
|
const commandsStart = cursor;
|
|
975
980
|
let runEnd = cursor;
|
|
976
981
|
let prevStart = cursor;
|
|
977
|
-
shot.run.forEach((
|
|
978
|
-
const base =
|
|
979
|
-
const begin = base + (
|
|
980
|
-
const targets =
|
|
981
|
-
const durations =
|
|
982
|
-
const stagger =
|
|
982
|
+
shot.run.forEach((command3, i) => {
|
|
983
|
+
const base = command3.with === "previous" && i > 0 ? prevStart : runEnd;
|
|
984
|
+
const begin = base + (command3.type === "wait" ? 0 : (_nullishCoalesce(command3.delay, () => ( 0))) * f);
|
|
985
|
+
const targets = command3.type === "wait" ? [] : command3.targets;
|
|
986
|
+
const durations = command3.type === "wait" ? [command3.duration * f] : targets.map((id) => motionCommandDuration(command3, scene, id) * f);
|
|
987
|
+
const stagger = command3.type === "wait" ? 0 : (_nullishCoalesce(command3.stagger, () => ( 0))) * f;
|
|
983
988
|
const end2 = durations.reduce((m, d, k) => Math.max(m, begin + k * stagger + d), begin);
|
|
984
|
-
commands.push({ shot: shot.id, shotIndex: index, command: i, type:
|
|
989
|
+
commands.push({ shot: shot.id, shotIndex: index, command: i, type: command3.type, start: begin, end: end2, duration: _nullishCoalesce(durations[0], () => ( 0)) });
|
|
985
990
|
prevStart = begin;
|
|
986
991
|
runEnd = Math.max(runEnd, end2);
|
|
987
992
|
});
|
|
@@ -1013,14 +1018,14 @@ function compileMotionScene(scene) {
|
|
|
1013
1018
|
}
|
|
1014
1019
|
for (const timing of commands) {
|
|
1015
1020
|
const shot = scene.shots[timing.shotIndex];
|
|
1016
|
-
const
|
|
1017
|
-
if (
|
|
1018
|
-
if (
|
|
1021
|
+
const command3 = shot.run[timing.command];
|
|
1022
|
+
if (command3.type === "wait") continue;
|
|
1023
|
+
if (command3.type === "play") {
|
|
1019
1024
|
const f = motionShotTimeScale(shot);
|
|
1020
|
-
|
|
1025
|
+
command3.targets.forEach((target, k) => {
|
|
1021
1026
|
if (!nodes.has(target)) return;
|
|
1022
|
-
const at = timing.start + k * (_nullishCoalesce(
|
|
1023
|
-
for (const item of motionClipLayout(scene,
|
|
1027
|
+
const at = timing.start + k * (_nullishCoalesce(command3.stagger, () => ( 0))) * f;
|
|
1028
|
+
for (const item of motionClipLayout(scene, command3.clip, target, (_nullishCoalesce(command3.speed, () => ( 1))) / f).items) {
|
|
1024
1029
|
const entry = nodes.get(item.target);
|
|
1025
1030
|
if (!entry) continue;
|
|
1026
1031
|
jobs.push({ start: at + item.start, order: order++, run: () => compileRepeated(item.command, item.target, entry, at + item.start, item.cycle, timing) });
|
|
@@ -1028,24 +1033,24 @@ function compileMotionScene(scene) {
|
|
|
1028
1033
|
});
|
|
1029
1034
|
continue;
|
|
1030
1035
|
}
|
|
1031
|
-
|
|
1036
|
+
command3.targets.forEach((target, k) => {
|
|
1032
1037
|
const entry = nodes.get(target);
|
|
1033
1038
|
if (!entry) return;
|
|
1034
1039
|
const f = motionShotTimeScale(shot);
|
|
1035
|
-
const start = timing.start + k * (_nullishCoalesce(
|
|
1036
|
-
const cycle = motionCycleDuration(
|
|
1037
|
-
jobs.push({ start, order: order++, run: () => compileRepeated(
|
|
1040
|
+
const start = timing.start + k * (_nullishCoalesce(command3.stagger, () => ( 0))) * f;
|
|
1041
|
+
const cycle = motionCycleDuration(command3, scene, target) * f;
|
|
1042
|
+
jobs.push({ start, order: order++, run: () => compileRepeated(command3, target, entry, start, cycle, timing) });
|
|
1038
1043
|
});
|
|
1039
1044
|
}
|
|
1040
1045
|
jobs.sort((a, b) => a.start - b.start || a.order - b.order).forEach((job) => job.run());
|
|
1041
|
-
function compileRepeated(
|
|
1046
|
+
function compileRepeated(command3, node, entry, start, cycle, timing) {
|
|
1042
1047
|
const first = segments.length;
|
|
1043
|
-
compileCommand(
|
|
1048
|
+
compileCommand(command3, node, entry, start, cycle, timing);
|
|
1044
1049
|
const made = segments.slice(first);
|
|
1045
|
-
const steps = _nullishCoalesce(
|
|
1050
|
+
const steps = _nullishCoalesce(command3.steps, () => ( scene.steps));
|
|
1046
1051
|
if (steps && steps > 0) for (const s of made) s.steps = steps;
|
|
1047
|
-
const n = motionCommandRepeat(
|
|
1048
|
-
const mode = _nullishCoalesce(
|
|
1052
|
+
const n = motionCommandRepeat(command3);
|
|
1053
|
+
const mode = _nullishCoalesce(command3.repeatMode, () => ( "loop"));
|
|
1049
1054
|
const shift = (v, by, k) => {
|
|
1050
1055
|
if (typeof v === "number" && typeof by === "number") return v + by * k;
|
|
1051
1056
|
if (Array.isArray(v) && Array.isArray(by) && v.length === by.length) return v.map((x, i) => x + by[i] * k);
|
|
@@ -1064,16 +1069,16 @@ function compileMotionScene(scene) {
|
|
|
1064
1069
|
}
|
|
1065
1070
|
}
|
|
1066
1071
|
}
|
|
1067
|
-
function compileCommand(
|
|
1072
|
+
function compileCommand(command3, node, entry, start, duration2, timing) {
|
|
1068
1073
|
const end = start + duration2;
|
|
1069
1074
|
const where = { shot: timing.shot, command: timing.command };
|
|
1070
1075
|
const seg = (property, to, ease2, s = start, e = end, extra = {}) => push({ node, property, start: s, end: e, from: _nullishCoalesce(extra.from, () => ( valueAt(node, property, s))), to, ease: ease2, ...where, ...extra });
|
|
1071
1076
|
const rest = (p) => motionRestValue(entry, p, artwork);
|
|
1072
|
-
const
|
|
1077
|
+
const num2 = (p, time = start) => {
|
|
1073
1078
|
const v = valueAt(node, p, time);
|
|
1074
1079
|
return typeof v === "number" ? v : 0;
|
|
1075
1080
|
};
|
|
1076
|
-
const ease =
|
|
1081
|
+
const ease = command3.ease;
|
|
1077
1082
|
const drawWindows = (s, e, o) => {
|
|
1078
1083
|
const order2 = _nullishCoalesce(o.order, () => ( "together"));
|
|
1079
1084
|
const pace = _nullishCoalesce(o.pace, () => ( "time"));
|
|
@@ -1111,11 +1116,11 @@ function compileMotionScene(scene) {
|
|
|
1111
1116
|
return o.align === "end" ? { id: p.id, start: e - d, end: e } : { id: p.id, start: s, end: s + d };
|
|
1112
1117
|
});
|
|
1113
1118
|
};
|
|
1114
|
-
switch (
|
|
1119
|
+
switch (command3.type) {
|
|
1115
1120
|
case "enter": {
|
|
1116
|
-
const style = _nullishCoalesce(
|
|
1121
|
+
const style = _nullishCoalesce(command3.style, () => ( "fade"));
|
|
1117
1122
|
const opacity = rest("opacity");
|
|
1118
|
-
const reveal = style === "wipe" ? motionRevealClip(entry, { style, direction:
|
|
1123
|
+
const reveal = style === "wipe" ? motionRevealClip(entry, { style, direction: command3.direction }) : style === "iris" ? motionRevealClip(entry, { style, shape: command3.shape }) : style === "split" ? motionRevealClip(entry, { style, orientation: command3.orientation }) : null;
|
|
1119
1124
|
for (const p of ["clipRect", "clipCircle"]) if (p !== _optionalChain([reveal, 'optionalAccess', _35 => _35.property]) && tracks.has(motionTrackKey(node, p))) seg(p, rest(p), "linear", start, start);
|
|
1120
1125
|
if (reveal) {
|
|
1121
1126
|
seg("opacity", opacity, "linear", start, start);
|
|
@@ -1123,30 +1128,30 @@ function compileMotionScene(scene) {
|
|
|
1123
1128
|
break;
|
|
1124
1129
|
}
|
|
1125
1130
|
if (style === "draw") {
|
|
1126
|
-
const windows = drawWindows(start, start + duration2 * 0.75,
|
|
1131
|
+
const windows = drawWindows(start, start + duration2 * 0.75, command3);
|
|
1127
1132
|
if (windows) for (const w of windows) push({ node: w.id, property: "drawEnd", start: w.start, end: w.end, from: 0, to: 1, ease: _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), ...where });
|
|
1128
1133
|
else seg("drawEnd", 1, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, start + duration2 * 0.75, { from: 0 });
|
|
1129
1134
|
seg("fillOpacity", 1, MOTION_EASE_OUT, start + duration2 * 0.6, end, { from: 0 });
|
|
1130
1135
|
break;
|
|
1131
1136
|
}
|
|
1132
1137
|
if (style === "pop" || style === "zoom") {
|
|
1133
|
-
const from = _nullishCoalesce(
|
|
1138
|
+
const from = _nullishCoalesce(command3.scale, () => ( (style === "pop" ? 0.5 : 1.6)));
|
|
1134
1139
|
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * (style === "pop" ? 0.4 : 0.5), { from: 0 });
|
|
1135
1140
|
seg("scaleX", 1, _nullishCoalesce(ease, () => ( (style === "pop" ? "ease-out-back" : MOTION_EASE_OUT))), start, end, { from });
|
|
1136
1141
|
seg("scaleY", 1, _nullishCoalesce(ease, () => ( (style === "pop" ? "ease-out-back" : MOTION_EASE_OUT))), start, end, { from });
|
|
1137
1142
|
} else if (style === "rise") {
|
|
1138
|
-
const y =
|
|
1143
|
+
const y = num2("y");
|
|
1139
1144
|
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * 0.5, { from: 0 });
|
|
1140
|
-
seg("y", y, _nullishCoalesce(ease, () => ( "ease-out-back")), start, end, { from: y + (_nullishCoalesce(
|
|
1145
|
+
seg("y", y, _nullishCoalesce(ease, () => ( "ease-out-back")), start, end, { from: y + (_nullishCoalesce(command3.distance, () => ( 20))) });
|
|
1141
1146
|
} else if (style === "grow") {
|
|
1142
1147
|
seg("opacity", opacity, MOTION_EASE_OUT, start, start + duration2 * 0.3, { from: 0 });
|
|
1143
1148
|
seg("scaleX", 1, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: 0 });
|
|
1144
1149
|
seg("scaleY", 1, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: 0 });
|
|
1145
1150
|
} else if (style === "slide") {
|
|
1146
|
-
const dir = DIRECTION[_nullishCoalesce(
|
|
1147
|
-
const distance = _nullishCoalesce(
|
|
1148
|
-
const x =
|
|
1149
|
-
const y =
|
|
1151
|
+
const dir = DIRECTION[_nullishCoalesce(command3.direction, () => ( "up"))];
|
|
1152
|
+
const distance = _nullishCoalesce(command3.distance, () => ( 40));
|
|
1153
|
+
const x = num2("x");
|
|
1154
|
+
const y = num2("y");
|
|
1150
1155
|
seg("opacity", opacity, MOTION_EASE_OUT, start, end, { from: 0 });
|
|
1151
1156
|
seg("x", x, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: x - dir.x * distance });
|
|
1152
1157
|
seg("y", y, _nullishCoalesce(ease, () => ( MOTION_EASE_OUT)), start, end, { from: y - dir.y * distance });
|
|
@@ -1154,12 +1159,12 @@ function compileMotionScene(scene) {
|
|
|
1154
1159
|
break;
|
|
1155
1160
|
}
|
|
1156
1161
|
case "exit": {
|
|
1157
|
-
const style = _nullishCoalesce(
|
|
1158
|
-
const wipe = style === "wipe" ? motionRevealClip(entry, { style, direction:
|
|
1162
|
+
const style = _nullishCoalesce(command3.style, () => ( "fade"));
|
|
1163
|
+
const wipe = style === "wipe" ? motionRevealClip(entry, { style, direction: command3.direction, hide: true }) : null;
|
|
1159
1164
|
if (wipe) seg(wipe.property, wipe.to, _nullishCoalesce(ease, () => ( "ease-in")), start, end, { from: wipe.from });
|
|
1160
1165
|
else if (style === "undraw") {
|
|
1161
1166
|
seg("fillOpacity", 0, "ease-in", start, start + duration2 * 0.4);
|
|
1162
|
-
const windows = drawWindows(start, end,
|
|
1167
|
+
const windows = drawWindows(start, end, command3);
|
|
1163
1168
|
if (windows) for (const w of windows) push({ node: w.id, property: "drawEnd", start: w.start, end: w.end, from: valueAt(w.id, "drawEnd", w.start), to: 0, ease: _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), ...where });
|
|
1164
1169
|
else seg("drawEnd", 0, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1165
1170
|
} else if (style === "shrink") {
|
|
@@ -1167,18 +1172,18 @@ function compileMotionScene(scene) {
|
|
|
1167
1172
|
seg("scaleY", 0, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
1168
1173
|
seg("opacity", 0, "ease-in", start + duration2 * 0.6, end);
|
|
1169
1174
|
} else if (style === "slide") {
|
|
1170
|
-
const dir = DIRECTION[_nullishCoalesce(
|
|
1171
|
-
const distance = _nullishCoalesce(
|
|
1172
|
-
seg("x",
|
|
1173
|
-
seg("y",
|
|
1175
|
+
const dir = DIRECTION[_nullishCoalesce(command3.direction, () => ( "down"))];
|
|
1176
|
+
const distance = _nullishCoalesce(command3.distance, () => ( 40));
|
|
1177
|
+
seg("x", num2("x") + dir.x * distance, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
1178
|
+
seg("y", num2("y") + dir.y * distance, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
1174
1179
|
seg("opacity", 0, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
1175
1180
|
} else seg("opacity", 0, _nullishCoalesce(ease, () => ( "ease-in")));
|
|
1176
1181
|
break;
|
|
1177
1182
|
}
|
|
1178
1183
|
case "draw": {
|
|
1179
1184
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
1180
|
-
const comet =
|
|
1181
|
-
const windows = _nullishCoalesce(drawWindows(start, end,
|
|
1185
|
+
const comet = command3.comet !== void 0 ? Math.min(1, Math.max(0, command3.comet)) : void 0;
|
|
1186
|
+
const windows = _nullishCoalesce(drawWindows(start, end, command3), () => ( [{ id: node, start, end }]));
|
|
1182
1187
|
for (const w of windows) {
|
|
1183
1188
|
if (comet !== void 0) {
|
|
1184
1189
|
push({ node: w.id, property: "drawEnd", start: w.start, end: w.end, from: 0, to: 1 + comet, ease: e, ...where });
|
|
@@ -1186,27 +1191,27 @@ function compileMotionScene(scene) {
|
|
|
1186
1191
|
continue;
|
|
1187
1192
|
}
|
|
1188
1193
|
const drawn = tracks.has(motionTrackKey(w.id, "drawEnd"));
|
|
1189
|
-
push({ node: w.id, property: "drawEnd", start: w.start, end: w.end, from: _nullishCoalesce(
|
|
1194
|
+
push({ node: w.id, property: "drawEnd", start: w.start, end: w.end, from: _nullishCoalesce(command3.from, () => ( (drawn ? valueAt(w.id, "drawEnd", w.start) : 0))), to: _nullishCoalesce(command3.to, () => ( 1)), ease: e, ...where });
|
|
1190
1195
|
}
|
|
1191
1196
|
break;
|
|
1192
1197
|
}
|
|
1193
1198
|
case "move": {
|
|
1194
1199
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
1195
|
-
let dx = _nullishCoalesce(_optionalChain([
|
|
1196
|
-
let dy = _nullishCoalesce(_optionalChain([
|
|
1197
|
-
if (
|
|
1200
|
+
let dx = _nullishCoalesce(_optionalChain([command3, 'access', _36 => _36.by, 'optionalAccess', _37 => _37.x]), () => ( 0));
|
|
1201
|
+
let dy = _nullishCoalesce(_optionalChain([command3, 'access', _38 => _38.by, 'optionalAccess', _39 => _39.y]), () => ( 0));
|
|
1202
|
+
if (command3.to) {
|
|
1198
1203
|
const inv = _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
1199
|
-
const target = _chunkYJLCBA7Vcjs.applyMatrix.call(void 0, inv,
|
|
1200
|
-
dx = target.x - (entry.center.x +
|
|
1201
|
-
dy = target.y - (entry.center.y +
|
|
1204
|
+
const target = _chunkYJLCBA7Vcjs.applyMatrix.call(void 0, inv, command3.to);
|
|
1205
|
+
dx = target.x - (entry.center.x + num2("x"));
|
|
1206
|
+
dy = target.y - (entry.center.y + num2("y"));
|
|
1202
1207
|
}
|
|
1203
|
-
if (_optionalChain([
|
|
1208
|
+
if (_optionalChain([command3, 'access', _40 => _40.via, 'optionalAccess', _41 => _41.length])) {
|
|
1204
1209
|
const inv = _chunkYJLCBA7Vcjs.invertMatrix.call(void 0, entry.parentWorld);
|
|
1205
|
-
const x0 =
|
|
1206
|
-
const y0 =
|
|
1207
|
-
const add =
|
|
1208
|
-
const offsets = [{ x: 0, y: 0 }, ...
|
|
1209
|
-
const times = smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(
|
|
1210
|
+
const x0 = num2("x");
|
|
1211
|
+
const y0 = num2("y");
|
|
1212
|
+
const add = command3.blend === "add";
|
|
1213
|
+
const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkYJLCBA7Vcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
|
|
1214
|
+
const times = smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(command3.pacing, () => ( "even")));
|
|
1210
1215
|
for (const axis of ["x", "y"]) {
|
|
1211
1216
|
const base = add ? 0 : axis === "x" ? x0 : y0;
|
|
1212
1217
|
for (const leg of smoothMotionLegs(times, offsets.map((o) => o[axis])))
|
|
@@ -1214,42 +1219,42 @@ function compileMotionScene(scene) {
|
|
|
1214
1219
|
}
|
|
1215
1220
|
break;
|
|
1216
1221
|
}
|
|
1217
|
-
if (
|
|
1222
|
+
if (command3.blend === "add") {
|
|
1218
1223
|
seg("x", dx, e, start, end, { from: 0, blend: "add" });
|
|
1219
1224
|
seg("y", dy, e, start, end, { from: 0, blend: "add" });
|
|
1220
1225
|
} else {
|
|
1221
|
-
seg("x",
|
|
1222
|
-
seg("y",
|
|
1226
|
+
seg("x", num2("x") + dx, e);
|
|
1227
|
+
seg("y", num2("y") + dy, e);
|
|
1223
1228
|
}
|
|
1224
1229
|
break;
|
|
1225
1230
|
}
|
|
1226
1231
|
case "rotate": {
|
|
1227
1232
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
1228
|
-
if (
|
|
1229
|
-
else seg("rotation", _nullishCoalesce(
|
|
1233
|
+
if (command3.blend === "add") seg("rotation", command3.to !== void 0 ? command3.to - num2("rotation") : _nullishCoalesce(command3.by, () => ( 0)), e, start, end, { from: 0, blend: "add" });
|
|
1234
|
+
else seg("rotation", _nullishCoalesce(command3.to, () => ( num2("rotation") + (_nullishCoalesce(command3.by, () => ( 0))))), e);
|
|
1230
1235
|
break;
|
|
1231
1236
|
}
|
|
1232
1237
|
case "scale": {
|
|
1233
|
-
const to = typeof
|
|
1234
|
-
const extra = { ...
|
|
1238
|
+
const to = typeof command3.to === "number" ? { x: command3.to, y: command3.to } : command3.to;
|
|
1239
|
+
const extra = { ...command3.geometric ? { geometric: true } : {}, ...command3.blend === "add" ? { from: 1, blend: "add" } : {} };
|
|
1235
1240
|
seg("scaleX", to.x, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, extra);
|
|
1236
1241
|
seg("scaleY", to.y, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, extra);
|
|
1237
1242
|
break;
|
|
1238
1243
|
}
|
|
1239
1244
|
case "fade":
|
|
1240
|
-
seg("opacity",
|
|
1245
|
+
seg("opacity", command3.to, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1241
1246
|
break;
|
|
1242
1247
|
case "style":
|
|
1243
|
-
if (
|
|
1244
|
-
if (
|
|
1245
|
-
if (
|
|
1248
|
+
if (command3.fill !== void 0) seg("fill", command3.fill, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1249
|
+
if (command3.stroke !== void 0) seg("stroke", command3.stroke, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1250
|
+
if (command3.strokeWidth !== void 0) seg("strokeWidth", command3.strokeWidth, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1246
1251
|
break;
|
|
1247
1252
|
case "morph":
|
|
1248
|
-
seg("shape",
|
|
1253
|
+
seg("shape", command3.into, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1249
1254
|
break;
|
|
1250
1255
|
case "match": {
|
|
1251
|
-
const into = nodes.get(
|
|
1252
|
-
if (!into ||
|
|
1256
|
+
const into = nodes.get(command3.into);
|
|
1257
|
+
if (!into || command3.into === node) break;
|
|
1253
1258
|
const match = matchMotionNodes(entry.node, into.node);
|
|
1254
1259
|
const e = _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT));
|
|
1255
1260
|
for (const [a, b] of match.pairs) push({ node: a, property: "shape", start, end, from: valueAt(a, "shape", start), to: b, ease: e, ...where });
|
|
@@ -1257,7 +1262,7 @@ function compileMotionScene(scene) {
|
|
|
1257
1262
|
break;
|
|
1258
1263
|
}
|
|
1259
1264
|
case "follow":
|
|
1260
|
-
seg("follow", _nullishCoalesce(
|
|
1265
|
+
seg("follow", _nullishCoalesce(command3.to, () => ( 1)), _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)), start, end, { from: _nullishCoalesce(command3.from, () => ( 0)), path: command3.path, rotate: _nullishCoalesce(command3.rotate, () => ( false)) });
|
|
1261
1266
|
break;
|
|
1262
1267
|
// Emphasis: a change toward a peak that a behaviour swings round (as Flair's primitives do).
|
|
1263
1268
|
case "pulse":
|
|
@@ -1265,33 +1270,33 @@ function compileMotionScene(scene) {
|
|
|
1265
1270
|
case "teeter":
|
|
1266
1271
|
case "wave":
|
|
1267
1272
|
case "wiggle": {
|
|
1268
|
-
const add = (_nullishCoalesce(
|
|
1273
|
+
const add = (_nullishCoalesce(command3.blend, () => ( "add"))) === "add";
|
|
1269
1274
|
const swing = (p, by, extra) => {
|
|
1270
1275
|
const scale = p === "scaleX" || p === "scaleY";
|
|
1271
1276
|
if (add) seg(p, by, _nullishCoalesce(ease, () => ( "linear")), start, end, { from: scale ? 1 : 0, blend: "add", ...extra });
|
|
1272
|
-
else seg(p, scale ?
|
|
1277
|
+
else seg(p, scale ? num2(p) * by : num2(p) + by, _nullishCoalesce(ease, () => ( "linear")), start, end, extra);
|
|
1273
1278
|
};
|
|
1274
|
-
if (
|
|
1275
|
-
const behavior = { type: "pulse", count: _nullishCoalesce(
|
|
1276
|
-
swing("scaleX", 1 + (_nullishCoalesce(
|
|
1277
|
-
swing("scaleY", 1 + (_nullishCoalesce(
|
|
1278
|
-
} else if (
|
|
1279
|
-
else if (
|
|
1280
|
-
else if (
|
|
1279
|
+
if (command3.type === "pulse") {
|
|
1280
|
+
const behavior = { type: "pulse", count: _nullishCoalesce(command3.count, () => ( 1)) };
|
|
1281
|
+
swing("scaleX", 1 + (_nullishCoalesce(command3.amount, () => ( 0.15))), { behavior });
|
|
1282
|
+
swing("scaleY", 1 + (_nullishCoalesce(command3.amount, () => ( 0.15))), { behavior });
|
|
1283
|
+
} else if (command3.type === "shake") swing(command3.axis === "vertical" ? "y" : "x", _nullishCoalesce(command3.amount, () => ( 8)), { behavior: { type: "oscillate", count: _nullishCoalesce(command3.count, () => ( 3)), decay: 1 } });
|
|
1284
|
+
else if (command3.type === "teeter") swing("rotation", _nullishCoalesce(command3.angle, () => ( 8)), { behavior: { type: "oscillate", count: _nullishCoalesce(command3.count, () => ( 3)), decay: 1 } });
|
|
1285
|
+
else if (command3.type === "wave") swing("y", -(_nullishCoalesce(command3.amount, () => ( 6))), { behavior: { type: "oscillate", count: _nullishCoalesce(command3.count, () => ( 2)) } });
|
|
1281
1286
|
else {
|
|
1282
|
-
const behavior = { type: "wriggle", frequency: _nullishCoalesce(
|
|
1283
|
-
const amount = _nullishCoalesce(
|
|
1287
|
+
const behavior = { type: "wriggle", frequency: _nullishCoalesce(command3.frequency, () => ( 3)), octaves: _nullishCoalesce(command3.octaves, () => ( 2)), seed: command3.seed || _chunkZCNLBRT6cjs.motionSeedFromId.call(void 0, node) };
|
|
1288
|
+
const amount = _nullishCoalesce(command3.amount, () => ( 6));
|
|
1284
1289
|
swing("x", amount, { behavior, index: 0 });
|
|
1285
1290
|
swing("y", amount, { behavior, index: 1 });
|
|
1286
|
-
if (
|
|
1291
|
+
if (command3.rotate) swing("rotation", command3.rotate, { behavior, index: 2 });
|
|
1287
1292
|
}
|
|
1288
1293
|
break;
|
|
1289
1294
|
}
|
|
1290
1295
|
case "color-pulse":
|
|
1291
|
-
seg(_nullishCoalesce(
|
|
1296
|
+
seg(_nullishCoalesce(command3.paint, () => ( "fill")), _nullishCoalesce(command3.color, () => ( "#f59e0b")), _nullishCoalesce(ease, () => ( "linear")), start, end, { behavior: { type: "pulse", count: _nullishCoalesce(command3.count, () => ( 1)) } });
|
|
1292
1297
|
break;
|
|
1293
1298
|
case "effect":
|
|
1294
|
-
seg(`effect:${
|
|
1299
|
+
seg(`effect:${command3.effect}:${command3.param}`, command3.to, _nullishCoalesce(ease, () => ( MOTION_EASE_IN_OUT)));
|
|
1295
1300
|
break;
|
|
1296
1301
|
}
|
|
1297
1302
|
}
|
|
@@ -1682,24 +1687,24 @@ function usesColor(scene, color) {
|
|
|
1682
1687
|
return found;
|
|
1683
1688
|
}
|
|
1684
1689
|
function visibleAt(timeline, id, time, node) {
|
|
1685
|
-
const
|
|
1690
|
+
const num2 = (p, rest) => {
|
|
1686
1691
|
const v = trackValue(timeline.tracks.get(motionTrackKey(id, p)), time);
|
|
1687
1692
|
return typeof v === "number" ? v : rest;
|
|
1688
1693
|
};
|
|
1689
1694
|
if (node.visible === false) return false;
|
|
1690
|
-
if (
|
|
1691
|
-
if (Math.abs(
|
|
1695
|
+
if (num2("opacity", _nullishCoalesce(node.opacity, () => ( 1))) <= 0.01) return false;
|
|
1696
|
+
if (Math.abs(num2("scaleX", 1) * num2("scaleY", 1)) <= 1e-4) return false;
|
|
1692
1697
|
const clip = (p) => trackValue(timeline.tracks.get(motionTrackKey(id, p)), time);
|
|
1693
1698
|
const rect = clip("clipRect");
|
|
1694
1699
|
if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
|
|
1695
1700
|
const circle = clip("clipCircle");
|
|
1696
1701
|
if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
|
|
1697
1702
|
const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
|
|
1698
|
-
const drawn =
|
|
1703
|
+
const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkYJLCBA7Vcjs.collectPathNodes.call(void 0, node).some((p) => {
|
|
1699
1704
|
const v = trackValue(timeline.tracks.get(motionTrackKey(p.id, "drawEnd")), time);
|
|
1700
1705
|
return typeof v !== "number" || v > 0.01;
|
|
1701
1706
|
}));
|
|
1702
|
-
return drawn || hasFill &&
|
|
1707
|
+
return drawn || hasFill && num2("fillOpacity", 1) > 0.01;
|
|
1703
1708
|
}
|
|
1704
1709
|
function checkMotionScene(scene) {
|
|
1705
1710
|
const issues = [];
|
|
@@ -1727,48 +1732,48 @@ function checkMotionScene(scene) {
|
|
|
1727
1732
|
issues.push(motionIssue("camera-aspect", `The camera is ${c.width} \xD7 ${c.height}, a different shape from the ${scene.artwork.width} \xD7 ${scene.artwork.height} artwork, so it shows bands at the sides; frame a node instead to match.`, { shot: shot.id }));
|
|
1728
1733
|
}
|
|
1729
1734
|
if (!shot.run.length && !shot.camera && shotIndex2 > 0) issues.push(motionIssue("empty-shot", "This shot only holds; add commands or a camera move, or remove it.", { shot: shot.id }));
|
|
1730
|
-
shot.run.forEach((
|
|
1735
|
+
shot.run.forEach((command3, i) => {
|
|
1731
1736
|
const where = { shot: shot.id, command: i };
|
|
1732
|
-
if (
|
|
1733
|
-
const targets =
|
|
1737
|
+
if (command3.type === "wait") return;
|
|
1738
|
+
const targets = command3.targets.filter((id) => known(id, "unknown-target", "node", where));
|
|
1734
1739
|
const timing = timeline.commands.find((c) => c.shot === shot.id && c.command === i);
|
|
1735
1740
|
if (timing && timing.duration > 0 && timing.duration < MOTION_MIN_CHANGE_MS)
|
|
1736
|
-
issues.push(motionIssue("too-fast", `This ${
|
|
1737
|
-
if (
|
|
1738
|
-
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0,
|
|
1741
|
+
issues.push(motionIssue("too-fast", `This ${command3.type} lasts ${timing.duration} ms, too quick to follow; make it at least ${MOTION_MIN_CHANGE_MS} ms.`, { ...where, measured: timing.duration, needed: MOTION_MIN_CHANGE_MS, unit: "ms", ids: targets }));
|
|
1742
|
+
if (command3.duration !== void 0 && command3.ease !== void 0) {
|
|
1743
|
+
const ease = _chunk2FHLHZALcjs.resolveEasing.call(void 0, command3.ease);
|
|
1739
1744
|
if (ease !== "hold" && ease.type === "spring") {
|
|
1740
1745
|
const settle = _chunk2FHLHZALcjs.springSettleMs.call(void 0, ease);
|
|
1741
|
-
if (
|
|
1742
|
-
issues.push(motionIssue("spring-cut-short", `This ${
|
|
1746
|
+
if (command3.duration < settle * 0.9)
|
|
1747
|
+
issues.push(motionIssue("spring-cut-short", `This ${command3.type}'s spring takes ${settle} ms to settle but lasts ${command3.duration} ms, so it jumps to its end; leave "duration" out (the spring sets it) or make it at least ${settle} ms.`, { ...where, measured: command3.duration, needed: settle, unit: "ms", ids: targets }));
|
|
1743
1748
|
}
|
|
1744
1749
|
}
|
|
1745
|
-
if (
|
|
1746
|
-
issues.push(motionIssue("not-a-path", `"${
|
|
1747
|
-
if (
|
|
1748
|
-
if (
|
|
1749
|
-
issues.push(motionIssue("unknown-clip", `There is no clip ${namedWithSuggestion(
|
|
1750
|
-
if (
|
|
1751
|
-
const into = nodes.get(
|
|
1750
|
+
if (command3.type === "follow" && known(command3.path, "unknown-path", "path", where) && nodes.get(command3.path).node.type !== "path")
|
|
1751
|
+
issues.push(motionIssue("not-a-path", `"${command3.path}" is a group; follow a single path node.`, { ...where, ids: [command3.path] }));
|
|
1752
|
+
if (command3.type === "morph") known(command3.into, "unknown-shape", "shape", where);
|
|
1753
|
+
if (command3.type === "play" && !_optionalChain([scene, 'access', _79 => _79.clips, 'optionalAccess', _80 => _80[command3.clip]]))
|
|
1754
|
+
issues.push(motionIssue("unknown-clip", `There is no clip ${namedWithSuggestion(command3.clip, Object.keys(_nullishCoalesce(scene.clips, () => ( {}))))}; define it with set_animation_clip.`, where));
|
|
1755
|
+
if (command3.type === "match" && known(command3.into, "unknown-shape", "group", where)) {
|
|
1756
|
+
const into = nodes.get(command3.into);
|
|
1752
1757
|
for (const id of targets) {
|
|
1753
1758
|
const entry = nodes.get(id);
|
|
1754
|
-
if (id ===
|
|
1755
|
-
issues.push(motionIssue("match-self", `"${id}" cannot match "${
|
|
1759
|
+
if (id === command3.into || into.ancestors.includes(id) || entry.ancestors.includes(command3.into)) {
|
|
1760
|
+
issues.push(motionIssue("match-self", `"${id}" cannot match "${command3.into}": one is the other or holds it. Match two separate groups (the second usually hidden).`, { ...where, ids: [id, command3.into] }));
|
|
1756
1761
|
continue;
|
|
1757
1762
|
}
|
|
1758
1763
|
const m = matchMotionNodes(entry.node, into.node);
|
|
1759
1764
|
if (m.unpairedInto.length)
|
|
1760
|
-
issues.push(motionIssue("match-unpaired", `${m.unpairedInto.map((x) => `"${x}"`).join(", ")} in "${
|
|
1765
|
+
issues.push(motionIssue("match-unpaired", `${m.unpairedInto.map((x) => `"${x}"`).join(", ")} in "${command3.into}" ${m.unpairedInto.length > 1 ? "have" : "has"} no partner in "${id}", so ${m.unpairedInto.length > 1 ? "they do" : "it does"} not appear; add a part with the same name or id to "${id}" (it can start hidden or tiny).`, { ...where, ids: m.unpairedInto }));
|
|
1761
1766
|
}
|
|
1762
1767
|
}
|
|
1763
|
-
const style =
|
|
1768
|
+
const style = command3.type === "enter" || command3.type === "exit" ? command3.style : void 0;
|
|
1764
1769
|
if (style === "wipe" || style === "iris" || style === "split") {
|
|
1765
1770
|
for (const id of targets)
|
|
1766
1771
|
if (!motionRevealPadding(nodes.get(id)))
|
|
1767
|
-
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 "${
|
|
1772
|
+
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 "${command3.type === "enter" ? "draw" : "undraw"}" for a line.`, { ...where, ids: [id] }));
|
|
1768
1773
|
}
|
|
1769
|
-
if (
|
|
1774
|
+
if (command3.type === "style") {
|
|
1770
1775
|
for (const key of ["fill", "stroke"]) {
|
|
1771
|
-
const color =
|
|
1776
|
+
const color = command3[key];
|
|
1772
1777
|
if (color === void 0) continue;
|
|
1773
1778
|
if (_chunkA6PHCAGXcjs.normalizeTokenColor.call(void 0, color) === null) {
|
|
1774
1779
|
issues.push(motionIssue("invalid-color", `${key} "${color}" is not a colour this editor reads; use hex ("#0ea5e9"), rgb() or rgba().`, where));
|
|
@@ -1782,9 +1787,9 @@ function checkMotionScene(scene) {
|
|
|
1782
1787
|
}
|
|
1783
1788
|
}
|
|
1784
1789
|
}
|
|
1785
|
-
if (
|
|
1786
|
-
const key = _nullishCoalesce(
|
|
1787
|
-
const color = _nullishCoalesce(
|
|
1790
|
+
if (command3.type === "color-pulse") {
|
|
1791
|
+
const key = _nullishCoalesce(command3.paint, () => ( "fill"));
|
|
1792
|
+
const color = _nullishCoalesce(command3.color, () => ( "#f59e0b"));
|
|
1788
1793
|
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));
|
|
1789
1794
|
else
|
|
1790
1795
|
for (const id of targets) {
|
|
@@ -1794,15 +1799,15 @@ function checkMotionScene(scene) {
|
|
|
1794
1799
|
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] }));
|
|
1795
1800
|
}
|
|
1796
1801
|
}
|
|
1797
|
-
if (
|
|
1802
|
+
if (command3.type === "effect") {
|
|
1798
1803
|
for (const id of targets) {
|
|
1799
1804
|
const node = nodes.get(id).node;
|
|
1800
|
-
const params = NUMERIC_PARAMS(node,
|
|
1805
|
+
const params = NUMERIC_PARAMS(node, command3.effect);
|
|
1801
1806
|
const effects = (_nullishCoalesce(node.effects, () => ( []))).map((e) => e.id);
|
|
1802
1807
|
if (!params)
|
|
1803
|
-
issues.push(motionIssue("unknown-effect", `"${id}" has no effect ${namedWithSuggestion(
|
|
1804
|
-
else if (!params.includes(
|
|
1805
|
-
issues.push(motionIssue("unknown-effect-param", `Effect "${
|
|
1808
|
+
issues.push(motionIssue("unknown-effect", `"${id}" has no effect ${namedWithSuggestion(command3.effect, effects)}${effects.length ? `; its effects are ${effects.map((e) => `"${e}"`).join(", ")}` : "; it has no live effects"}.`, { ...where, ids: [id] }));
|
|
1809
|
+
else if (!params.includes(command3.param))
|
|
1810
|
+
issues.push(motionIssue("unknown-effect-param", `Effect "${command3.effect}" has no numeric parameter ${namedWithSuggestion(command3.param, params)}; use one of ${params.join(", ")}.`, { ...where, ids: [id] }));
|
|
1806
1811
|
}
|
|
1807
1812
|
}
|
|
1808
1813
|
if (timing) {
|
|
@@ -1810,11 +1815,11 @@ function checkMotionScene(scene) {
|
|
|
1810
1815
|
const node = nodes.get(id).node;
|
|
1811
1816
|
const before = Math.max(0, timing.start - 0.5);
|
|
1812
1817
|
const visible = timing.start > 0 ? visibleAt(timeline, id, before, node) : node.visible !== false;
|
|
1813
|
-
if (
|
|
1818
|
+
if (command3.type === "enter" && visible && timing.start > 0)
|
|
1814
1819
|
issues.push(motionIssue("enter-visible", `"${id}" is already showing when it enters, so it blinks out first; remove the enter or exit it earlier.`, { ...where, ids: [id] }));
|
|
1815
|
-
const probe =
|
|
1816
|
-
if (
|
|
1817
|
-
issues.push(motionIssue("exit-hidden", `"${id}" is hidden when this ${
|
|
1820
|
+
const probe = command3.type === "exit" ? timing.start + 0.5 : (timing.start + timing.end) / 2;
|
|
1821
|
+
if (command3.type !== "enter" && command3.type !== "draw" && !visibleAt(timeline, id, probe, node))
|
|
1822
|
+
issues.push(motionIssue("exit-hidden", `"${id}" is hidden when this ${command3.type} starts, so it is not seen; enter it first.`, { ...where, ids: [id] }));
|
|
1818
1823
|
}
|
|
1819
1824
|
}
|
|
1820
1825
|
});
|
|
@@ -1842,9 +1847,9 @@ function checkMotionScene(scene) {
|
|
|
1842
1847
|
if (loop.length) issues.push(motionIssue("driver-cycle", `Drivers follow each other round in a loop (${loop.join(" \u2190 ")}); remove one of them.`, { ids: [...new Set(loop.map((k) => k.split(".")[0]))] }));
|
|
1843
1848
|
}
|
|
1844
1849
|
for (const [name, clip] of Object.entries(_nullishCoalesce(scene.clips, () => ( {}))))
|
|
1845
|
-
for (const
|
|
1846
|
-
if (
|
|
1847
|
-
for (const id of
|
|
1850
|
+
for (const command3 of clip.run)
|
|
1851
|
+
if (command3.type !== "wait") {
|
|
1852
|
+
for (const id of command3.targets)
|
|
1848
1853
|
if (id !== MOTION_CLIP_TARGET && !nodes.has(id)) issues.push(motionIssue("unknown-target", `Clip "${name}" names ${namedWithSuggestion(id, [...nodes.keys()])}, which the artwork does not have; use "$" for the node the clip is played on.`, { ids: [id] }));
|
|
1849
1854
|
}
|
|
1850
1855
|
if (scene.trigger) {
|
|
@@ -1887,18 +1892,18 @@ function checkMotionScene(scene) {
|
|
|
1887
1892
|
}
|
|
1888
1893
|
const reported = /* @__PURE__ */ new Set();
|
|
1889
1894
|
for (const timing of timeline.commands) {
|
|
1890
|
-
const
|
|
1891
|
-
if (
|
|
1895
|
+
const command3 = scene.shots[timing.shotIndex].run[timing.command];
|
|
1896
|
+
if (command3.type === "wait" || command3.type === "exit") continue;
|
|
1892
1897
|
const frame = motionFrameAt(scene, timing.end);
|
|
1893
1898
|
const cam = frame.camera;
|
|
1894
1899
|
const docIndex = indexMotionNodes(frame.document.nodes);
|
|
1895
|
-
for (const id of
|
|
1900
|
+
for (const id of command3.targets) {
|
|
1896
1901
|
const b = _optionalChain([docIndex, 'access', _84 => _84.get, 'call', _85 => _85(id), 'optionalAccess', _86 => _86.bounds]);
|
|
1897
1902
|
if (!b || reported.has(id) || !visibleAt(timeline, id, timing.end, nodes.get(id).node)) continue;
|
|
1898
1903
|
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;
|
|
1899
1904
|
if (outside) {
|
|
1900
1905
|
reported.add(id);
|
|
1901
|
-
issues.push(motionIssue("out-of-frame", `"${id}" is outside the camera when this ${
|
|
1906
|
+
issues.push(motionIssue("out-of-frame", `"${id}" is outside the camera when this ${command3.type} ends, so it is not seen; move it into frame or move the camera.`, { shot: timing.shot, command: timing.command, ids: [id] }));
|
|
1902
1907
|
}
|
|
1903
1908
|
}
|
|
1904
1909
|
}
|
|
@@ -2052,8 +2057,8 @@ function applyOne(scene, edit) {
|
|
|
2052
2057
|
case "add_commands": {
|
|
2053
2058
|
const i = shotIndex(scene, edit.shot);
|
|
2054
2059
|
if (!edit.commands.length) fail("Give at least one command.");
|
|
2055
|
-
edit.commands.forEach((
|
|
2056
|
-
const problems = commandShapeProblems(
|
|
2060
|
+
edit.commands.forEach((command3, k) => {
|
|
2061
|
+
const problems = commandShapeProblems(command3, `Command ${k + 1}`);
|
|
2057
2062
|
if (problems.length) fail(problems.join(" "));
|
|
2058
2063
|
});
|
|
2059
2064
|
const run = scene.shots[i].run;
|
|
@@ -2065,14 +2070,14 @@ function applyOne(scene, edit) {
|
|
|
2065
2070
|
const run = scene.shots[i].run;
|
|
2066
2071
|
if (!Number.isInteger(edit.command) || edit.command < 0 || edit.command >= run.length)
|
|
2067
2072
|
fail(`Shot "${edit.shot}" has ${run.length} command${run.length === 1 ? "" : "s"}; "command" must be an index from 0 to ${run.length - 1} (got ${edit.command}).`);
|
|
2068
|
-
const
|
|
2073
|
+
const command3 = { ...run[edit.command], ..._nullishCoalesce(edit.set, () => ( {})) };
|
|
2069
2074
|
for (const key of _nullishCoalesce(edit.remove, () => ( []))) {
|
|
2070
2075
|
if (key === "type") fail('"type" cannot be removed; replace the command instead.');
|
|
2071
|
-
delete
|
|
2076
|
+
delete command3[key];
|
|
2072
2077
|
}
|
|
2073
|
-
const problems = commandShapeProblems(
|
|
2078
|
+
const problems = commandShapeProblems(command3, `Command ${edit.command}`);
|
|
2074
2079
|
if (problems.length) fail(problems.join(" "));
|
|
2075
|
-
return replaceShot(scene, i, { ...scene.shots[i], run: run.map((c, k) => k === edit.command ?
|
|
2080
|
+
return replaceShot(scene, i, { ...scene.shots[i], run: run.map((c, k) => k === edit.command ? command3 : c) });
|
|
2076
2081
|
}
|
|
2077
2082
|
case "delete_commands": {
|
|
2078
2083
|
const i = shotIndex(scene, edit.shot);
|
|
@@ -2103,9 +2108,9 @@ function applyOne(scene, edit) {
|
|
|
2103
2108
|
else delete next.presets;
|
|
2104
2109
|
}
|
|
2105
2110
|
const names = new Set(edit.controls.map((c) => c.name));
|
|
2106
|
-
for (const
|
|
2107
|
-
for (const key of Object.keys(
|
|
2108
|
-
if (!names.has(key)) fail(`Preset "${
|
|
2111
|
+
for (const preset2 of _nullishCoalesce(next.presets, () => ( [])))
|
|
2112
|
+
for (const key of Object.keys(preset2.values))
|
|
2113
|
+
if (!names.has(key)) fail(`Preset "${preset2.name}" sets ${namedWithSuggestion(key, names)}, which is not a control.`);
|
|
2109
2114
|
return next;
|
|
2110
2115
|
}
|
|
2111
2116
|
case "replace_scene":
|
|
@@ -2272,7 +2277,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2272
2277
|
const springs = flairAtLeast(flair, "0.39");
|
|
2273
2278
|
const strobes = flairAtLeast(flair, "0.39");
|
|
2274
2279
|
const writeEase = (ease) => typeof ease === "string" || "spring" in ease ? ease : ease.map(round2);
|
|
2275
|
-
const
|
|
2280
|
+
const easeOf2 = (segment) => {
|
|
2276
2281
|
const resolved = _chunk2FHLHZALcjs.resolveEasing.call(void 0, segment.ease);
|
|
2277
2282
|
if (resolved !== "hold" && resolved.type === "spring") {
|
|
2278
2283
|
if (!springs || segment.reverse) return void 0;
|
|
@@ -2451,7 +2456,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2451
2456
|
const first = active[0];
|
|
2452
2457
|
const key = (x) => JSON.stringify([x.ease, x.behavior, _nullishCoalesce(x.reverse, () => ( false)), _nullishCoalesce(x.steps, () => ( 0))]);
|
|
2453
2458
|
const together = active.every((x) => x.start === a && x.end === b && channel.exact(x) && key(x) === key(first));
|
|
2454
|
-
const curve = together ?
|
|
2459
|
+
const curve = together ? easeOf2(first) : void 0;
|
|
2455
2460
|
const ease = curve && (!overshoots(curve) || channel.overshoot) ? curve : void 0;
|
|
2456
2461
|
if (ease) {
|
|
2457
2462
|
const from = channel.value(a);
|
|
@@ -2478,7 +2483,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2478
2483
|
for (const seg of follow.segments) {
|
|
2479
2484
|
const along = { id: follow.wrapper, along: follow.routes.get(seg.path), ...seg.rotate ? { orient: true } : {} };
|
|
2480
2485
|
const progress = (t) => round2(Math.min(1, Math.max(0, Number(segmentValue(seg, t)))));
|
|
2481
|
-
const curve = seg.end > seg.start ? plays(seg) ?
|
|
2486
|
+
const curve = seg.end > seg.start ? plays(seg) ? easeOf2(seg) : void 0 : "linear";
|
|
2482
2487
|
if (curve && !(overshoots(curve) && seg.rotate)) {
|
|
2483
2488
|
const ends = seg.reverse ? [Number(seg.to), Number(seg.from)] : [Number(seg.from), Number(seg.to)];
|
|
2484
2489
|
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])] });
|
|
@@ -2722,9 +2727,9 @@ function fromFlairSvgMotion(input, options = {}) {
|
|
|
2722
2727
|
if (!anim.id) continue;
|
|
2723
2728
|
const at = Math.max(0, (_nullishCoalesce(anim.delay, () => ( 0))) - cameraMs);
|
|
2724
2729
|
if (cameraMs && (_nullishCoalesce(anim.delay, () => ( 0))) < cameraMs) notes.push(`Step ${step}: a change to "${anim.id}" during the camera move now starts after it.`);
|
|
2725
|
-
for (const
|
|
2730
|
+
for (const command3 of commandsFor(anim, nodes, entered, notes)) {
|
|
2726
2731
|
const first = run.length === 0;
|
|
2727
|
-
run.push({ ...
|
|
2732
|
+
run.push({ ...command3, ...first ? {} : { with: "previous" }, ...at - last > 0 || first ? { delay: first ? at : at - last } : {} });
|
|
2728
2733
|
if (first && at === 0) delete run[run.length - 1].delay;
|
|
2729
2734
|
last = at;
|
|
2730
2735
|
}
|
|
@@ -2974,11 +2979,11 @@ function toLottie(scene, options = {}) {
|
|
|
2974
2979
|
}
|
|
2975
2980
|
const stroke = paintOf(path.stroke, "stroke", path.id);
|
|
2976
2981
|
if (stroke || strokeFrom) {
|
|
2977
|
-
const
|
|
2982
|
+
const colour2 = strokeFrom ? track(strokeFrom, "stroke") : [];
|
|
2978
2983
|
items.push({
|
|
2979
2984
|
ty: "st",
|
|
2980
2985
|
nm: "Stroke",
|
|
2981
|
-
c:
|
|
2986
|
+
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( stroke)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(stroke, () => ( [0, 0, 0, 1]))).map(round2) },
|
|
2982
2987
|
o: { a: 0, k: 100 },
|
|
2983
2988
|
w: widthFrom ? animate(track(widthFrom, "strokeWidth"), (t) => [Math.max(0, Number(_nullishCoalesce(_nullishCoalesce(trackValue(track(widthFrom, "strokeWidth"), t), () => ( path.strokeWidth)), () => ( 1))))]) : { a: 0, k: round2(_nullishCoalesce(path.strokeWidth, () => ( 1))) },
|
|
2984
2989
|
lc: path.strokeLinecap === "round" ? 2 : path.strokeLinecap === "square" ? 3 : 1,
|
|
@@ -2990,12 +2995,12 @@ function toLottie(scene, options = {}) {
|
|
|
2990
2995
|
}
|
|
2991
2996
|
const fill = paintOf(path.fill, "fill", path.id);
|
|
2992
2997
|
if (fill || fillFrom) {
|
|
2993
|
-
const
|
|
2998
|
+
const colour2 = fillFrom ? track(fillFrom, "fill") : [];
|
|
2994
2999
|
const fade = fadeFrom ? track(fadeFrom, "fillOpacity") : [];
|
|
2995
3000
|
items.push({
|
|
2996
3001
|
ty: "fl",
|
|
2997
3002
|
nm: "Fill",
|
|
2998
|
-
c:
|
|
3003
|
+
c: colour2.length ? animate(colour2, (t) => _nullishCoalesce(_nullishCoalesce(rgba(trackValue(colour2, t)), () => ( fill)), () => ( [0, 0, 0, 1]))) : { a: 0, k: (_nullishCoalesce(fill, () => ( [0, 0, 0, 1]))).map(round2) },
|
|
2999
3004
|
o: fade.length ? animate(fade, (t) => [Math.min(1, Math.max(0, Number(_nullishCoalesce(trackValue(fade, t), () => ( 1))))) * 100]) : { a: 0, k: 100 },
|
|
3000
3005
|
r: path.fillRule === "evenodd" ? 2 : 1
|
|
3001
3006
|
});
|
|
@@ -3069,6 +3074,383 @@ function toLottie(scene, options = {}) {
|
|
|
3069
3074
|
return { lottie, sampled, notes: [...new Set(notes)] };
|
|
3070
3075
|
}
|
|
3071
3076
|
|
|
3077
|
+
// src/animation-editor/pptx.ts
|
|
3078
|
+
var EMU = 9525;
|
|
3079
|
+
var kids = (el, name) => el ? Array.from(el.children).filter((c) => c.localName === name) : [];
|
|
3080
|
+
var kid = (el, name) => _nullishCoalesce(kids(el, name)[0], () => ( null));
|
|
3081
|
+
var deep = (el, name) => el ? Array.from(el.getElementsByTagNameNS("*", name)) : [];
|
|
3082
|
+
var num = (el, attr, fallback = 0) => {
|
|
3083
|
+
const v = _optionalChain([el, 'optionalAccess', _122 => _122.getAttribute, 'call', _123 => _123(attr)]);
|
|
3084
|
+
const n = v === null || v === void 0 ? NaN : Number(v);
|
|
3085
|
+
return Number.isFinite(n) ? n : fallback;
|
|
3086
|
+
};
|
|
3087
|
+
var dirname = (p) => p.slice(0, p.lastIndexOf("/") + 1);
|
|
3088
|
+
function resolve(base, target) {
|
|
3089
|
+
const out = [];
|
|
3090
|
+
for (const seg of (target.startsWith("/") ? target.slice(1) : base + target).split("/")) {
|
|
3091
|
+
if (seg === "..") out.pop();
|
|
3092
|
+
else if (seg && seg !== ".") out.push(seg);
|
|
3093
|
+
}
|
|
3094
|
+
return out.join("/");
|
|
3095
|
+
}
|
|
3096
|
+
async function xml(ctx, path) {
|
|
3097
|
+
if (!ctx.zip.has(path)) return null;
|
|
3098
|
+
const text = new TextDecoder().decode(await ctx.zip.read(path));
|
|
3099
|
+
const doc = new ctx.Parser().parseFromString(text, "application/xml");
|
|
3100
|
+
return doc.getElementsByTagName("parsererror").length ? null : doc;
|
|
3101
|
+
}
|
|
3102
|
+
async function rels(ctx, part) {
|
|
3103
|
+
const doc = await xml(ctx, `${dirname(part)}_rels/${part.slice(part.lastIndexOf("/") + 1)}.rels`);
|
|
3104
|
+
const out = /* @__PURE__ */ new Map();
|
|
3105
|
+
for (const r of deep(doc, "Relationship")) if (r.getAttribute("TargetMode") !== "External") out.set(_nullishCoalesce(r.getAttribute("Id"), () => ( "")), resolve(dirname(part), _nullishCoalesce(r.getAttribute("Target"), () => ( ""))));
|
|
3106
|
+
return out;
|
|
3107
|
+
}
|
|
3108
|
+
function colour(ctx, holder) {
|
|
3109
|
+
if (!holder) return null;
|
|
3110
|
+
const c = holder.firstElementChild;
|
|
3111
|
+
if (!c) return null;
|
|
3112
|
+
let hex = null;
|
|
3113
|
+
if (c.localName === "srgbClr") hex = `#${(_nullishCoalesce(c.getAttribute("val"), () => ( "000000"))).toLowerCase()}`;
|
|
3114
|
+
else if (c.localName === "sysClr") hex = `#${(_nullishCoalesce(c.getAttribute("lastClr"), () => ( "000000"))).toLowerCase()}`;
|
|
3115
|
+
else if (c.localName === "schemeClr") {
|
|
3116
|
+
const name = _nullishCoalesce(c.getAttribute("val"), () => ( ""));
|
|
3117
|
+
const alias = { tx1: "dk1", bg1: "lt1", tx2: "dk2", bg2: "lt2" };
|
|
3118
|
+
hex = _nullishCoalesce(ctx.theme.get(_nullishCoalesce(alias[name], () => ( name))), () => ( null));
|
|
3119
|
+
} else if (c.localName === "prstClr") hex = _nullishCoalesce({ black: "#000000", white: "#ffffff", red: "#ff0000", green: "#008000", blue: "#0000ff" }[_nullishCoalesce(c.getAttribute("val"), () => ( ""))], () => ( null));
|
|
3120
|
+
if (!hex || !/^#[0-9a-f]{6}$/.test(hex)) return null;
|
|
3121
|
+
const lum = kid(c, "lumMod");
|
|
3122
|
+
if (lum) {
|
|
3123
|
+
const k = num(lum, "val", 1e5) / 1e5;
|
|
3124
|
+
const off = num(kid(c, "lumOff"), "val", 0) / 1e5;
|
|
3125
|
+
hex = `#${[1, 3, 5].map((i) => Math.round(Math.min(255, Math.max(0, parseInt(hex.slice(i, i + 2), 16) * k + 255 * off))).toString(16).padStart(2, "0")).join("")}`;
|
|
3126
|
+
}
|
|
3127
|
+
return hex;
|
|
3128
|
+
}
|
|
3129
|
+
function preset(prst, w, h) {
|
|
3130
|
+
const poly = (pts) => [{ closed: true, anchors: pts.map(([x, y]) => ({ x, y })) }];
|
|
3131
|
+
switch (prst) {
|
|
3132
|
+
case "rect":
|
|
3133
|
+
return [_chunkYJLCBA7Vcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
|
|
3134
|
+
case "roundRect":
|
|
3135
|
+
return [_chunkYJLCBA7Vcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
|
|
3136
|
+
case "ellipse":
|
|
3137
|
+
return [_chunkYJLCBA7Vcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
|
|
3138
|
+
case "triangle":
|
|
3139
|
+
return poly([[w / 2, 0], [w, h], [0, h]]);
|
|
3140
|
+
case "rtTriangle":
|
|
3141
|
+
return poly([[0, 0], [w, h], [0, h]]);
|
|
3142
|
+
case "diamond":
|
|
3143
|
+
return poly([[w / 2, 0], [w, h / 2], [w / 2, h], [0, h / 2]]);
|
|
3144
|
+
case "parallelogram":
|
|
3145
|
+
return poly([[w * 0.25, 0], [w, 0], [w * 0.75, h], [0, h]]);
|
|
3146
|
+
case "hexagon":
|
|
3147
|
+
return poly([[w * 0.25, 0], [w * 0.75, 0], [w, h / 2], [w * 0.75, h], [w * 0.25, h], [0, h / 2]]);
|
|
3148
|
+
case "line":
|
|
3149
|
+
case "straightConnector1":
|
|
3150
|
+
return [{ closed: false, anchors: [{ x: 0, y: 0 }, { x: w, y: h }] }];
|
|
3151
|
+
default:
|
|
3152
|
+
return null;
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
function custom(geom, w, h) {
|
|
3156
|
+
const out = [];
|
|
3157
|
+
for (const path of deep(geom, "path")) {
|
|
3158
|
+
const sx = w / (num(path, "w") || w || 1);
|
|
3159
|
+
const sy = h / (num(path, "h") || h || 1);
|
|
3160
|
+
const pt = (el) => ({ x: num(el, "x") * sx, y: num(el, "y") * sy });
|
|
3161
|
+
let cur = null;
|
|
3162
|
+
for (const cmd of Array.from(path.children)) {
|
|
3163
|
+
const pts = kids(cmd, "pt").map(pt);
|
|
3164
|
+
if (cmd.localName === "moveTo" && pts[0]) {
|
|
3165
|
+
if (cur) out.push(cur);
|
|
3166
|
+
cur = { closed: false, anchors: [{ x: pts[0].x, y: pts[0].y }] };
|
|
3167
|
+
} else if (!cur) continue;
|
|
3168
|
+
else if (cmd.localName === "lnTo" && pts[0]) cur.anchors.push({ x: pts[0].x, y: pts[0].y });
|
|
3169
|
+
else if (cmd.localName === "cubicBezTo" && pts.length === 3) {
|
|
3170
|
+
cur.anchors[cur.anchors.length - 1].out = pts[0];
|
|
3171
|
+
cur.anchors.push({ x: pts[2].x, y: pts[2].y, in: pts[1] });
|
|
3172
|
+
} else if (cmd.localName === "quadBezTo" && pts.length === 2) {
|
|
3173
|
+
const p0 = cur.anchors[cur.anchors.length - 1];
|
|
3174
|
+
cur.anchors[cur.anchors.length - 1].out = { x: p0.x + 2 / 3 * (pts[0].x - p0.x), y: p0.y + 2 / 3 * (pts[0].y - p0.y) };
|
|
3175
|
+
cur.anchors.push({ x: pts[1].x, y: pts[1].y, in: { x: pts[1].x + 2 / 3 * (pts[0].x - pts[1].x), y: pts[1].y + 2 / 3 * (pts[0].y - pts[1].y) } });
|
|
3176
|
+
} else if (cmd.localName === "close") {
|
|
3177
|
+
cur.closed = true;
|
|
3178
|
+
out.push(cur);
|
|
3179
|
+
cur = null;
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
if (cur) out.push(cur);
|
|
3183
|
+
}
|
|
3184
|
+
return out;
|
|
3185
|
+
}
|
|
3186
|
+
function placement(xfrm, map) {
|
|
3187
|
+
const off = kid(xfrm, "off");
|
|
3188
|
+
const ext = kid(xfrm, "ext");
|
|
3189
|
+
const [x, y, w, h] = map(num(off, "x"), num(off, "y"), num(ext, "cx"), num(ext, "cy"));
|
|
3190
|
+
const rot = num(xfrm, "rot") / 6e4 * (Math.PI / 180);
|
|
3191
|
+
const fx = _optionalChain([xfrm, 'optionalAccess', _124 => _124.getAttribute, 'call', _125 => _125("flipH")]) === "1" ? -1 : 1;
|
|
3192
|
+
const fy = _optionalChain([xfrm, 'optionalAccess', _126 => _126.getAttribute, 'call', _127 => _127("flipV")]) === "1" ? -1 : 1;
|
|
3193
|
+
const cx = x + w / 2;
|
|
3194
|
+
const cy = y + h / 2;
|
|
3195
|
+
const cos = Math.cos(rot);
|
|
3196
|
+
const sin = Math.sin(rot);
|
|
3197
|
+
const a = cos * fx;
|
|
3198
|
+
const b = sin * fx;
|
|
3199
|
+
const c = -sin * fy;
|
|
3200
|
+
const d = cos * fy;
|
|
3201
|
+
const e = cx - a * (w / 2) - c * (h / 2);
|
|
3202
|
+
const f = cy - b * (w / 2) - d * (h / 2);
|
|
3203
|
+
return { x, y, w, h, transform: [a, b, c, d, e, f].map((v) => v + 0) };
|
|
3204
|
+
}
|
|
3205
|
+
var idFor = (ctx, spid, name) => {
|
|
3206
|
+
const base = `${name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "shape"}-${spid}`;
|
|
3207
|
+
let id = base;
|
|
3208
|
+
for (let k = 2; ctx.used.has(id); k++) id = `${base}-${k}`;
|
|
3209
|
+
ctx.used.add(id);
|
|
3210
|
+
ctx.nodes.set(spid, id);
|
|
3211
|
+
return id;
|
|
3212
|
+
};
|
|
3213
|
+
function shapes(ctx, tree, map) {
|
|
3214
|
+
const out = [];
|
|
3215
|
+
for (const el of Array.from(tree.children)) {
|
|
3216
|
+
const nv = el.firstElementChild;
|
|
3217
|
+
const cNvPr = kid(nv, "cNvPr");
|
|
3218
|
+
const spid = num(cNvPr, "id", -1);
|
|
3219
|
+
const name = _nullishCoalesce(_optionalChain([cNvPr, 'optionalAccess', _128 => _128.getAttribute, 'call', _129 => _129("name")]), () => ( ""));
|
|
3220
|
+
if (el.localName === "grpSp") {
|
|
3221
|
+
const xfrm = kid(kid(el, "grpSpPr"), "xfrm");
|
|
3222
|
+
const off = kid(xfrm, "off");
|
|
3223
|
+
const ext = kid(xfrm, "ext");
|
|
3224
|
+
const chOff = kid(xfrm, "chOff");
|
|
3225
|
+
const chExt = kid(xfrm, "chExt");
|
|
3226
|
+
const sx = num(ext, "cx") / (num(chExt, "cx") || num(ext, "cx") || 1);
|
|
3227
|
+
const sy = num(ext, "cy") / (num(chExt, "cy") || num(ext, "cy") || 1);
|
|
3228
|
+
const inner = (x, y, w2, h2) => map(num(off, "x") + (x - num(chOff, "x")) * sx, num(off, "y") + (y - num(chOff, "y")) * sy, w2 * sx, h2 * sy);
|
|
3229
|
+
const id = idFor(ctx, spid, name || "group");
|
|
3230
|
+
out.push({ id, type: "group", ...name ? { name } : {}, children: shapes(ctx, el, inner) });
|
|
3231
|
+
continue;
|
|
3232
|
+
}
|
|
3233
|
+
if (el.localName === "pic" || el.localName === "graphicFrame") {
|
|
3234
|
+
ctx.notes.push(`"${name || `shape ${spid}`}" is a ${el.localName === "pic" ? "picture" : "chart, table or diagram"}, which the artwork cannot hold; it was left out.`);
|
|
3235
|
+
continue;
|
|
3236
|
+
}
|
|
3237
|
+
if (el.localName !== "sp" && el.localName !== "cxnSp") continue;
|
|
3238
|
+
const spPr = kid(el, "spPr");
|
|
3239
|
+
const { w, h, transform } = placement(kid(spPr, "xfrm"), map);
|
|
3240
|
+
const prst = _optionalChain([kid, 'call', _130 => _130(spPr, "prstGeom"), 'optionalAccess', _131 => _131.getAttribute, 'call', _132 => _132("prst")]);
|
|
3241
|
+
const cust = kid(spPr, "custGeom");
|
|
3242
|
+
let subpaths = cust ? custom(cust, w, h) : prst ? preset(prst, w, h) : null;
|
|
3243
|
+
if (!subpaths) {
|
|
3244
|
+
if (prst) ctx.notes.push(`"${name}" is a ${prst}, drawn as its bounding rectangle.`);
|
|
3245
|
+
subpaths = [_chunkYJLCBA7Vcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
|
|
3246
|
+
}
|
|
3247
|
+
const style = kid(el, "style");
|
|
3248
|
+
const fill = kid(spPr, "noFill") ? null : _nullishCoalesce(colour(ctx, kid(spPr, "solidFill")), () => ( (el.localName === "cxnSp" ? null : colour(ctx, kid(style, "fillRef")))));
|
|
3249
|
+
const ln = kid(spPr, "ln");
|
|
3250
|
+
const stroke = kid(ln, "noFill") ? null : _nullishCoalesce(colour(ctx, kid(ln, "solidFill")), () => ( colour(ctx, kid(style, "lnRef"))));
|
|
3251
|
+
if (kid(spPr, "gradFill")) ctx.notes.push(`"${name}" has a gradient fill, imported as its first colour or none.`);
|
|
3252
|
+
const text = deep(kid(el, "txBody"), "t").map((t) => _nullishCoalesce(t.textContent, () => ( ""))).join("").trim();
|
|
3253
|
+
if (text) ctx.notes.push(`"${name}" has text ("${text.slice(0, 40)}${text.length > 40 ? "\u2026" : ""}"), which the artwork cannot hold; only its shape was imported.`);
|
|
3254
|
+
const node = {
|
|
3255
|
+
id: idFor(ctx, spid, name),
|
|
3256
|
+
type: "path",
|
|
3257
|
+
...name ? { name } : {},
|
|
3258
|
+
transform,
|
|
3259
|
+
fill: _nullishCoalesce(fill, () => ( (kid(spPr, "gradFill") ? colour(ctx, kid(deep(spPr, "gs")[0], "srgbClr") ? deep(spPr, "gs")[0] : null) : null))),
|
|
3260
|
+
stroke,
|
|
3261
|
+
strokeWidth: Math.max(0.5, (num(ln, "w", 12700) || 12700) / EMU),
|
|
3262
|
+
subpaths
|
|
3263
|
+
};
|
|
3264
|
+
out.push(node);
|
|
3265
|
+
}
|
|
3266
|
+
return out;
|
|
3267
|
+
}
|
|
3268
|
+
var DIRECTION_FROM = { 1: "down", 2: "left", 4: "up", 8: "right" };
|
|
3269
|
+
var DIRECTION_TO = { 1: "up", 2: "right", 4: "down", 8: "left" };
|
|
3270
|
+
function easeOf(ctn) {
|
|
3271
|
+
const accel = num(ctn, "accel") / 1e5;
|
|
3272
|
+
const decel = num(ctn, "decel") / 1e5;
|
|
3273
|
+
if (!accel && !decel) return void 0;
|
|
3274
|
+
return { type: "cubic-bezier", x1: Math.min(1, accel), y1: 0, x2: Math.max(0, 1 - decel), y2: 1 };
|
|
3275
|
+
}
|
|
3276
|
+
function command(ctx, ctn, scene, artwork, target, hidden) {
|
|
3277
|
+
const cls = ctn.getAttribute("presetClass");
|
|
3278
|
+
const id = num(ctn, "presetID");
|
|
3279
|
+
const sub = num(ctn, "presetSubtype");
|
|
3280
|
+
const durs = [ctn, ...deep(ctn, "cTn")].map((c) => num(c, "dur", NaN)).filter(Number.isFinite);
|
|
3281
|
+
const duration = durs.length ? Math.max(...durs) : void 0;
|
|
3282
|
+
const ease = easeOf(ctn);
|
|
3283
|
+
const base = { targets: [target], ...duration !== void 0 ? { duration } : {}, ...ease ? { ease } : {} };
|
|
3284
|
+
const repeat = num(ctn, "repeatCount", 1e3) / 1e3;
|
|
3285
|
+
const auto = ctn.getAttribute("autoRev") === "1";
|
|
3286
|
+
const timing = auto || repeat > 1 ? { repeat: Math.max(1, Math.round(repeat)) * (auto ? 2 : 1), ...auto ? { repeatMode: "mirror" } : {} } : {};
|
|
3287
|
+
const label = `${cls} effect ${id} on "${target}"`;
|
|
3288
|
+
if (cls === "entr") {
|
|
3289
|
+
const by = {
|
|
3290
|
+
1: { type: "enter", ...base, duration: 0 },
|
|
3291
|
+
2: { type: "enter", style: "slide", ...base, direction: _nullishCoalesce(DIRECTION_FROM[sub], () => ( "up")), distance: Math.round(Math.max(scene.width, scene.height) / 3) },
|
|
3292
|
+
10: { type: "enter", style: "fade", ...base },
|
|
3293
|
+
9: { type: "enter", style: "fade", ...base },
|
|
3294
|
+
22: { type: "enter", style: "wipe", ...base, direction: _nullishCoalesce(DIRECTION_FROM[sub], () => ( "right")) },
|
|
3295
|
+
16: { type: "enter", style: "split", ...base, orientation: sub === 26 || sub === 42 ? "vertical" : "horizontal" },
|
|
3296
|
+
6: { type: "enter", style: "iris", ...base, shape: "circle" },
|
|
3297
|
+
4: { type: "enter", style: "iris", ...base, shape: "box" },
|
|
3298
|
+
53: { type: "enter", style: "zoom", ...base },
|
|
3299
|
+
23: { type: "enter", style: "zoom", ...base },
|
|
3300
|
+
31: { type: "enter", style: "pop", ...base },
|
|
3301
|
+
26: { type: "enter", style: "pop", ...base },
|
|
3302
|
+
55: { type: "enter", style: "grow", ...base },
|
|
3303
|
+
37: { type: "enter", style: "rise", ...base },
|
|
3304
|
+
42: { type: "enter", style: "rise", ...base }
|
|
3305
|
+
};
|
|
3306
|
+
if (by[id]) return by[id];
|
|
3307
|
+
ctx.notes.push(`${label} has no match here; it fades in instead.`);
|
|
3308
|
+
return { type: "enter", style: "fade", ...base };
|
|
3309
|
+
}
|
|
3310
|
+
if (cls === "exit") {
|
|
3311
|
+
const by = {
|
|
3312
|
+
1: { type: "exit", ...base, duration: 0 },
|
|
3313
|
+
10: { type: "exit", style: "fade", ...base },
|
|
3314
|
+
9: { type: "exit", style: "fade", ...base },
|
|
3315
|
+
2: { type: "exit", style: "slide", ...base, direction: _nullishCoalesce(DIRECTION_TO[sub], () => ( "down")), distance: Math.round(Math.max(scene.width, scene.height) / 3) },
|
|
3316
|
+
22: { type: "exit", style: "wipe", ...base, direction: _nullishCoalesce(DIRECTION_TO[sub], () => ( "right")) },
|
|
3317
|
+
53: { type: "exit", style: "shrink", ...base },
|
|
3318
|
+
31: { type: "exit", style: "shrink", ...base }
|
|
3319
|
+
};
|
|
3320
|
+
if (by[id]) return by[id];
|
|
3321
|
+
ctx.notes.push(`${label} has no match here; it fades out instead.`);
|
|
3322
|
+
return { type: "exit", style: "fade", ...base };
|
|
3323
|
+
}
|
|
3324
|
+
if (cls === "emph") {
|
|
3325
|
+
const rot = deep(ctn, "animRot")[0];
|
|
3326
|
+
const scale = kid(deep(ctn, "animScale")[0], "by");
|
|
3327
|
+
const clr = colour(ctx, kid(deep(ctn, "animClr")[0], "to"));
|
|
3328
|
+
switch (id) {
|
|
3329
|
+
case 26:
|
|
3330
|
+
return { type: "pulse", ...base, ...timing };
|
|
3331
|
+
case 27:
|
|
3332
|
+
return { type: "color-pulse", ...base, ...clr ? { color: clr } : {}, ...timing };
|
|
3333
|
+
case 32:
|
|
3334
|
+
return { type: "teeter", ...base, ...timing };
|
|
3335
|
+
case 34:
|
|
3336
|
+
return { type: "wave", ...base, ...timing };
|
|
3337
|
+
case 8:
|
|
3338
|
+
return { type: "rotate", ...base, by: rot ? num(rot, "by") / 6e4 : 360, ...timing };
|
|
3339
|
+
case 6:
|
|
3340
|
+
return { type: "scale", ...base, to: scale ? { x: num(scale, "x", 1e5) / 1e5, y: num(scale, "y", 1e5) / 1e5 } : 1.5, ...timing };
|
|
3341
|
+
case 9:
|
|
3342
|
+
return { type: "fade", ...base, to: 0.5, ...timing };
|
|
3343
|
+
case 1:
|
|
3344
|
+
case 19:
|
|
3345
|
+
return clr ? { type: "style", ...base, fill: clr, ...timing } : null;
|
|
3346
|
+
case 7:
|
|
3347
|
+
return clr ? { type: "style", ...base, stroke: clr, ...timing } : null;
|
|
3348
|
+
}
|
|
3349
|
+
ctx.notes.push(`${label} has no match here and was skipped.`);
|
|
3350
|
+
return null;
|
|
3351
|
+
}
|
|
3352
|
+
if (cls === "path") {
|
|
3353
|
+
const motion = deep(ctn, "animMotion")[0];
|
|
3354
|
+
const d = _optionalChain([motion, 'optionalAccess', _133 => _133.getAttribute, 'call', _134 => _134("path")]);
|
|
3355
|
+
if (!d) return null;
|
|
3356
|
+
const entry = artwork.flatMap(function all(n) {
|
|
3357
|
+
return n.type === "group" ? [n, ...n.children.flatMap(all)] : [n];
|
|
3358
|
+
}).find((n) => n.id === target);
|
|
3359
|
+
const t = _nullishCoalesce(_optionalChain([entry, 'optionalAccess', _135 => _135.transform]), () => ( [1, 0, 0, 1, 0, 0]));
|
|
3360
|
+
const p = _optionalChain([entry, 'optionalAccess', _136 => _136.type]) === "path" ? _optionalChain([entry, 'access', _137 => _137.subpaths, 'access', _138 => _138[0], 'optionalAccess', _139 => _139.anchors]) : void 0;
|
|
3361
|
+
const xs = (_nullishCoalesce(p, () => ( []))).map((a) => a.x);
|
|
3362
|
+
const ys = (_nullishCoalesce(p, () => ( []))).map((a) => a.y);
|
|
3363
|
+
const lx = xs.length ? (Math.min(...xs) + Math.max(...xs)) / 2 : 0;
|
|
3364
|
+
const ly = ys.length ? (Math.min(...ys) + Math.max(...ys)) / 2 : 0;
|
|
3365
|
+
const cx = t[0] * lx + t[2] * ly + t[4];
|
|
3366
|
+
const cy = t[1] * lx + t[3] * ly + t[5];
|
|
3367
|
+
const nums = _nullishCoalesce(d.match(/[MLCZE]|-?[\d.]+(?:e-?\d+)?/gi), () => ( []));
|
|
3368
|
+
const sp = { closed: false, anchors: [] };
|
|
3369
|
+
let i = 0;
|
|
3370
|
+
const read = () => ({ x: cx + Number(nums[i++]) * scene.width, y: cy + Number(nums[i++]) * scene.height });
|
|
3371
|
+
while (i < nums.length) {
|
|
3372
|
+
const c = nums[i++].toUpperCase();
|
|
3373
|
+
if (c === "M" || c === "L") sp.anchors.push(read());
|
|
3374
|
+
else if (c === "C") {
|
|
3375
|
+
const c1 = read();
|
|
3376
|
+
const c2 = read();
|
|
3377
|
+
const e = read();
|
|
3378
|
+
if (sp.anchors.length) sp.anchors[sp.anchors.length - 1].out = c1;
|
|
3379
|
+
sp.anchors.push({ ...e, in: c2 });
|
|
3380
|
+
} else if (c === "Z") sp.closed = true;
|
|
3381
|
+
}
|
|
3382
|
+
if (sp.anchors.length < 2) return null;
|
|
3383
|
+
const pathId = `${target}-path-${hidden.length + 1}`;
|
|
3384
|
+
hidden.push({ id: pathId, type: "path", name: "Motion path", visible: false, fill: null, stroke: "#94a3b8", subpaths: [sp] });
|
|
3385
|
+
return { type: "follow", ...base, path: pathId, ...timing };
|
|
3386
|
+
}
|
|
3387
|
+
return null;
|
|
3388
|
+
}
|
|
3389
|
+
async function fromPptxAnimation(data, options = {}) {
|
|
3390
|
+
const Parser = _nullishCoalesce(options.DOMParser, () => ( globalThis.DOMParser));
|
|
3391
|
+
if (!Parser) throw new Error("No DOMParser: pass one in options (jsdom's or xmldom's in Node).");
|
|
3392
|
+
let zip;
|
|
3393
|
+
try {
|
|
3394
|
+
zip = await _chunkEMQWJA3Gcjs.readZip.call(void 0, data, options);
|
|
3395
|
+
} catch (error) {
|
|
3396
|
+
throw new Error(`This is not a PowerPoint file (.pptx): ${error.message}`);
|
|
3397
|
+
}
|
|
3398
|
+
const ctx = { zip, Parser, notes: [], theme: /* @__PURE__ */ new Map(), nodes: /* @__PURE__ */ new Map(), used: /* @__PURE__ */ new Set() };
|
|
3399
|
+
const pres = await xml(ctx, "ppt/presentation.xml");
|
|
3400
|
+
if (!pres) throw new Error("This is not a PowerPoint file (.pptx): it has no ppt/presentation.xml.");
|
|
3401
|
+
const presRels = await rels(ctx, "ppt/presentation.xml");
|
|
3402
|
+
const slidePaths = deep(pres, "sldId").map((s) => _nullishCoalesce(presRels.get(_nullishCoalesce(_nullishCoalesce(s.getAttributeNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id"), () => ( s.getAttribute("r:id"))), () => ( ""))), () => ( ""))).filter(Boolean);
|
|
3403
|
+
const n = _nullishCoalesce(options.slide, () => ( 1));
|
|
3404
|
+
if (!(Number.isInteger(n) && n >= 1 && n <= slidePaths.length)) throw new Error(`There is no slide ${n}; the file has ${slidePaths.length} slide${slidePaths.length === 1 ? "" : "s"}.`);
|
|
3405
|
+
const size = deep(pres, "sldSz")[0];
|
|
3406
|
+
const width = Math.round(num(size, "cx", 12192e3) / EMU);
|
|
3407
|
+
const height = Math.round(num(size, "cy", 6858e3) / EMU);
|
|
3408
|
+
for (const [, path] of presRels) {
|
|
3409
|
+
if (!path.includes("theme/")) continue;
|
|
3410
|
+
const theme = await xml(ctx, path);
|
|
3411
|
+
const scheme = deep(theme, "clrScheme")[0];
|
|
3412
|
+
for (const c of Array.from(_nullishCoalesce(_optionalChain([scheme, 'optionalAccess', _140 => _140.children]), () => ( [])))) {
|
|
3413
|
+
const v = c.firstElementChild;
|
|
3414
|
+
const hex = _optionalChain([v, 'optionalAccess', _141 => _141.localName]) === "srgbClr" ? v.getAttribute("val") : _optionalChain([v, 'optionalAccess', _142 => _142.getAttribute, 'call', _143 => _143("lastClr")]);
|
|
3415
|
+
if (hex) ctx.theme.set(c.localName, `#${hex.toLowerCase()}`);
|
|
3416
|
+
}
|
|
3417
|
+
break;
|
|
3418
|
+
}
|
|
3419
|
+
const slide = await xml(ctx, slidePaths[n - 1]);
|
|
3420
|
+
if (!slide) throw new Error(`Slide ${n} cannot be read.`);
|
|
3421
|
+
const tree = deep(slide, "spTree")[0];
|
|
3422
|
+
const toPx = (x, y, w, h) => [x / EMU, y / EMU, w / EMU, h / EMU];
|
|
3423
|
+
const nodes = tree ? shapes(ctx, tree, toPx) : [];
|
|
3424
|
+
const bg = _nullishCoalesce(colour(ctx, _nullishCoalesce(deep(deep(slide, "bg")[0], "solidFill")[0], () => ( null))), () => ( "#ffffff"));
|
|
3425
|
+
const hidden = [];
|
|
3426
|
+
const shots = [];
|
|
3427
|
+
const effects = deep(deep(slide, "timing")[0], "cTn").filter((c) => c.hasAttribute("presetClass"));
|
|
3428
|
+
for (const ctn of effects) {
|
|
3429
|
+
const spid = num(deep(ctn, "spTgt")[0], "spid", -1);
|
|
3430
|
+
const target = ctx.nodes.get(spid);
|
|
3431
|
+
if (!target) {
|
|
3432
|
+
ctx.notes.push(`An effect targets shape ${spid}, which was not imported; it was skipped.`);
|
|
3433
|
+
continue;
|
|
3434
|
+
}
|
|
3435
|
+
if (deep(ctn, "txEl").length) ctx.notes.push(`An effect on "${target}" animates part of its text, which was not imported; it animates the whole shape.`);
|
|
3436
|
+
const cmd = command(ctx, ctn, { width, height }, nodes, target, hidden);
|
|
3437
|
+
if (!cmd) continue;
|
|
3438
|
+
const kind = ctn.getAttribute("nodeType");
|
|
3439
|
+
const delay = num(kid(kid(ctn, "stCondLst"), "cond"), "delay", 0);
|
|
3440
|
+
if (kind === "clickEffect" || !shots.length) shots.push({ id: `click-${shots.length + 1}`, run: [] });
|
|
3441
|
+
const run = shots[shots.length - 1].run;
|
|
3442
|
+
const placed = { ...cmd, ...delay > 0 ? { delay } : {}, ...kind === "withEffect" && run.length ? { with: "previous" } : {} };
|
|
3443
|
+
run.push(placed);
|
|
3444
|
+
}
|
|
3445
|
+
if (effects.length && !shots.length) ctx.notes.push("The slide's effects could not be read.");
|
|
3446
|
+
const artwork = { width, height, background: bg, nodes: [...nodes, ...hidden] };
|
|
3447
|
+
const scene = { version: 1, name: `slide-${n}`, artwork, shots, ...shots.length > 1 ? { trigger: "click" } : {} };
|
|
3448
|
+
const problems = motionSceneShapeProblems(scene);
|
|
3449
|
+
if (problems.length) throw new Error(`The imported scene is not well formed:
|
|
3450
|
+
${problems.join("\n")}`);
|
|
3451
|
+
return { scene, notes: [...new Set(ctx.notes)], issues: checkMotionScene(scene), slides: slidePaths.length };
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3072
3454
|
// src/animation-editor/controller.ts
|
|
3073
3455
|
var BLANK = { width: 800, height: 450, background: "#ffffff", nodes: [] };
|
|
3074
3456
|
var AnimationEditorController = (_class = class {
|
|
@@ -3136,7 +3518,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3136
3518
|
time: p.time,
|
|
3137
3519
|
playing: p.playing,
|
|
3138
3520
|
loop: p.loop,
|
|
3139
|
-
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call',
|
|
3521
|
+
currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _144 => _144(timeline, p.time), 'optionalAccess', _145 => _145.id]), () => ( null)),
|
|
3140
3522
|
selection: this.selection,
|
|
3141
3523
|
readOnly: this.readOnly,
|
|
3142
3524
|
error: this.error,
|
|
@@ -3175,7 +3557,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3175
3557
|
this.applying = false;
|
|
3176
3558
|
}
|
|
3177
3559
|
this.notify();
|
|
3178
|
-
_optionalChain([this, 'access',
|
|
3560
|
+
_optionalChain([this, 'access', _146 => _146.onChange, 'optionalCall', _147 => _147(scene)]);
|
|
3179
3561
|
}
|
|
3180
3562
|
commit(label, next) {
|
|
3181
3563
|
const before = this.scene;
|
|
@@ -3184,14 +3566,14 @@ var AnimationEditorController = (_class = class {
|
|
|
3184
3566
|
this.notify();
|
|
3185
3567
|
return;
|
|
3186
3568
|
}
|
|
3187
|
-
const
|
|
3569
|
+
const command3 = {
|
|
3188
3570
|
name: label,
|
|
3189
3571
|
tag: "animation-editor",
|
|
3190
3572
|
execute: () => this.setScene(next),
|
|
3191
3573
|
undo: () => this.setScene(before),
|
|
3192
3574
|
redo: () => this.setScene(next)
|
|
3193
3575
|
};
|
|
3194
|
-
this.history.execute(
|
|
3576
|
+
this.history.execute(command3);
|
|
3195
3577
|
}
|
|
3196
3578
|
refuse(message) {
|
|
3197
3579
|
this.error = message;
|
|
@@ -3364,11 +3746,11 @@ var DRAW_ORDER = {
|
|
|
3364
3746
|
sortBy: { type: "string", enum: ["document", "distance"], description: "With sequence: stacking order (default) or distance from origin (a radial reveal)." },
|
|
3365
3747
|
origin: object({ x: { type: "number", description: "Document units." }, y: { type: "number", description: "Document units." } }, ["x", "y"], "With sortBy distance: where strokes are drawn out from (default the target's centre).")
|
|
3366
3748
|
};
|
|
3367
|
-
var
|
|
3749
|
+
var command2 = (type, description, extra = {}, required = []) => object({ type: { const: type, description }, ...BASE, ...extra }, ["type", "targets", ...required], description);
|
|
3368
3750
|
var MOTION_COMMAND_SCHEMA = {
|
|
3369
3751
|
description: `A command (one of ${MOTION_COMMAND_TYPES.join(", ")}). Commands in a shot play one after another unless "with": "previous".`,
|
|
3370
3752
|
oneOf: [
|
|
3371
|
-
|
|
3753
|
+
command2("enter", "Brings hidden targets in; they are hidden before this shot.", {
|
|
3372
3754
|
...DRAW_ORDER,
|
|
3373
3755
|
style: {
|
|
3374
3756
|
type: "string",
|
|
@@ -3381,18 +3763,18 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
3381
3763
|
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." },
|
|
3382
3764
|
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." }
|
|
3383
3765
|
}),
|
|
3384
|
-
|
|
3766
|
+
command2("exit", "Takes targets out.", {
|
|
3385
3767
|
...DRAW_ORDER,
|
|
3386
3768
|
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)." },
|
|
3387
3769
|
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)." },
|
|
3388
3770
|
distance: { type: "number", description: "For slide: document units (default 40)." }
|
|
3389
3771
|
}),
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3772
|
+
command2("draw", "Draws strokes on (or off) to a fraction of their length.", { ...DRAW_ORDER, comet: FRACTION("A travelling stroke this fraction of the length long: it runs along the path and off the end (leave out from and to)."), to: FRACTION("Fraction drawn at the end (default 1)."), from: FRACTION("Fraction drawn at the start (default: what is drawn now).") }),
|
|
3773
|
+
command2("move", "Moves targets by an offset or so their centre lands on a point.", { via: { type: "array", items: POINT("A point the centre passes through."), minItems: 1, maxItems: 64, description: 'Waypoints (document units) the centre passes through on the way to "to" or "by", smoothly (velocity carries through each) and without overshooting any. Default length 700 ms + 400 per waypoint.' }, pacing: { type: "string", enum: ["even", "equal"], description: "With via: even (default) keeps the speed steady along the path; equal gives each stretch the same time." }, blend: BLEND("replace"), by: POINT("Offset in document units."), to: POINT("Point (document coordinates) for the centre.") }),
|
|
3774
|
+
command2("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." } }),
|
|
3775
|
+
command2("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"]),
|
|
3776
|
+
command2("fade", "Changes opacity.", { to: FRACTION("Opacity at the end (0\u20131).") }, ["to"]),
|
|
3777
|
+
command2("style", "Blends solid fill / stroke colours (in OKLab) and stroke width. On a group it changes every path in it.", {
|
|
3396
3778
|
fill: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
|
|
3397
3779
|
stroke: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
|
|
3398
3780
|
strokeWidth: { type: "number", minimum: 0, description: "Document units." }
|
|
@@ -3411,24 +3793,24 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
3411
3793
|
["type", "targets", "clip"],
|
|
3412
3794
|
"Plays a clip on the targets."
|
|
3413
3795
|
),
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3796
|
+
command2("match", `Smart Animate: tweens a group into another group (usually hidden), part by part. Parts pair by name, then by id with the group ids taken out (card-a-title \u2194 card-b-title), then by kind in order; each takes its partner's shape, paint and place. Unpaired parts fade out; parts of "into" with no partner do not appear (check_animation lists them).`, { into: { type: "string", minLength: 1, description: "Id of the group to become." } }, ["into"]),
|
|
3797
|
+
command2("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"]),
|
|
3798
|
+
command2("follow", "Moves targets along a path node, centre on the path.", {
|
|
3417
3799
|
path: { type: "string", minLength: 1, description: "Id of a path node (it can be hidden)." },
|
|
3418
3800
|
rotate: { type: "boolean", description: "Turn with the path (default false); moves and shakes made meanwhile turn with it too." },
|
|
3419
3801
|
from: FRACTION("Where to start along the path (default 0)."),
|
|
3420
3802
|
to: FRACTION("Where to end along the path (default 1).")
|
|
3421
3803
|
}, ["path"]),
|
|
3422
|
-
|
|
3423
|
-
|
|
3804
|
+
command2("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)." } }),
|
|
3805
|
+
command2("shake", "Shakes side to side (or up and down), settling.", {
|
|
3424
3806
|
blend: BLEND("add"),
|
|
3425
3807
|
amount: { type: "number", description: "Document units (default 8)." },
|
|
3426
3808
|
count: { type: "integer", minimum: 1, description: "Shakes (default 3)." },
|
|
3427
3809
|
axis: { type: "string", enum: ["horizontal", "vertical"], description: "Default horizontal." }
|
|
3428
3810
|
}),
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3811
|
+
command2("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)." } }),
|
|
3812
|
+
command2("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)." } }),
|
|
3813
|
+
command2("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.", {
|
|
3432
3814
|
blend: BLEND("add"),
|
|
3433
3815
|
amount: { type: "number", description: "Up to about this far, in document units (default 6)." },
|
|
3434
3816
|
frequency: { type: "number", exclusiveMinimum: 0, description: "Wanders per second, in Hz (default 3)." },
|
|
@@ -3436,12 +3818,12 @@ var MOTION_COMMAND_SCHEMA = {
|
|
|
3436
3818
|
rotate: { type: "number", description: "Also turns about the centre by up to about this many degrees (default 0)." },
|
|
3437
3819
|
seed: { type: "integer", minimum: 0, description: "Default: one picked from the target id, so each target wanders its own way." }
|
|
3438
3820
|
}),
|
|
3439
|
-
|
|
3821
|
+
command2("color-pulse", "Tints solid paint toward a colour and back (mixed in OKLab). On a group it tints every path in it.", {
|
|
3440
3822
|
color: { type: "string", description: 'The tint, a CSS colour (default "#f59e0b").' },
|
|
3441
3823
|
paint: { type: "string", enum: ["fill", "stroke"], description: "Which paint (default fill)." },
|
|
3442
3824
|
count: { type: "integer", minimum: 1, description: "Pulses (default 1)." }
|
|
3443
3825
|
}),
|
|
3444
|
-
|
|
3826
|
+
command2("effect", "Tweens a numeric parameter of a live path effect on the targets (twist angle, wiggle time, zig zag size, trim offset\u2026).", {
|
|
3445
3827
|
effect: { type: "string", minLength: 1, description: `Effect id from get_animation's element "effects".` },
|
|
3446
3828
|
param: { type: "string", minLength: 1, description: "A numeric parameter of that effect (listed with it)." },
|
|
3447
3829
|
to: { type: "number", description: "Value at the end." }
|
|
@@ -3740,9 +4122,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3740
4122
|
handler: ({ from = 0, to, limit = 200 }) => {
|
|
3741
4123
|
const s = scene();
|
|
3742
4124
|
const timeline = compileMotionScene(s);
|
|
3743
|
-
const words = _nullishCoalesce(_optionalChain([s, 'access',
|
|
4125
|
+
const words = _nullishCoalesce(_optionalChain([s, 'access', _148 => _148.narration, 'optionalAccess', _149 => _149.words]), () => ( []));
|
|
3744
4126
|
const end = _nullishCoalesce(to, () => ( Math.max(timeline.duration, words.length ? _nullishCoalesce(words[words.length - 1].end, () => ( words[words.length - 1].start)) : 0)));
|
|
3745
|
-
const shotAt = (ms) => _optionalChain([timeline, 'access',
|
|
4127
|
+
const shotAt = (ms) => _optionalChain([timeline, 'access', _150 => _150.shots, 'access', _151 => _151.find, 'call', _152 => _152((x) => ms >= x.start && ms < x.end), 'optionalAccess', _153 => _153.id]);
|
|
3746
4128
|
const beats = [];
|
|
3747
4129
|
if (s.beat && s.beat.bpm > 0) {
|
|
3748
4130
|
const first = Math.max(0, Math.ceil(motionBeatAt(s.beat, from).beat - 1e-9));
|
|
@@ -3835,6 +4217,33 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
3835
4217
|
return apply({ op: "set_artwork", artwork }, "Replace artwork", (s) => ({ elements: describeMotionElements(s) }));
|
|
3836
4218
|
}
|
|
3837
4219
|
};
|
|
4220
|
+
const importPptx = {
|
|
4221
|
+
name: "import_pptx_animation",
|
|
4222
|
+
title: "Import a PowerPoint slide's animation",
|
|
4223
|
+
description: "Replaces the whole animation with a PowerPoint slide (one undo step): its shapes become the artwork and its animation pane becomes shots, a shot per click (with previous / after previous, delays, repeats and acceleration kept; the scene plays on click). Text, pictures and charts are left out and effects with no match fade, with notes. Returns the shots, notes and issues. With dry_run it only reports them.",
|
|
4224
|
+
inputSchema: object(
|
|
4225
|
+
{
|
|
4226
|
+
data: { type: "string", minLength: 1, description: "The .pptx file, base64-encoded." },
|
|
4227
|
+
slide: { type: "integer", minimum: 1, description: "Which slide (1 = first, default 1)." },
|
|
4228
|
+
dry_run: { type: "boolean", description: "Report without replacing anything (default false)." }
|
|
4229
|
+
},
|
|
4230
|
+
["data"]
|
|
4231
|
+
),
|
|
4232
|
+
annotations: { title: "Import a PowerPoint slide's animation", ...DESTRUCTIVE },
|
|
4233
|
+
handler: async ({ data, slide, dry_run = false }) => {
|
|
4234
|
+
let result;
|
|
4235
|
+
try {
|
|
4236
|
+
const bytes = Uint8Array.from(atob(data.replace(/\s+/g, "")), (c) => c.charCodeAt(0));
|
|
4237
|
+
result = await fromPptxAnimation(bytes, slide ? { slide } : {});
|
|
4238
|
+
} catch (error) {
|
|
4239
|
+
throw new Error(`The slide could not be imported: ${error.message} Nothing was changed.`);
|
|
4240
|
+
}
|
|
4241
|
+
const report = { slides: result.slides, notes: result.notes, issues: issueSummary(result.issues), shots: describeMotionShots(result.scene).map(({ id, start, end, commands }) => ({ id, start, end, commands: commands.length })) };
|
|
4242
|
+
if (dry_run) return { dry_run: true, ...report, hint: "Nothing was replaced; call again without dry_run to import." };
|
|
4243
|
+
const applied = controller.apply({ op: "replace_scene", scene: result.scene }, "Import PowerPoint slide");
|
|
4244
|
+
return outcome(applied, applied.ok ? { ...report, elements: describeMotionElements(result.scene) } : {});
|
|
4245
|
+
}
|
|
4246
|
+
};
|
|
3838
4247
|
const importFlairEffect = {
|
|
3839
4248
|
name: "import_flair_effect",
|
|
3840
4249
|
title: "Import a Flair effect",
|
|
@@ -4022,7 +4431,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4022
4431
|
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"]),
|
|
4023
4432
|
annotations: { title: "Add commands to a shot", ...WRITE },
|
|
4024
4433
|
handler: ({ shot, commands, at }) => {
|
|
4025
|
-
const before = _nullishCoalesce(_optionalChain([scene, 'call',
|
|
4434
|
+
const before = _nullishCoalesce(_optionalChain([scene, 'call', _154 => _154(), 'access', _155 => _155.shots, 'access', _156 => _156.find, 'call', _157 => _157((s) => s.id === shot), 'optionalAccess', _158 => _158.run, 'access', _159 => _159.length]), () => ( 0));
|
|
4026
4435
|
const first = _nullishCoalesce(at, () => ( before));
|
|
4027
4436
|
return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
|
|
4028
4437
|
const shots = describeMotionShots(s);
|
|
@@ -4045,7 +4454,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4045
4454
|
["shot", "command"]
|
|
4046
4455
|
),
|
|
4047
4456
|
annotations: { title: "Change a command", ...WRITE_IDEMPOTENT },
|
|
4048
|
-
handler: ({ shot, command:
|
|
4457
|
+
handler: ({ shot, command: command3, set, remove }) => apply({ op: "update_command", shot, command: command3, set, remove }, "Change command", (s) => ({ command: describeMotionShots(s).find((x) => x.id === shot).commands[command3] }))
|
|
4049
4458
|
};
|
|
4050
4459
|
const deleteCommands = {
|
|
4051
4460
|
name: "delete_commands",
|
|
@@ -4068,7 +4477,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4068
4477
|
["shot", "command", "to"]
|
|
4069
4478
|
),
|
|
4070
4479
|
annotations: { title: "Reorder a command", ...WRITE },
|
|
4071
|
-
handler: ({ shot, command:
|
|
4480
|
+
handler: ({ shot, command: command3, to }) => apply({ op: "move_command", shot, command: command3, to }, "Move command", (s) => ({ shot, command: to, from: command3, commands: describeMotionShots(s).find((x) => x.id === shot).commands.map((c) => ({ index: c.index, type: c.type, start: c.start, end: c.end })) }))
|
|
4072
4481
|
};
|
|
4073
4482
|
const setSettings = {
|
|
4074
4483
|
name: "set_animation_settings",
|
|
@@ -4154,7 +4563,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
|
|
|
4154
4563
|
}
|
|
4155
4564
|
};
|
|
4156
4565
|
const reads = [getAnimation, getShot, findElements, getMotionPath, getTimingGrid, checkAnimation, renderFrame, exportFlairMotion, exportFlairEffect, exportLottie, seekAnimation];
|
|
4157
|
-
const writes = [setArtworkSvg, setDrivers, setClip, copyAnimation, fitAnimation, importFlairEffect, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, moveCommand, setSettings, setControls, editAnimation, writeAnimation, undo, redo];
|
|
4566
|
+
const writes = [setArtworkSvg, importPptx, setDrivers, setClip, copyAnimation, fitAnimation, importFlairEffect, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, moveCommand, setSettings, setControls, editAnimation, writeAnimation, undo, redo];
|
|
4158
4567
|
return {
|
|
4159
4568
|
id: _nullishCoalesce(options.id, () => ( "animation")),
|
|
4160
4569
|
namespace: options.namespace,
|
|
@@ -4203,7 +4612,7 @@ Commands
|
|
|
4203
4612
|
- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).
|
|
4204
4613
|
|
|
4205
4614
|
Working method
|
|
4206
|
-
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
|
|
4615
|
+
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 / import_pptx_animation to start from a Flair effect or a PowerPoint slide).
|
|
4207
4616
|
2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).
|
|
4208
4617
|
- In edit_animation, a later op can use what an earlier one made: "$0.indexes[0]" (the first command op 1 added), "$last.shot".
|
|
4209
4618
|
3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result, or with "times" for a contact sheet of several moments; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.
|
|
@@ -4217,7 +4626,7 @@ var TIMING = /* @__PURE__ */ new Set(["duration", "delay", "stagger", "with", "e
|
|
|
4217
4626
|
var COLORS = /* @__PURE__ */ new Set(["fill", "stroke", "color"]);
|
|
4218
4627
|
var NODES = /* @__PURE__ */ new Set(["into", "path"]);
|
|
4219
4628
|
function branch(type) {
|
|
4220
|
-
return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access',
|
|
4629
|
+
return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _160 => _160.properties, 'optionalAccess', _161 => _161.type, 'optionalAccess', _162 => _162.const]) === type);
|
|
4221
4630
|
}
|
|
4222
4631
|
function unitOf(type, name) {
|
|
4223
4632
|
if (name === "duration" || name === "delay" || name === "stagger") return "ms";
|
|
@@ -4252,7 +4661,7 @@ function kindOf(name, schema) {
|
|
|
4252
4661
|
}
|
|
4253
4662
|
function motionCommandFields(type) {
|
|
4254
4663
|
const schema = branch(type);
|
|
4255
|
-
if (!_optionalChain([schema, 'optionalAccess',
|
|
4664
|
+
if (!_optionalChain([schema, 'optionalAccess', _163 => _163.properties])) return [];
|
|
4256
4665
|
const required = new Set(_nullishCoalesce(schema.required, () => ( [])));
|
|
4257
4666
|
const fields = Object.entries(schema.properties).filter(([name]) => name !== "type").map(([name, s]) => {
|
|
4258
4667
|
const kind = kindOf(name, s);
|
|
@@ -4299,17 +4708,17 @@ function parseMotionFieldInput(field, raw) {
|
|
|
4299
4708
|
if (field.kind === "enum" && field.options && !field.options.includes(text)) return { error: `${field.label} must be one of ${field.options.join(", ")}.` };
|
|
4300
4709
|
return { set: text };
|
|
4301
4710
|
}
|
|
4302
|
-
function motionFieldEdit(shot,
|
|
4711
|
+
function motionFieldEdit(shot, command3, field, raw) {
|
|
4303
4712
|
const input = parseMotionFieldInput(field, raw);
|
|
4304
4713
|
if ("error" in input) return input;
|
|
4305
|
-
if ("remove" in input) return { op: "update_command", shot, command:
|
|
4306
|
-
return { op: "update_command", shot, command:
|
|
4714
|
+
if ("remove" in input) return { op: "update_command", shot, command: command3, remove: [field.name] };
|
|
4715
|
+
return { op: "update_command", shot, command: command3, set: { [field.name]: input.set } };
|
|
4307
4716
|
}
|
|
4308
4717
|
function defaultMotionCommand(type, targets, scene) {
|
|
4309
4718
|
if (type === "wait") return { type: "wait", duration: 500 };
|
|
4310
4719
|
if (!targets.length) return { error: "Pick a target first: click an element on the stage." };
|
|
4311
4720
|
const nodes = [...indexMotionNodes(scene.artwork.nodes).values()];
|
|
4312
|
-
const other = (pred) => _optionalChain([nodes, 'access',
|
|
4721
|
+
const other = (pred) => _optionalChain([nodes, 'access', _164 => _164.find, 'call', _165 => _165((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _166 => _166.node, 'access', _167 => _167.id]);
|
|
4313
4722
|
const base = { targets: [...targets] };
|
|
4314
4723
|
switch (type) {
|
|
4315
4724
|
case "scale":
|
|
@@ -4340,8 +4749,8 @@ function defaultMotionCommand(type, targets, scene) {
|
|
|
4340
4749
|
}
|
|
4341
4750
|
case "effect": {
|
|
4342
4751
|
for (const id of targets) {
|
|
4343
|
-
const node = _optionalChain([nodes, 'access',
|
|
4344
|
-
for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess',
|
|
4752
|
+
const node = _optionalChain([nodes, 'access', _168 => _168.find, 'call', _169 => _169((e) => e.node.id === id), 'optionalAccess', _170 => _170.node]);
|
|
4753
|
+
for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _171 => _171.effects]), () => ( []))) {
|
|
4345
4754
|
const param = Object.entries(effect.params).find(([, v]) => typeof v === "number");
|
|
4346
4755
|
if (param) return { type, ...base, effect: effect.id, param: param[0], to: param[1] + 1 };
|
|
4347
4756
|
}
|
|
@@ -4352,26 +4761,26 @@ function defaultMotionCommand(type, targets, scene) {
|
|
|
4352
4761
|
return { type, ...base };
|
|
4353
4762
|
}
|
|
4354
4763
|
}
|
|
4355
|
-
function motionCommandSummary(
|
|
4356
|
-
const c =
|
|
4357
|
-
const what = [
|
|
4358
|
-
if (
|
|
4764
|
+
function motionCommandSummary(command3) {
|
|
4765
|
+
const c = command3;
|
|
4766
|
+
const what = [command3.type, typeof c.style === "string" ? c.style : ""].filter(Boolean).join(" ");
|
|
4767
|
+
if (command3.type === "wait") return `wait ${command3.duration} ms`;
|
|
4359
4768
|
const extra = typeof c.into === "string" ? ` \u2192 ${c.into}` : typeof c.path === "string" ? ` along ${c.path}` : "";
|
|
4360
|
-
return `${what} \xB7 ${(_nullishCoalesce(
|
|
4769
|
+
return `${what} \xB7 ${(_nullishCoalesce(command3.targets, () => ( []))).join(", ")}${extra}`;
|
|
4361
4770
|
}
|
|
4362
4771
|
function motionCommandRows(scene, shotId) {
|
|
4363
4772
|
const index = scene.shots.findIndex((s) => s.id === shotId);
|
|
4364
4773
|
if (index < 0) return [];
|
|
4365
4774
|
const timeline = compileMotionScene(scene);
|
|
4366
|
-
return scene.shots[index].run.map((
|
|
4775
|
+
return scene.shots[index].run.map((command3, i) => {
|
|
4367
4776
|
const t = timeline.commands.find((c) => c.shotIndex === index && c.command === i);
|
|
4368
|
-
const primitive = motionFlairPrimitive(
|
|
4369
|
-
return { index: i, command:
|
|
4777
|
+
const primitive = motionFlairPrimitive(command3);
|
|
4778
|
+
return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _172 => _172.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _173 => _173.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
|
|
4370
4779
|
});
|
|
4371
4780
|
}
|
|
4372
|
-
function duplicateMotionCommandEdit(scene, shot,
|
|
4373
|
-
const run = _nullishCoalesce(_optionalChain([scene, 'access',
|
|
4374
|
-
return { op: "add_commands", shot, commands: run[
|
|
4781
|
+
function duplicateMotionCommandEdit(scene, shot, command3) {
|
|
4782
|
+
const run = _nullishCoalesce(_optionalChain([scene, 'access', _174 => _174.shots, 'access', _175 => _175.find, 'call', _176 => _176((s) => s.id === shot), 'optionalAccess', _177 => _177.run]), () => ( []));
|
|
4783
|
+
return { op: "add_commands", shot, commands: run[command3] ? [structuredClone(run[command3])] : [], at: command3 + 1 };
|
|
4375
4784
|
}
|
|
4376
4785
|
var MOTION_EASE_CHOICES = [
|
|
4377
4786
|
{ value: "", label: "Default" },
|
|
@@ -4455,7 +4864,7 @@ function motionCueFromKey(key) {
|
|
|
4455
4864
|
function motionCueChoices(scene, limit = 256) {
|
|
4456
4865
|
const choices = [];
|
|
4457
4866
|
const s = (ms) => `${(ms / 1e3).toFixed(2)} s`;
|
|
4458
|
-
const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access',
|
|
4867
|
+
const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _178 => _178.narration, 'optionalAccess', _179 => _179.words, 'access', _180 => _180.map, 'call', _181 => _181((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
|
|
4459
4868
|
if (scene.beat && scene.beat.bpm > 0) {
|
|
4460
4869
|
for (let beat = 0; choices.length < limit; beat++) {
|
|
4461
4870
|
const time = motionBeatTime(scene.beat, beat);
|
|
@@ -4465,7 +4874,7 @@ function motionCueChoices(scene, limit = 256) {
|
|
|
4465
4874
|
choices.push({ value: `beat:${beat}`, label: `Beat ${beat} (bar ${at.bar}.${at.beatInBar}) \xB7 ${s(time)}`, time });
|
|
4466
4875
|
}
|
|
4467
4876
|
}
|
|
4468
|
-
_optionalChain([scene, 'access',
|
|
4877
|
+
_optionalChain([scene, 'access', _182 => _182.narration, 'optionalAccess', _183 => _183.words, 'access', _184 => _184.forEach, 'call', _185 => _185((w, i) => {
|
|
4469
4878
|
if (choices.length < limit * 2) choices.push({ value: `word:${i}`, label: `Word ${i} \u201C${w.text}\u201D \xB7 ${s(w.start)}`, time: w.start });
|
|
4470
4879
|
})]);
|
|
4471
4880
|
return choices;
|
|
@@ -4474,7 +4883,7 @@ function motionShotCueTime(scene, cue) {
|
|
|
4474
4883
|
return cue ? motionCueTime(scene, cue) : void 0;
|
|
4475
4884
|
}
|
|
4476
4885
|
function formatMotionNarration(narration) {
|
|
4477
|
-
return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess',
|
|
4886
|
+
return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _186 => _186.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
|
|
4478
4887
|
}
|
|
4479
4888
|
function parseMotionNarration(text) {
|
|
4480
4889
|
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
@@ -4646,5 +5055,6 @@ function parseMotionDrivers(text) {
|
|
|
4646
5055
|
|
|
4647
5056
|
|
|
4648
5057
|
|
|
4649
|
-
|
|
5058
|
+
|
|
5059
|
+
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_CLIP_TARGET = MOTION_CLIP_TARGET; 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_DRIVEN_PROPERTIES = MOTION_DRIVEN_PROPERTIES; exports.MOTION_EASE_CHOICES = MOTION_EASE_CHOICES; exports.MOTION_EASE_IN_OUT = MOTION_EASE_IN_OUT; exports.MOTION_EASE_OUT = MOTION_EASE_OUT; exports.MOTION_EDIT_OPS = MOTION_EDIT_OPS; exports.MOTION_ENTER_STYLES = MOTION_ENTER_STYLES; exports.MOTION_EXIT_STYLES = MOTION_EXIT_STYLES; exports.MOTION_IRIS_SHAPES = MOTION_IRIS_SHAPES; exports.MOTION_ISSUE_CODES = MOTION_ISSUE_CODES; exports.MOTION_MIN_CHANGE_MS = MOTION_MIN_CHANGE_MS; exports.MOTION_REPEAT_MODES = MOTION_REPEAT_MODES; exports.MOTION_SPEED_RANGE = MOTION_SPEED_RANGE; exports.MOTION_SPLIT_ORIENTATIONS = MOTION_SPLIT_ORIENTATIONS; exports.MOTION_TRIGGERS = MOTION_TRIGGERS; exports.MotionSceneFormatError = MotionSceneFormatError; exports.activeSegment = activeSegment; exports.applyMotionControlValues = applyMotionControlValues; exports.applyMotionDrivers = applyMotionDrivers; exports.applyMotionEdits = applyMotionEdits; exports.checkMotionScene = checkMotionScene; exports.clipsShapeProblems = clipsShapeProblems; exports.commandShapeProblems = commandShapeProblems; exports.compileMotionScene = compileMotionScene; exports.createAnimationEditorToolProvider = createAnimationEditorToolProvider; exports.createMotionScene = createMotionScene; exports.defaultMotionCommand = defaultMotionCommand; exports.describeMotionElements = describeMotionElements; exports.describeMotionShots = describeMotionShots; exports.driversShapeProblems = driversShapeProblems; exports.duplicateMotionCommandEdit = duplicateMotionCommandEdit; exports.fitMotionRect = fitMotionRect; exports.fitMotionScene = fitMotionScene; exports.fitMotionSceneEdits = fitMotionSceneEdits; exports.flairAtLeast = flairAtLeast; exports.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.formatMotionDrivers = formatMotionDrivers; exports.formatMotionNarration = formatMotionNarration; exports.freshShotId = freshShotId; exports.fromFlairSvgMotion = fromFlairSvgMotion; exports.fromFlairVectorEffect = fromFlairVectorEffect; exports.fromPptxAnimation = fromPptxAnimation; exports.highlightMotionSvg = highlightMotionSvg; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.matchMotionNodes = matchMotionNodes; exports.motionAddTrackKey = motionAddTrackKey; exports.motionBeatAt = motionBeatAt; exports.motionBeatTime = motionBeatTime; exports.motionBlurTimes = motionBlurTimes; exports.motionClipAttrs = motionClipAttrs; exports.motionClipLayout = motionClipLayout; exports.motionCommandDuration = motionCommandDuration; exports.motionCommandFields = motionCommandFields; exports.motionCommandRepeat = motionCommandRepeat; exports.motionCommandRows = motionCommandRows; exports.motionCommandSummary = motionCommandSummary; exports.motionContactSheetSvg = motionContactSheetSvg; exports.motionCueChoices = motionCueChoices; exports.motionCueFromKey = motionCueFromKey; exports.motionCueKey = motionCueKey; exports.motionCueTime = motionCueTime; exports.motionCycleDuration = motionCycleDuration; exports.motionDrivenNodes = motionDrivenNodes; exports.motionDriverSources = motionDriverSources; exports.motionEaseKey = motionEaseKey; exports.motionEasingCurve = motionEasingCurve; exports.motionEasingGuides = motionEasingGuides; exports.motionEasingPath = motionEasingPath; exports.motionFieldEdit = motionFieldEdit; exports.motionFieldLabel = motionFieldLabel; exports.motionFlairPrimitive = motionFlairPrimitive; exports.motionFollowRoute = motionFollowRoute; exports.motionFrameAt = motionFrameAt; exports.motionFrameToSvg = motionFrameToSvg; exports.motionGhosts = motionGhosts; exports.motionIssue = motionIssue; exports.motionIssueKey = motionIssueKey; exports.motionIssueLine = motionIssueLine; exports.motionMovingIds = motionMovingIds; exports.motionNodeAtElement = motionNodeAtElement; exports.motionNodeClips = motionNodeClips; exports.motionNodeOffset = motionNodeOffset; exports.motionPath = motionPath; exports.motionPathLength = motionPathLength; exports.motionPathsSvg = motionPathsSvg; exports.motionPropertyValue = motionPropertyValue; exports.motionRestValue = motionRestValue; exports.motionRevealClip = motionRevealClip; exports.motionRevealPadding = motionRevealPadding; exports.motionRulerTicks = motionRulerTicks; exports.motionSceneShapeProblems = motionSceneShapeProblems; exports.motionSceneToJson = motionSceneToJson; exports.motionShotAt = motionShotAt; exports.motionShotCueTime = motionShotCueTime; exports.motionShotTimeScale = motionShotTimeScale; exports.motionStageSvg = motionStageSvg; exports.motionTrackKey = motionTrackKey; exports.namedWithSuggestion = namedWithSuggestion; exports.parseMotionDrivers = parseMotionDrivers; exports.parseMotionFieldInput = parseMotionFieldInput; exports.parseMotionNarration = parseMotionNarration; exports.parseMotionScene = parseMotionScene; exports.resolveMotionCamera = resolveMotionCamera; exports.resolveMotionEditRefs = resolveMotionEditRefs; exports.segmentProgress = segmentProgress; exports.segmentValue = segmentValue; exports.shotShapeProblems = shotShapeProblems; exports.smoothMotionLegs = smoothMotionLegs; exports.smoothMotionTimes = smoothMotionTimes; exports.suggestName = suggestName; exports.toFlairEffectDocument = toFlairEffectDocument; exports.toFlairSvgMotion = toFlairSvgMotion; exports.toFlairVectorEffect = toFlairVectorEffect; exports.toLottie = toLottie; exports.trackValue = trackValue; exports.withMotionLayers = withMotionLayers; exports.withViewBox = withViewBox;
|
|
4650
5060
|
//# sourceMappingURL=index.cjs.map
|