reframe-video 0.1.0 → 0.1.2
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/assets/sfx/LICENSE.md +5 -0
- package/assets/sfx/bgm-song21.mp3 +0 -0
- package/assets/sfx/pop.wav +0 -0
- package/assets/sfx/rise.wav +0 -0
- package/assets/sfx/shimmer.wav +0 -0
- package/assets/sfx/thud.wav +0 -0
- package/assets/sfx/tick.wav +0 -0
- package/assets/sfx/whoosh.wav +0 -0
- package/dist/analyze.js +44 -1
- package/dist/bin.js +371 -35
- package/dist/browserEntry.js +311 -8
- package/dist/cli.js +305 -21
- package/dist/index.js +566 -16
- package/dist/renderer-canvas.js +58 -3
- package/dist/trace-cli.js +677 -0
- package/dist/types/assets.d.ts +9 -0
- package/dist/types/compile.d.ts +15 -1
- package/dist/types/compose.d.ts +12 -2
- package/dist/types/dsl.d.ts +30 -1
- package/dist/types/evaluate.d.ts +17 -0
- package/dist/types/index.d.ts +5 -1
- package/dist/types/ir.d.ts +82 -1
- package/dist/types/motion.d.ts +54 -0
- package/dist/types/path.d.ts +15 -0
- package/dist/types/presets.d.ts +41 -0
- package/guides/edsl-guide.md +24 -0
- package/package.json +1 -1
- package/preview/src/main.ts +111 -6
- package/preview/src/panel.ts +37 -3
- package/preview/src/store.ts +28 -2
- package/preview/src/virtual.d.ts +9 -1
- package/preview/vite.config.ts +3 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,89 @@
|
|
|
1
1
|
// ../core/src/ir.ts
|
|
2
2
|
var DEFAULT_TO_DURATION = 0.5;
|
|
3
3
|
var DEFAULT_TWEEN_DURATION = 0.5;
|
|
4
|
+
var DEFAULT_MOTIONPATH_DURATION = 1;
|
|
4
5
|
var DEFAULT_FPS = 30;
|
|
5
6
|
|
|
7
|
+
// ../core/src/path.ts
|
|
8
|
+
function locate(segCount, u) {
|
|
9
|
+
if (segCount <= 0) return { i: 0, t: 0 };
|
|
10
|
+
const clamped = Math.max(0, Math.min(1, u));
|
|
11
|
+
const scaled = clamped * segCount;
|
|
12
|
+
let i = Math.floor(scaled);
|
|
13
|
+
if (i >= segCount) i = segCount - 1;
|
|
14
|
+
return { i, t: scaled - i };
|
|
15
|
+
}
|
|
16
|
+
function controls(points, closed, i) {
|
|
17
|
+
const n = points.length;
|
|
18
|
+
const at = (k) => {
|
|
19
|
+
if (closed) return points[(k % n + n) % n];
|
|
20
|
+
return points[Math.max(0, Math.min(n - 1, k))];
|
|
21
|
+
};
|
|
22
|
+
return [at(i - 1), at(i), at(i + 1), at(i + 2)];
|
|
23
|
+
}
|
|
24
|
+
function segCountOf(points, closed) {
|
|
25
|
+
const n = points.length;
|
|
26
|
+
if (n < 2) return 0;
|
|
27
|
+
return closed ? n : n - 1;
|
|
28
|
+
}
|
|
29
|
+
function pathPoint(points, closed, u) {
|
|
30
|
+
const n = points.length;
|
|
31
|
+
if (n === 0) return [0, 0];
|
|
32
|
+
if (n === 1) return [points[0][0], points[0][1]];
|
|
33
|
+
const segs = segCountOf(points, closed);
|
|
34
|
+
const { i, t } = locate(segs, u);
|
|
35
|
+
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
36
|
+
const t2 = t * t;
|
|
37
|
+
const t3 = t2 * t;
|
|
38
|
+
const f = (a, b, c, d) => 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t2 + (-a + 3 * b - 3 * c + d) * t3);
|
|
39
|
+
return [f(p0[0], p1[0], p2[0], p3[0]), f(p0[1], p1[1], p2[1], p3[1])];
|
|
40
|
+
}
|
|
41
|
+
function pathTangentAngle(points, closed, u) {
|
|
42
|
+
const n = points.length;
|
|
43
|
+
if (n < 2) return 0;
|
|
44
|
+
const segs = segCountOf(points, closed);
|
|
45
|
+
const { i, t } = locate(segs, u);
|
|
46
|
+
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
47
|
+
const t2 = t * t;
|
|
48
|
+
const d = (a, b, c, e) => 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - e) * t + 3 * (-a + 3 * b - 3 * c + e) * t2);
|
|
49
|
+
const dx = d(p0[0], p1[0], p2[0], p3[0]);
|
|
50
|
+
const dy = d(p0[1], p1[1], p2[1], p3[1]);
|
|
51
|
+
if (dx === 0 && dy === 0) return 0;
|
|
52
|
+
return Math.atan2(dy, dx) * 180 / Math.PI;
|
|
53
|
+
}
|
|
54
|
+
|
|
6
55
|
// ../core/src/compile.ts
|
|
7
56
|
var key = (target, prop) => `${target}.${prop}`;
|
|
57
|
+
function scaleTimeline(tl, k) {
|
|
58
|
+
switch (tl.kind) {
|
|
59
|
+
case "seq":
|
|
60
|
+
case "par":
|
|
61
|
+
return { ...tl, children: tl.children.map((c) => scaleTimeline(c, k)) };
|
|
62
|
+
case "stagger":
|
|
63
|
+
return { ...tl, interval: tl.interval * k, children: tl.children.map((c) => scaleTimeline(c, k)) };
|
|
64
|
+
case "wait":
|
|
65
|
+
return { ...tl, duration: tl.duration * k };
|
|
66
|
+
case "tween":
|
|
67
|
+
return { ...tl, duration: (tl.duration ?? DEFAULT_TWEEN_DURATION) * k };
|
|
68
|
+
case "motionPath":
|
|
69
|
+
return { ...tl, duration: (tl.duration ?? DEFAULT_MOTIONPATH_DURATION) * k };
|
|
70
|
+
case "to":
|
|
71
|
+
return {
|
|
72
|
+
...tl,
|
|
73
|
+
duration: (tl.duration ?? DEFAULT_TO_DURATION) * k,
|
|
74
|
+
...tl.stagger !== void 0 && { stagger: tl.stagger * k }
|
|
75
|
+
};
|
|
76
|
+
case "beat":
|
|
77
|
+
return {
|
|
78
|
+
...tl,
|
|
79
|
+
children: tl.children.map((c) => scaleTimeline(c, k)),
|
|
80
|
+
...tl.gap !== void 0 && { gap: tl.gap * k }
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function orderBeats(children) {
|
|
85
|
+
return children.map((c, i) => ({ c, i, key: c.kind === "beat" && c.order !== void 0 ? c.order : i })).sort((a, b) => a.key - b.key || a.i - b.i).map((x) => x.c);
|
|
86
|
+
}
|
|
8
87
|
function compileScene(ir) {
|
|
9
88
|
const nodeById = /* @__PURE__ */ new Map();
|
|
10
89
|
const nodeOrder = [];
|
|
@@ -33,6 +112,7 @@ function compileScene(ir) {
|
|
|
33
112
|
}
|
|
34
113
|
}
|
|
35
114
|
const segments = /* @__PURE__ */ new Map();
|
|
115
|
+
const motionPaths = /* @__PURE__ */ new Map();
|
|
36
116
|
const current = new Map(initialValues);
|
|
37
117
|
const pushSegment = (seg) => {
|
|
38
118
|
const k = key(seg.target, seg.prop);
|
|
@@ -49,6 +129,50 @@ function compileScene(ir) {
|
|
|
49
129
|
throw new Error(`cannot animate "${prop}" of "${target}": no base value to start from`);
|
|
50
130
|
};
|
|
51
131
|
const labelTimes = /* @__PURE__ */ new Map();
|
|
132
|
+
const beatTimes = /* @__PURE__ */ new Map();
|
|
133
|
+
const durationOf = (tl, start) => {
|
|
134
|
+
switch (tl.kind) {
|
|
135
|
+
case "seq": {
|
|
136
|
+
let t = start;
|
|
137
|
+
for (const child of orderBeats(tl.children)) t = durationOf(child, t);
|
|
138
|
+
return t;
|
|
139
|
+
}
|
|
140
|
+
case "par": {
|
|
141
|
+
let end = start;
|
|
142
|
+
for (const child of tl.children) end = Math.max(end, durationOf(child, start));
|
|
143
|
+
return end;
|
|
144
|
+
}
|
|
145
|
+
case "stagger": {
|
|
146
|
+
let end = start;
|
|
147
|
+
tl.children.forEach((child, i) => {
|
|
148
|
+
end = Math.max(end, durationOf(child, start + i * tl.interval));
|
|
149
|
+
});
|
|
150
|
+
return end;
|
|
151
|
+
}
|
|
152
|
+
case "wait":
|
|
153
|
+
return start + tl.duration;
|
|
154
|
+
case "tween":
|
|
155
|
+
return start + (tl.duration ?? DEFAULT_TWEEN_DURATION);
|
|
156
|
+
case "motionPath":
|
|
157
|
+
return start + (tl.duration ?? DEFAULT_MOTIONPATH_DURATION);
|
|
158
|
+
case "to": {
|
|
159
|
+
const override = ir.states?.[tl.state] ?? {};
|
|
160
|
+
const duration = tl.duration ?? DEFAULT_TO_DURATION;
|
|
161
|
+
const si = tl.stagger ?? 0;
|
|
162
|
+
const targets = nodeOrder.filter(
|
|
163
|
+
(id) => id in override && (tl.filter === void 0 || tl.filter.includes(id))
|
|
164
|
+
);
|
|
165
|
+
return start + duration + Math.max(0, targets.length - 1) * si;
|
|
166
|
+
}
|
|
167
|
+
case "beat": {
|
|
168
|
+
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
169
|
+
const natural = durationOf(grouping, 0);
|
|
170
|
+
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, natural) : 1);
|
|
171
|
+
const beatStart = tl.at ?? start + (tl.gap ?? 0);
|
|
172
|
+
return beatStart + k * natural;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
52
176
|
const walk = (tl, start) => {
|
|
53
177
|
const end = walkInner(tl, start);
|
|
54
178
|
if ("label" in tl && tl.label !== void 0) labelTimes.set(tl.label, { t0: start, t1: end });
|
|
@@ -58,9 +182,19 @@ function compileScene(ir) {
|
|
|
58
182
|
switch (tl.kind) {
|
|
59
183
|
case "seq": {
|
|
60
184
|
let t = start;
|
|
61
|
-
for (const child of tl.children) t = walk(child, t);
|
|
185
|
+
for (const child of orderBeats(tl.children)) t = walk(child, t);
|
|
62
186
|
return t;
|
|
63
187
|
}
|
|
188
|
+
case "beat": {
|
|
189
|
+
const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
|
|
190
|
+
const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
|
|
191
|
+
const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
|
|
192
|
+
const beatStart = tl.at ?? start + (tl.gap ?? 0);
|
|
193
|
+
const end = walk(inner, beatStart);
|
|
194
|
+
beatTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
195
|
+
labelTimes.set(tl.name, { t0: beatStart, t1: end });
|
|
196
|
+
return end;
|
|
197
|
+
}
|
|
64
198
|
case "par": {
|
|
65
199
|
let end = start;
|
|
66
200
|
for (const child of tl.children) end = Math.max(end, walk(child, start));
|
|
@@ -90,6 +224,23 @@ function compileScene(ir) {
|
|
|
90
224
|
}
|
|
91
225
|
return start + duration;
|
|
92
226
|
}
|
|
227
|
+
case "motionPath": {
|
|
228
|
+
const duration = tl.duration ?? DEFAULT_MOTIONPATH_DURATION;
|
|
229
|
+
const points = tl.points;
|
|
230
|
+
const closed = tl.closed ?? false;
|
|
231
|
+
const autoRotate = tl.autoRotate ?? false;
|
|
232
|
+
const rotateOffset = tl.rotateOffset ?? 0;
|
|
233
|
+
let list = motionPaths.get(tl.target);
|
|
234
|
+
if (!list) motionPaths.set(tl.target, list = []);
|
|
235
|
+
list.push({ t0: start, t1: start + duration, points, closed, autoRotate, rotateOffset, ...tl.ease !== void 0 && { ease: tl.ease } });
|
|
236
|
+
if (points.length > 0) {
|
|
237
|
+
const [ex, ey] = pathPoint(points, closed, 1);
|
|
238
|
+
current.set(key(tl.target, "x"), ex);
|
|
239
|
+
current.set(key(tl.target, "y"), ey);
|
|
240
|
+
if (autoRotate) current.set(key(tl.target, "rotation"), pathTangentAngle(points, closed, 1) + rotateOffset);
|
|
241
|
+
}
|
|
242
|
+
return start + duration;
|
|
243
|
+
}
|
|
93
244
|
case "to": {
|
|
94
245
|
const override = ir.states?.[tl.state] ?? {};
|
|
95
246
|
const duration = tl.duration ?? DEFAULT_TO_DURATION;
|
|
@@ -118,14 +269,17 @@ function compileScene(ir) {
|
|
|
118
269
|
};
|
|
119
270
|
const inferredEnd = ir.timeline ? walk(ir.timeline, 0) : 0;
|
|
120
271
|
for (const list of segments.values()) list.sort((a, b) => a.t0 - b.t0);
|
|
272
|
+
for (const list of motionPaths.values()) list.sort((a, b) => a.t0 - b.t0);
|
|
121
273
|
return {
|
|
122
274
|
ir,
|
|
123
275
|
duration: ir.duration ?? inferredEnd,
|
|
124
276
|
segments,
|
|
277
|
+
motionPaths,
|
|
125
278
|
initialValues,
|
|
126
279
|
nodeById,
|
|
127
280
|
nodeOrder,
|
|
128
|
-
labelTimes
|
|
281
|
+
labelTimes,
|
|
282
|
+
beatTimes
|
|
129
283
|
};
|
|
130
284
|
}
|
|
131
285
|
|
|
@@ -136,6 +290,8 @@ var PROPS_BY_TYPE = {
|
|
|
136
290
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
|
137
291
|
line: ["x1", "y1", "x2", "y2", "stroke", "strokeWidth", "opacity", "progress"],
|
|
138
292
|
text: [...COMMON_PROPS, "content", "contentDecimals", "fontFamily", "fontSize", "fontWeight", "fill", "letterSpacing"],
|
|
293
|
+
image: [...COMMON_PROPS, "src", "width", "height"],
|
|
294
|
+
path: [...COMMON_PROPS, "d", "fill", "stroke", "strokeWidth", "progress", "originX", "originY"],
|
|
139
295
|
group: COMMON_PROPS
|
|
140
296
|
};
|
|
141
297
|
var SceneValidationError = class extends Error {
|
|
@@ -189,11 +345,11 @@ function validateScene(ir) {
|
|
|
189
345
|
);
|
|
190
346
|
}
|
|
191
347
|
const labels = /* @__PURE__ */ new Set();
|
|
192
|
-
const checkTimeline = (tl,
|
|
348
|
+
const checkTimeline = (tl, path2) => {
|
|
193
349
|
if ("label" in tl && tl.label !== void 0) {
|
|
194
350
|
if (labels.has(tl.label)) {
|
|
195
351
|
problems.push(
|
|
196
|
-
`${
|
|
352
|
+
`${path2}: duplicate timeline label "${tl.label}" \u2014 labels are overlay addresses and must be unique`
|
|
197
353
|
);
|
|
198
354
|
}
|
|
199
355
|
labels.add(tl.label);
|
|
@@ -201,33 +357,63 @@ function validateScene(ir) {
|
|
|
201
357
|
switch (tl.kind) {
|
|
202
358
|
case "seq":
|
|
203
359
|
case "par":
|
|
204
|
-
tl.children.forEach((c, i) => checkTimeline(c, `${
|
|
360
|
+
tl.children.forEach((c, i) => checkTimeline(c, `${path2}.${tl.kind}[${i}]`));
|
|
205
361
|
break;
|
|
206
362
|
case "stagger":
|
|
207
|
-
if (tl.interval < 0) problems.push(`${
|
|
208
|
-
tl.children.forEach((c, i) => checkTimeline(c, `${
|
|
363
|
+
if (tl.interval < 0) problems.push(`${path2}: stagger interval must be >= 0`);
|
|
364
|
+
tl.children.forEach((c, i) => checkTimeline(c, `${path2}.stagger[${i}]`));
|
|
209
365
|
break;
|
|
210
366
|
case "to":
|
|
211
367
|
if (!(tl.state in states)) {
|
|
212
368
|
problems.push(
|
|
213
|
-
`${
|
|
369
|
+
`${path2}: to("${tl.state}") references an undefined state \u2014 defined states: ${Object.keys(states).join(", ") || "(none)"}`
|
|
214
370
|
);
|
|
215
371
|
}
|
|
216
372
|
if (tl.duration !== void 0 && tl.duration <= 0) {
|
|
217
|
-
problems.push(`${
|
|
373
|
+
problems.push(`${path2}: to("${tl.state}") duration must be > 0`);
|
|
218
374
|
}
|
|
219
375
|
for (const id of tl.filter ?? []) {
|
|
220
|
-
if (!nodeById.has(id)) problems.push(`${
|
|
376
|
+
if (!nodeById.has(id)) problems.push(`${path2}: filter contains unknown node "${id}"`);
|
|
221
377
|
}
|
|
222
378
|
break;
|
|
223
379
|
case "tween":
|
|
224
|
-
checkProps(
|
|
380
|
+
checkProps(path2, tl.target, tl.props);
|
|
225
381
|
if (tl.duration !== void 0 && tl.duration <= 0) {
|
|
226
|
-
problems.push(`${
|
|
382
|
+
problems.push(`${path2}: tween duration must be > 0`);
|
|
227
383
|
}
|
|
228
384
|
break;
|
|
385
|
+
case "motionPath": {
|
|
386
|
+
const node = nodeById.get(tl.target);
|
|
387
|
+
if (!node) {
|
|
388
|
+
problems.push(
|
|
389
|
+
`${path2}: motionPath targets unknown node "${tl.target}" \u2014 known ids: ${[...nodeById.keys()].join(", ")}`
|
|
390
|
+
);
|
|
391
|
+
} else if (node.type === "line") {
|
|
392
|
+
problems.push(`${path2}: motionPath cannot target a line (no x/y) \u2014 "${tl.target}"`);
|
|
393
|
+
}
|
|
394
|
+
if (tl.points.length < 1) problems.push(`${path2}: motionPath "${tl.target}" needs at least 1 point`);
|
|
395
|
+
if (tl.duration !== void 0 && tl.duration <= 0) {
|
|
396
|
+
problems.push(`${path2}: motionPath "${tl.target}" duration must be > 0`);
|
|
397
|
+
}
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
229
400
|
case "wait":
|
|
230
|
-
if (tl.duration < 0) problems.push(`${
|
|
401
|
+
if (tl.duration < 0) problems.push(`${path2}: wait duration must be >= 0`);
|
|
402
|
+
break;
|
|
403
|
+
case "beat":
|
|
404
|
+
if (labels.has(tl.name)) {
|
|
405
|
+
problems.push(
|
|
406
|
+
`${path2}: duplicate timeline label "${tl.name}" (beat name) \u2014 labels are overlay addresses and must be unique`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
labels.add(tl.name);
|
|
410
|
+
if (tl.duration !== void 0 && tl.duration <= 0) {
|
|
411
|
+
problems.push(`${path2}: beat "${tl.name}" duration must be > 0`);
|
|
412
|
+
}
|
|
413
|
+
if (tl.scale !== void 0 && tl.scale <= 0) {
|
|
414
|
+
problems.push(`${path2}: beat "${tl.name}" scale must be > 0`);
|
|
415
|
+
}
|
|
416
|
+
tl.children.forEach((c, i) => checkTimeline(c, `${path2}.beat(${tl.name})[${i}]`));
|
|
231
417
|
break;
|
|
232
418
|
}
|
|
233
419
|
};
|
|
@@ -293,6 +479,14 @@ function text(props) {
|
|
|
293
479
|
const { id, ...rest } = props;
|
|
294
480
|
return { type: "text", id, props: rest };
|
|
295
481
|
}
|
|
482
|
+
function image(props) {
|
|
483
|
+
const { id, ...rest } = props;
|
|
484
|
+
return { type: "image", id, props: rest };
|
|
485
|
+
}
|
|
486
|
+
function path(props) {
|
|
487
|
+
const { id, ...rest } = props;
|
|
488
|
+
return { type: "path", id, props: rest };
|
|
489
|
+
}
|
|
296
490
|
function group(props, children) {
|
|
297
491
|
const { id, ...rest } = props;
|
|
298
492
|
return { type: "group", id, props: rest, children };
|
|
@@ -306,6 +500,9 @@ function par(...children) {
|
|
|
306
500
|
function stagger(interval, ...children) {
|
|
307
501
|
return { kind: "stagger", interval, children };
|
|
308
502
|
}
|
|
503
|
+
function beat(name, opts, children) {
|
|
504
|
+
return { kind: "beat", name, children, ...opts };
|
|
505
|
+
}
|
|
309
506
|
function to(state, opts = {}) {
|
|
310
507
|
return { kind: "to", state, ...opts };
|
|
311
508
|
}
|
|
@@ -315,6 +512,9 @@ function tween(target, props, opts = {}) {
|
|
|
315
512
|
function wait(duration, label) {
|
|
316
513
|
return { kind: "wait", duration, ...label !== void 0 && { label } };
|
|
317
514
|
}
|
|
515
|
+
function motionPath(target, points, opts = {}) {
|
|
516
|
+
return { kind: "motionPath", target, points, ...opts };
|
|
517
|
+
}
|
|
318
518
|
function oscillate(target, prop, params, window = {}) {
|
|
319
519
|
return { target, prop, ...window, behavior: { kind: "named", name: "oscillate", params } };
|
|
320
520
|
}
|
|
@@ -446,13 +646,16 @@ function applyOverlay(ir, overlay, layer, report) {
|
|
|
446
646
|
const byLabel = /* @__PURE__ */ new Map();
|
|
447
647
|
const walkTimeline = (tl) => {
|
|
448
648
|
if ("label" in tl && tl.label !== void 0) byLabel.set(tl.label, tl);
|
|
649
|
+
if (tl.kind === "beat") byLabel.set(tl.name, tl);
|
|
449
650
|
if ("children" in tl) tl.children.forEach(walkTimeline);
|
|
450
651
|
};
|
|
451
652
|
if (ir.timeline) walkTimeline(ir.timeline);
|
|
452
653
|
const PATCHABLE = {
|
|
453
654
|
to: ["duration", "ease", "stagger"],
|
|
454
655
|
tween: ["duration", "ease"],
|
|
455
|
-
wait: ["duration"]
|
|
656
|
+
wait: ["duration"],
|
|
657
|
+
motionPath: ["points", "duration", "ease"],
|
|
658
|
+
beat: ["at", "gap", "scale", "duration", "order"]
|
|
456
659
|
};
|
|
457
660
|
let timingPatched = false;
|
|
458
661
|
for (const [label, patch] of Object.entries(overlay.timeline)) {
|
|
@@ -476,7 +679,7 @@ function applyOverlay(ir, overlay, layer, report) {
|
|
|
476
679
|
}
|
|
477
680
|
step[key2] = value;
|
|
478
681
|
applied(`timeline.${label}.${key2}`, "set");
|
|
479
|
-
if (
|
|
682
|
+
if (["duration", "stagger", "at", "gap", "scale", "order"].includes(key2)) timingPatched = true;
|
|
480
683
|
}
|
|
481
684
|
}
|
|
482
685
|
if (timingPatched && overlay.scene?.duration === void 0) {
|
|
@@ -501,6 +704,186 @@ function formatComposeReport(report) {
|
|
|
501
704
|
return lines.join("\n");
|
|
502
705
|
}
|
|
503
706
|
|
|
707
|
+
// ../core/src/presets.ts
|
|
708
|
+
var PRESET_NAMES = [
|
|
709
|
+
"draw-bloom",
|
|
710
|
+
"punch-in",
|
|
711
|
+
"rise-settle",
|
|
712
|
+
"slide-bank",
|
|
713
|
+
"reveal-orbit",
|
|
714
|
+
"spin-forge"
|
|
715
|
+
];
|
|
716
|
+
function makeRng(seed) {
|
|
717
|
+
let a = seed >>> 0 || 2654435769;
|
|
718
|
+
return () => {
|
|
719
|
+
a = a + 1831565813 | 0;
|
|
720
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
721
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
722
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
var clamp01 = (x) => Math.max(0, Math.min(1, x));
|
|
726
|
+
var SET = 1 / 120;
|
|
727
|
+
function ctx(o) {
|
|
728
|
+
const rand = makeRng((o.seed ?? 0) + 1);
|
|
729
|
+
return {
|
|
730
|
+
e: clamp01(o.energy ?? 0.5),
|
|
731
|
+
sp: Math.max(0.25, o.speed ?? 1),
|
|
732
|
+
it: clamp01(o.intensity ?? 0.5),
|
|
733
|
+
from: o.from,
|
|
734
|
+
rand,
|
|
735
|
+
jit: (amp) => (rand() - 0.5) * 2 * amp,
|
|
736
|
+
g: o.target.group,
|
|
737
|
+
cx: o.target.center[0],
|
|
738
|
+
cy: o.target.center[1],
|
|
739
|
+
s: o.target.baseScale,
|
|
740
|
+
fills: o.target.fills,
|
|
741
|
+
inks: o.target.inks
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
var dur = (base, sp) => base / sp;
|
|
745
|
+
function settleEase(e) {
|
|
746
|
+
return e < 0.34 ? "easeOutCubic" : e < 0.67 ? "easeOutBack" : "easeOutElastic";
|
|
747
|
+
}
|
|
748
|
+
function fromVec(from, dist) {
|
|
749
|
+
switch (from) {
|
|
750
|
+
case "left":
|
|
751
|
+
return [-dist, 0];
|
|
752
|
+
case "right":
|
|
753
|
+
return [dist, 0];
|
|
754
|
+
case "top":
|
|
755
|
+
return [0, -dist];
|
|
756
|
+
default:
|
|
757
|
+
return [0, dist];
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
function fadeFills(c, base = 0.4, gap = 0.06) {
|
|
761
|
+
return stagger(
|
|
762
|
+
gap / c.sp,
|
|
763
|
+
...c.fills.map(
|
|
764
|
+
(id, i) => tween(id, { opacity: 1 }, { duration: dur(base, c.sp), ease: "easeOutQuad", ...i === 0 && { label: "reveal" } })
|
|
765
|
+
)
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
function drawInks(c) {
|
|
769
|
+
return stagger(
|
|
770
|
+
0.15 / c.sp,
|
|
771
|
+
...c.inks.map(
|
|
772
|
+
(id, i) => tween(id, { progress: 1 }, { duration: dur(1.3 + c.jit(0.2), c.sp), ease: "easeInOutQuad", ...i === 0 && { label: "draw" } })
|
|
773
|
+
)
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
function motionPreset(name, opts) {
|
|
777
|
+
const c = ctx(opts);
|
|
778
|
+
switch (name) {
|
|
779
|
+
case "draw-bloom":
|
|
780
|
+
return beat("draw-bloom", {}, [
|
|
781
|
+
drawInks(c),
|
|
782
|
+
fadeFills(c, 0.45),
|
|
783
|
+
tween(c.g, { scale: c.s * (1.02 + 0.05 * c.e) }, { duration: dur(2.4, c.sp), ease: "easeInOutQuad", label: "settle" })
|
|
784
|
+
]);
|
|
785
|
+
case "punch-in": {
|
|
786
|
+
const peak = c.s * (1 + 0.06 + 0.24 * c.e + c.jit(0.02));
|
|
787
|
+
return beat("punch-in", {}, [
|
|
788
|
+
par(
|
|
789
|
+
fadeFills(c, 0.25),
|
|
790
|
+
seq(
|
|
791
|
+
tween(c.g, { scale: peak }, { duration: dur(0.45 + c.jit(0.05), c.sp), ease: "easeOutCubic", label: "punch" }),
|
|
792
|
+
tween(c.g, { scale: c.s }, { duration: dur(0.5, c.sp), ease: settleEase(c.e) })
|
|
793
|
+
)
|
|
794
|
+
)
|
|
795
|
+
]);
|
|
796
|
+
}
|
|
797
|
+
case "rise-settle": {
|
|
798
|
+
const es = 0.65 + c.rand() * 0.7;
|
|
799
|
+
const dist = (220 + 260 * c.it) * es;
|
|
800
|
+
const [dx, dy] = fromVec(c.from ?? "bottom", dist);
|
|
801
|
+
const jx = c.jit(110);
|
|
802
|
+
return beat("rise-settle", {}, [
|
|
803
|
+
par(
|
|
804
|
+
motionPath(
|
|
805
|
+
c.g,
|
|
806
|
+
[
|
|
807
|
+
[c.cx + dx + jx, c.cy + dy],
|
|
808
|
+
[c.cx + dx * 0.4 - jx * 0.6, c.cy + dy * 0.4],
|
|
809
|
+
[c.cx, c.cy]
|
|
810
|
+
],
|
|
811
|
+
{ duration: dur(1.1, c.sp), ease: settleEase(c.e), label: "rise" }
|
|
812
|
+
),
|
|
813
|
+
fadeFills(c, 0.4)
|
|
814
|
+
)
|
|
815
|
+
]);
|
|
816
|
+
}
|
|
817
|
+
case "slide-bank": {
|
|
818
|
+
const es = 0.65 + c.rand() * 0.7;
|
|
819
|
+
const dist = (420 + 240 * c.it) * es;
|
|
820
|
+
const [dx, dy] = fromVec(c.from ?? "left", dist);
|
|
821
|
+
const arc = c.jit(140);
|
|
822
|
+
const midx = c.jit(120);
|
|
823
|
+
const move = dur(1.2, c.sp);
|
|
824
|
+
return beat("slide-bank", {}, [
|
|
825
|
+
par(
|
|
826
|
+
motionPath(
|
|
827
|
+
c.g,
|
|
828
|
+
[
|
|
829
|
+
[c.cx + dx, c.cy + dy],
|
|
830
|
+
[c.cx + dx * 0.4 + midx, c.cy + dy * 0.4 - 70 - arc],
|
|
831
|
+
[c.cx, c.cy]
|
|
832
|
+
],
|
|
833
|
+
{ duration: move, ease: settleEase(c.e), autoRotate: true, label: "slide" }
|
|
834
|
+
),
|
|
835
|
+
// level the bank out once it lands (authored after the path → wins for rotation)
|
|
836
|
+
seq(wait(move), tween(c.g, { rotation: 0 }, { duration: dur(0.5, c.sp), ease: "easeOutCubic" })),
|
|
837
|
+
fadeFills(c, 0.4)
|
|
838
|
+
)
|
|
839
|
+
]);
|
|
840
|
+
}
|
|
841
|
+
case "reveal-orbit": {
|
|
842
|
+
const es = 0.65 + c.rand() * 0.7;
|
|
843
|
+
const orbit = (180 + 160 * c.it) * es;
|
|
844
|
+
const jx = c.jit(0.4);
|
|
845
|
+
const jy = c.jit(0.4);
|
|
846
|
+
return beat("reveal-orbit", {}, [
|
|
847
|
+
drawInks(c),
|
|
848
|
+
fadeFills(c, 0.45),
|
|
849
|
+
par(
|
|
850
|
+
motionPath(
|
|
851
|
+
c.g,
|
|
852
|
+
[
|
|
853
|
+
[c.cx, c.cy],
|
|
854
|
+
[c.cx - orbit * (1 + jx), c.cy - orbit * 0.8],
|
|
855
|
+
[c.cx + orbit * (1 + jy), c.cy - orbit],
|
|
856
|
+
[c.cx, c.cy]
|
|
857
|
+
],
|
|
858
|
+
{ duration: dur(1.7, c.sp), ease: "easeInOutCubic", label: "orbit" }
|
|
859
|
+
),
|
|
860
|
+
seq(
|
|
861
|
+
tween(c.g, { scale: c.s * (1.12 + 0.1 * c.e) }, { duration: dur(0.85, c.sp), ease: "easeOutBack" }),
|
|
862
|
+
tween(c.g, { scale: c.s }, { duration: dur(0.85, c.sp), ease: "easeInOutQuad" })
|
|
863
|
+
)
|
|
864
|
+
)
|
|
865
|
+
]);
|
|
866
|
+
}
|
|
867
|
+
case "spin-forge": {
|
|
868
|
+
const turns = 1 + Math.round(c.it);
|
|
869
|
+
const dir = c.rand() < 0.5 ? -1 : 1;
|
|
870
|
+
const startRot = dir * 360 * turns;
|
|
871
|
+
const peak = c.s * (1 + 0.05 + 0.2 * c.e);
|
|
872
|
+
return beat("spin-forge", {}, [
|
|
873
|
+
par(
|
|
874
|
+
seq(
|
|
875
|
+
tween(c.g, { scale: c.s * 0.2, rotation: startRot }, { duration: SET }),
|
|
876
|
+
// establish (invisible)
|
|
877
|
+
tween(c.g, { scale: peak, rotation: 0 }, { duration: dur(0.9, c.sp), ease: "easeOutBack", label: "spin" }),
|
|
878
|
+
tween(c.g, { scale: c.s }, { duration: dur(0.3, c.sp), ease: "easeInOutQuad" })
|
|
879
|
+
),
|
|
880
|
+
seq(wait(SET), fadeFills(c, 0.3))
|
|
881
|
+
)
|
|
882
|
+
]);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
504
887
|
// ../core/src/audio.ts
|
|
505
888
|
var SFX_DURATION = {
|
|
506
889
|
whoosh: 0.35,
|
|
@@ -602,6 +985,19 @@ function hash01(n, seed) {
|
|
|
602
985
|
}
|
|
603
986
|
|
|
604
987
|
// ../core/src/interpolate.ts
|
|
988
|
+
var BACK_C1 = 1.70158;
|
|
989
|
+
var BACK_C2 = BACK_C1 * 1.525;
|
|
990
|
+
var BACK_C3 = BACK_C1 + 1;
|
|
991
|
+
var ELASTIC_C4 = 2 * Math.PI / 3;
|
|
992
|
+
var ELASTIC_C5 = 2 * Math.PI / 4.5;
|
|
993
|
+
function easeOutBounce(u) {
|
|
994
|
+
const n1 = 7.5625;
|
|
995
|
+
const d1 = 2.75;
|
|
996
|
+
if (u < 1 / d1) return n1 * u * u;
|
|
997
|
+
if (u < 2 / d1) return n1 * (u -= 1.5 / d1) * u + 0.75;
|
|
998
|
+
if (u < 2.5 / d1) return n1 * (u -= 2.25 / d1) * u + 0.9375;
|
|
999
|
+
return n1 * (u -= 2.625 / d1) * u + 0.984375;
|
|
1000
|
+
}
|
|
605
1001
|
var EASE_TABLE = {
|
|
606
1002
|
linear: (u) => u,
|
|
607
1003
|
easeInQuad: (u) => u * u,
|
|
@@ -615,7 +1011,20 @@ var EASE_TABLE = {
|
|
|
615
1011
|
easeInOutQuart: (u) => u < 0.5 ? 8 * u ** 4 : 1 - (-2 * u + 2) ** 4 / 2,
|
|
616
1012
|
easeInExpo: (u) => u === 0 ? 0 : 2 ** (10 * u - 10),
|
|
617
1013
|
easeOutExpo: (u) => u === 1 ? 1 : 1 - 2 ** (-10 * u),
|
|
618
|
-
easeInOutExpo: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? 2 ** (20 * u - 10) / 2 : (2 - 2 ** (-20 * u + 10)) / 2
|
|
1014
|
+
easeInOutExpo: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? 2 ** (20 * u - 10) / 2 : (2 - 2 ** (-20 * u + 10)) / 2,
|
|
1015
|
+
// --- expressive eases (GSAP's signature feel) — standard Penner equations ---
|
|
1016
|
+
// back: overshoots past the target then settles (pop / snap)
|
|
1017
|
+
easeInBack: (u) => BACK_C3 * u ** 3 - BACK_C1 * u * u,
|
|
1018
|
+
easeOutBack: (u) => 1 + BACK_C3 * (u - 1) ** 3 + BACK_C1 * (u - 1) ** 2,
|
|
1019
|
+
easeInOutBack: (u) => u < 0.5 ? (2 * u) ** 2 * ((BACK_C2 + 1) * 2 * u - BACK_C2) / 2 : ((2 * u - 2) ** 2 * ((BACK_C2 + 1) * (2 * u - 2) + BACK_C2) + 2) / 2,
|
|
1020
|
+
// elastic: rings around the target before settling (playful spring)
|
|
1021
|
+
easeInElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : -(2 ** (10 * u - 10)) * Math.sin((u * 10 - 10.75) * ELASTIC_C4),
|
|
1022
|
+
easeOutElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : 2 ** (-10 * u) * Math.sin((u * 10 - 0.75) * ELASTIC_C4) + 1,
|
|
1023
|
+
easeInOutElastic: (u) => u === 0 ? 0 : u === 1 ? 1 : u < 0.5 ? -(2 ** (20 * u - 10) * Math.sin((20 * u - 11.125) * ELASTIC_C5)) / 2 : 2 ** (-20 * u + 10) * Math.sin((20 * u - 11.125) * ELASTIC_C5) / 2 + 1,
|
|
1024
|
+
// bounce: drops and bounces to rest (lands without overshoot)
|
|
1025
|
+
easeInBounce: (u) => 1 - easeOutBounce(1 - u),
|
|
1026
|
+
easeOutBounce,
|
|
1027
|
+
easeInOutBounce: (u) => u < 0.5 ? (1 - easeOutBounce(1 - 2 * u)) / 2 : (1 + easeOutBounce(2 * u - 1)) / 2
|
|
619
1028
|
};
|
|
620
1029
|
var EASE_NAMES = Object.keys(EASE_TABLE);
|
|
621
1030
|
function resolveEase(ease) {
|
|
@@ -730,6 +1139,7 @@ function evaluate(compiled, t) {
|
|
|
730
1139
|
const ops = [];
|
|
731
1140
|
const valueAt = (target, prop, fallback) => {
|
|
732
1141
|
let value = compiled.initialValues.get(`${target}.${prop}`) ?? fallback;
|
|
1142
|
+
let segStart = Number.NEGATIVE_INFINITY;
|
|
733
1143
|
const segs = compiled.segments.get(`${target}.${prop}`);
|
|
734
1144
|
if (segs) {
|
|
735
1145
|
let active;
|
|
@@ -738,6 +1148,7 @@ function evaluate(compiled, t) {
|
|
|
738
1148
|
else break;
|
|
739
1149
|
}
|
|
740
1150
|
if (active) {
|
|
1151
|
+
segStart = active.t0;
|
|
741
1152
|
if (t >= active.t1) {
|
|
742
1153
|
value = active.to;
|
|
743
1154
|
} else {
|
|
@@ -746,6 +1157,23 @@ function evaluate(compiled, t) {
|
|
|
746
1157
|
}
|
|
747
1158
|
}
|
|
748
1159
|
}
|
|
1160
|
+
if (prop === "x" || prop === "y" || prop === "rotation") {
|
|
1161
|
+
const drivers = compiled.motionPaths.get(target);
|
|
1162
|
+
if (drivers) {
|
|
1163
|
+
let active;
|
|
1164
|
+
for (const d of drivers) {
|
|
1165
|
+
if (d.t0 <= t) active = d;
|
|
1166
|
+
else break;
|
|
1167
|
+
}
|
|
1168
|
+
if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
|
|
1169
|
+
const span = active.t1 - active.t0;
|
|
1170
|
+
const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
|
|
1171
|
+
if (prop === "x") value = pathPoint(active.points, active.closed, u)[0];
|
|
1172
|
+
else if (prop === "y") value = pathPoint(active.points, active.closed, u)[1];
|
|
1173
|
+
else value = pathTangentAngle(active.points, active.closed, u) + active.rotateOffset;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
749
1177
|
for (const b of compiled.ir.behaviors ?? []) {
|
|
750
1178
|
if (b.target === target && b.prop === prop && typeof value === "number") {
|
|
751
1179
|
const envelope = behaviorEnvelope(b, t);
|
|
@@ -826,6 +1254,40 @@ function evaluate(compiled, t) {
|
|
|
826
1254
|
});
|
|
827
1255
|
return;
|
|
828
1256
|
}
|
|
1257
|
+
case "image": {
|
|
1258
|
+
const width = num(id, "width", node.props.width);
|
|
1259
|
+
const height = num(id, "height", node.props.height);
|
|
1260
|
+
const [ax, ay] = ANCHOR_FACTORS[node.props.anchor ?? "top-left"];
|
|
1261
|
+
ops.push({
|
|
1262
|
+
type: "image",
|
|
1263
|
+
id,
|
|
1264
|
+
transform: matrix,
|
|
1265
|
+
opacity,
|
|
1266
|
+
src: str(id, "src", node.props.src),
|
|
1267
|
+
width,
|
|
1268
|
+
height,
|
|
1269
|
+
offsetX: -width * ax,
|
|
1270
|
+
offsetY: -height * ay
|
|
1271
|
+
});
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
case "path": {
|
|
1275
|
+
const ox = num(id, "originX", node.props.originX ?? 0);
|
|
1276
|
+
const oy = num(id, "originY", node.props.originY ?? 0);
|
|
1277
|
+
const fill = opt(id, "fill", node.props.fill);
|
|
1278
|
+
const stroke = opt(id, "stroke", node.props.stroke);
|
|
1279
|
+
ops.push({
|
|
1280
|
+
type: "path",
|
|
1281
|
+
id,
|
|
1282
|
+
transform: ox === 0 && oy === 0 ? matrix : multiply(matrix, [1, 0, 0, 1, -ox, -oy]),
|
|
1283
|
+
opacity,
|
|
1284
|
+
d: str(id, "d", node.props.d),
|
|
1285
|
+
progress: Math.max(0, Math.min(1, num(id, "progress", node.props.progress ?? 1))),
|
|
1286
|
+
...fill !== void 0 && { fill },
|
|
1287
|
+
...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) }
|
|
1288
|
+
});
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
829
1291
|
case "text": {
|
|
830
1292
|
const [ax, ay] = ANCHOR_FACTORS[node.props.anchor ?? "top-left"];
|
|
831
1293
|
const raw = valueAt(id, "content", node.props.content);
|
|
@@ -854,31 +1316,119 @@ function evaluate(compiled, t) {
|
|
|
854
1316
|
for (const node of compiled.ir.nodes) walk(node, IDENTITY, 1);
|
|
855
1317
|
return ops;
|
|
856
1318
|
}
|
|
1319
|
+
|
|
1320
|
+
// ../core/src/assets.ts
|
|
1321
|
+
function collectImageSrcs(ir) {
|
|
1322
|
+
const srcs = /* @__PURE__ */ new Set();
|
|
1323
|
+
const imageIds = /* @__PURE__ */ new Set();
|
|
1324
|
+
const walkNodes = (nodes) => {
|
|
1325
|
+
for (const node of nodes) {
|
|
1326
|
+
if (node.type === "image") {
|
|
1327
|
+
imageIds.add(node.id);
|
|
1328
|
+
srcs.add(node.props.src);
|
|
1329
|
+
}
|
|
1330
|
+
if (node.type === "group") walkNodes(node.children);
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
walkNodes(ir.nodes);
|
|
1334
|
+
for (const overrides of Object.values(ir.states ?? {})) {
|
|
1335
|
+
for (const [nodeId, props] of Object.entries(overrides)) {
|
|
1336
|
+
if (imageIds.has(nodeId) && typeof props.src === "string") srcs.add(props.src);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
const walkTimeline = (step) => {
|
|
1340
|
+
if (!step) return;
|
|
1341
|
+
if (step.kind === "seq" || step.kind === "par" || step.kind === "stagger") {
|
|
1342
|
+
for (const child of step.children) walkTimeline(child);
|
|
1343
|
+
} else if (step.kind === "tween" && imageIds.has(step.target)) {
|
|
1344
|
+
const src = step.props.src;
|
|
1345
|
+
if (typeof src === "string") srcs.add(src);
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1348
|
+
walkTimeline(ir.timeline);
|
|
1349
|
+
return [...srcs];
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// ../core/src/motion.ts
|
|
1353
|
+
var EASE_BY_CLASS = {
|
|
1354
|
+
accelerating: "easeInCubic",
|
|
1355
|
+
decelerating: "easeOutCubic",
|
|
1356
|
+
linear: "linear"
|
|
1357
|
+
};
|
|
1358
|
+
function easeFor(easing) {
|
|
1359
|
+
return EASE_BY_CLASS[easing.class] ?? "easeOutCubic";
|
|
1360
|
+
}
|
|
1361
|
+
function sketchToTimeline(sketch, nodeIds) {
|
|
1362
|
+
if (nodeIds.length === 0) return seq();
|
|
1363
|
+
const events = [...sketch.events].sort((a, b) => a.t0 - b.t0);
|
|
1364
|
+
const steps = [];
|
|
1365
|
+
events.forEach((ev, i) => {
|
|
1366
|
+
const node = nodeIds[i % nodeIds.length];
|
|
1367
|
+
const dur2 = Math.max(0.05, ev.t1 - ev.t0);
|
|
1368
|
+
const ease = easeFor(ev.easing);
|
|
1369
|
+
let motion;
|
|
1370
|
+
switch (ev.kind) {
|
|
1371
|
+
case "enter":
|
|
1372
|
+
motion = tween(node, { opacity: 1 }, { duration: dur2, ease });
|
|
1373
|
+
break;
|
|
1374
|
+
case "exit":
|
|
1375
|
+
motion = tween(node, { opacity: 0 }, { duration: dur2, ease });
|
|
1376
|
+
break;
|
|
1377
|
+
case "emphasis": {
|
|
1378
|
+
const peak = 1 + Math.max(0.08, Math.min(0.5, ev.magnitude));
|
|
1379
|
+
motion = seq(
|
|
1380
|
+
tween(node, { scale: peak }, { duration: dur2 / 2, ease: "easeOutCubic" }),
|
|
1381
|
+
tween(node, { scale: 1 }, { duration: dur2 / 2, ease: "easeInOutQuad" })
|
|
1382
|
+
);
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
case "scale":
|
|
1386
|
+
motion = tween(node, { scale: 1 + Math.max(-0.5, Math.min(0.5, ev.magnitude)) }, { duration: dur2, ease });
|
|
1387
|
+
break;
|
|
1388
|
+
case "move":
|
|
1389
|
+
motion = tween(node, { opacity: 1 }, { duration: dur2, ease });
|
|
1390
|
+
break;
|
|
1391
|
+
}
|
|
1392
|
+
steps.push(ev.t0 > 0 ? seq(wait(ev.t0), motion) : motion);
|
|
1393
|
+
});
|
|
1394
|
+
return par(...steps);
|
|
1395
|
+
}
|
|
857
1396
|
export {
|
|
858
1397
|
DEFAULT_FPS,
|
|
1398
|
+
DEFAULT_MOTIONPATH_DURATION,
|
|
859
1399
|
DEFAULT_TO_DURATION,
|
|
860
1400
|
DEFAULT_TWEEN_DURATION,
|
|
861
1401
|
EASE_NAMES,
|
|
1402
|
+
PRESET_NAMES,
|
|
862
1403
|
PROPS_BY_TYPE,
|
|
863
1404
|
SFX_DURATION,
|
|
864
1405
|
SceneValidationError,
|
|
1406
|
+
beat,
|
|
1407
|
+
collectImageSrcs,
|
|
865
1408
|
compileScene,
|
|
866
1409
|
composeScene,
|
|
867
1410
|
ellipse,
|
|
868
1411
|
evaluate,
|
|
869
1412
|
formatComposeReport,
|
|
870
1413
|
group,
|
|
1414
|
+
image,
|
|
871
1415
|
isColor,
|
|
872
1416
|
lerpValue,
|
|
873
1417
|
line,
|
|
1418
|
+
motionPath,
|
|
1419
|
+
motionPreset,
|
|
874
1420
|
oscillate,
|
|
875
1421
|
par,
|
|
1422
|
+
path,
|
|
1423
|
+
pathPoint,
|
|
1424
|
+
pathTangentAngle,
|
|
876
1425
|
rect,
|
|
877
1426
|
resolveAudioPlan,
|
|
878
1427
|
resolveEase,
|
|
879
1428
|
sampleBehavior,
|
|
880
1429
|
scene,
|
|
881
1430
|
seq,
|
|
1431
|
+
sketchToTimeline,
|
|
882
1432
|
stagger,
|
|
883
1433
|
text,
|
|
884
1434
|
to,
|