reframe-video 0.2.0 → 0.4.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/assets/sfx/LICENSE.md +1 -0
- package/assets/sfx/footstep_001.ogg +0 -0
- package/assets/sfx/footstep_002.ogg +0 -0
- package/assets/sfx/footstep_003.ogg +0 -0
- package/dist/bin.js +48 -2
- package/dist/browserEntry.js +49 -0
- package/dist/index.js +1027 -37
- package/dist/types/characterPreset.d.ts +39 -0
- package/dist/types/figure.d.ts +32 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/interpolate.d.ts +3 -2
- package/dist/types/rig.d.ts +87 -0
- package/dist/types/textFx.d.ts +91 -0
- package/dist/types/textMetrics.d.ts +3 -0
- package/guides/edsl-guide.md +84 -0
- package/guides/regen-contract.md +11 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,22 +15,22 @@ function locate(segCount, u) {
|
|
|
15
15
|
return { i, t: scaled - i };
|
|
16
16
|
}
|
|
17
17
|
function controls(points, closed, i) {
|
|
18
|
-
const
|
|
18
|
+
const n3 = points.length;
|
|
19
19
|
const at = (k) => {
|
|
20
|
-
if (closed) return points[(k %
|
|
21
|
-
return points[Math.max(0, Math.min(
|
|
20
|
+
if (closed) return points[(k % n3 + n3) % n3];
|
|
21
|
+
return points[Math.max(0, Math.min(n3 - 1, k))];
|
|
22
22
|
};
|
|
23
23
|
return [at(i - 1), at(i), at(i + 1), at(i + 2)];
|
|
24
24
|
}
|
|
25
25
|
function segCountOf(points, closed) {
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
return closed ?
|
|
26
|
+
const n3 = points.length;
|
|
27
|
+
if (n3 < 2) return 0;
|
|
28
|
+
return closed ? n3 : n3 - 1;
|
|
29
29
|
}
|
|
30
30
|
function pathPoint(points, closed, u, curviness = 1) {
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
if (
|
|
31
|
+
const n3 = points.length;
|
|
32
|
+
if (n3 === 0) return [0, 0];
|
|
33
|
+
if (n3 === 1) return [points[0][0], points[0][1]];
|
|
34
34
|
const segs = segCountOf(points, closed);
|
|
35
35
|
const { i, t } = locate(segs, u);
|
|
36
36
|
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
@@ -49,8 +49,8 @@ function pathPoint(points, closed, u, curviness = 1) {
|
|
|
49
49
|
return [H(p0[0], p1[0], p2[0], p3[0]), H(p0[1], p1[1], p2[1], p3[1])];
|
|
50
50
|
}
|
|
51
51
|
function pathTangentAngle(points, closed, u, curviness = 1) {
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
52
|
+
const n3 = points.length;
|
|
53
|
+
if (n3 < 2) return 0;
|
|
54
54
|
const segs = segCountOf(points, closed);
|
|
55
55
|
const { i, t } = locate(segs, u);
|
|
56
56
|
const [p0, p1, p2, p3] = controls(points, closed, i);
|
|
@@ -816,7 +816,7 @@ function applyOverlay(ir, overlay, layer, report, baseNodeIds) {
|
|
|
816
816
|
);
|
|
817
817
|
continue;
|
|
818
818
|
}
|
|
819
|
-
const index = ir.nodes.findIndex((
|
|
819
|
+
const index = ir.nodes.findIndex((n3) => n3.id === id);
|
|
820
820
|
if (index < 0) {
|
|
821
821
|
orphan(
|
|
822
822
|
`removeNodes.${id}`,
|
|
@@ -884,14 +884,14 @@ function makeRng(seed) {
|
|
|
884
884
|
var clamp01 = (x) => Math.max(0, Math.min(1, x));
|
|
885
885
|
var SET = 1 / 120;
|
|
886
886
|
function ctx(o) {
|
|
887
|
-
const
|
|
887
|
+
const rand2 = makeRng((o.seed ?? 0) + 1);
|
|
888
888
|
return {
|
|
889
889
|
e: clamp01(o.energy ?? 0.5),
|
|
890
890
|
sp: Math.max(0.25, o.speed ?? 1),
|
|
891
891
|
it: clamp01(o.intensity ?? 0.5),
|
|
892
892
|
from: o.from,
|
|
893
|
-
rand,
|
|
894
|
-
jit: (amp) => (
|
|
893
|
+
rand: rand2,
|
|
894
|
+
jit: (amp) => (rand2() - 0.5) * 2 * amp,
|
|
895
895
|
g: o.target.group,
|
|
896
896
|
cx: o.target.center[0],
|
|
897
897
|
cy: o.target.center[1],
|
|
@@ -1263,9 +1263,936 @@ function devicePreset(name, opts = {}) {
|
|
|
1263
1263
|
);
|
|
1264
1264
|
}
|
|
1265
1265
|
|
|
1266
|
+
// ../core/src/rig.ts
|
|
1267
|
+
var DEFAULT_LINE = "#FFE3D2";
|
|
1268
|
+
var DEFAULT_FILL = "#0E1424";
|
|
1269
|
+
var LINE_W = 5;
|
|
1270
|
+
var GLOW_W = 16;
|
|
1271
|
+
var K = 0.5523;
|
|
1272
|
+
var n = (v) => Number(v.toFixed(2));
|
|
1273
|
+
function capsulePath(hw, len) {
|
|
1274
|
+
const yT = hw;
|
|
1275
|
+
const yB = Math.max(hw, len - hw);
|
|
1276
|
+
const k = hw * K;
|
|
1277
|
+
return `M ${n(-hw)} ${n(yT)} C ${n(-hw)} ${n(yT - k)} ${n(-k)} ${n(yT - hw)} 0 ${n(yT - hw)} C ${n(k)} ${n(yT - hw)} ${n(hw)} ${n(yT - k)} ${n(hw)} ${n(yT)} L ${n(hw)} ${n(yB)} C ${n(hw)} ${n(yB + k)} ${n(k)} ${n(yB + hw)} 0 ${n(yB + hw)} C ${n(-k)} ${n(yB + hw)} ${n(-hw)} ${n(yB + k)} ${n(-hw)} ${n(yB)} Z`;
|
|
1278
|
+
}
|
|
1279
|
+
function ovalPath(a, b, cx = 0, cy = 0) {
|
|
1280
|
+
const ka = n(a * K), kb = n(b * K);
|
|
1281
|
+
const t = n(cy - b), bo = n(cy + b), c = n(cy), A = n(a), L = n(-a), X = n(cx);
|
|
1282
|
+
return `M ${X} ${t} C ${n(cx + ka)} ${t} ${n(cx + A)} ${n(cy - kb)} ${n(cx + A)} ${c} C ${n(cx + A)} ${n(cy + kb)} ${n(cx + ka)} ${bo} ${X} ${bo} C ${n(cx - ka)} ${bo} ${n(cx + L)} ${n(cy + kb)} ${n(cx + L)} ${c} C ${n(cx + L)} ${n(cy - kb)} ${n(cx - ka)} ${t} ${X} ${t} Z`;
|
|
1283
|
+
}
|
|
1284
|
+
function boneShape(jointId, bone, o) {
|
|
1285
|
+
if (bone.shape) return bone.shape;
|
|
1286
|
+
const len = bone.length ?? 0;
|
|
1287
|
+
if (len <= 0) return [];
|
|
1288
|
+
const d = capsulePath((bone.width ?? 20) / 2, len);
|
|
1289
|
+
const nodes = [];
|
|
1290
|
+
if (o.glow) nodes.push(path({ id: `${jointId}-glow`, d, x: 0, y: 0, fill: "none", stroke: o.glow, strokeWidth: GLOW_W, opacity: 0.18 }));
|
|
1291
|
+
nodes.push(path({ id: `${jointId}-shape`, d, x: 0, y: 0, fill: o.fill, stroke: o.color, strokeWidth: LINE_W }));
|
|
1292
|
+
return nodes;
|
|
1293
|
+
}
|
|
1294
|
+
function buildBone(bone, id, o) {
|
|
1295
|
+
const jointId = `${id}-${bone.name}`;
|
|
1296
|
+
return group(
|
|
1297
|
+
{ id: jointId, x: bone.at[0], y: bone.at[1], rotation: bone.rotation ?? 0 },
|
|
1298
|
+
[...boneShape(jointId, bone, o), ...(bone.children ?? []).map((c) => buildBone(c, id, o))]
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1301
|
+
function rig(root, opts = {}) {
|
|
1302
|
+
const id = opts.id ?? "rig";
|
|
1303
|
+
const o = { color: opts.color ?? DEFAULT_LINE, fill: opts.fill ?? DEFAULT_FILL, glow: opts.glow };
|
|
1304
|
+
return group(
|
|
1305
|
+
{ id, x: opts.x ?? 0, y: opts.y ?? 0, scale: opts.scale ?? 1, opacity: opts.opacity ?? 1 },
|
|
1306
|
+
[buildBone(root, id, o)]
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
function rigPose(id, pose) {
|
|
1310
|
+
const out = {};
|
|
1311
|
+
for (const [name, deg] of Object.entries(pose)) out[`${id}-${name}`] = { rotation: deg };
|
|
1312
|
+
return out;
|
|
1313
|
+
}
|
|
1314
|
+
function poseTo(id, pose, opts = {}) {
|
|
1315
|
+
const tweens = Object.entries(pose).map(
|
|
1316
|
+
([name, deg]) => tween(`${id}-${name}`, { rotation: deg }, { duration: opts.duration ?? 0.5, ease: opts.ease ?? "easeInOutCubic" })
|
|
1317
|
+
);
|
|
1318
|
+
return opts.stagger ? stagger(opts.stagger, ...tweens) : par(...tweens);
|
|
1319
|
+
}
|
|
1320
|
+
function ikReach(upper, lower, dx, dy, flip = false) {
|
|
1321
|
+
const D = Math.hypot(dx, dy);
|
|
1322
|
+
const cos2 = Math.max(-1, Math.min(1, (D * D - upper * upper - lower * lower) / (2 * upper * lower)));
|
|
1323
|
+
const theta2 = (flip ? -1 : 1) * Math.acos(cos2);
|
|
1324
|
+
const vx = -lower * Math.sin(theta2);
|
|
1325
|
+
const vy = upper + lower * Math.cos(theta2);
|
|
1326
|
+
const theta1 = Math.atan2(dy, dx) - Math.atan2(vy, vx);
|
|
1327
|
+
const deg = (r) => r * 180 / Math.PI;
|
|
1328
|
+
return [deg(theta1), deg(theta2)];
|
|
1329
|
+
}
|
|
1330
|
+
function humanoid(opts = {}) {
|
|
1331
|
+
const line2 = opts.color ?? DEFAULT_LINE;
|
|
1332
|
+
const fill = opts.fill ?? DEFAULT_FILL;
|
|
1333
|
+
const glow = opts.glow;
|
|
1334
|
+
const blob = (jid, a, b, cy) => {
|
|
1335
|
+
const d = ovalPath(a, b, 0, cy);
|
|
1336
|
+
const nodes = [];
|
|
1337
|
+
if (glow) nodes.push(path({ id: `${jid}-glow`, d, x: 0, y: 0, fill: "none", stroke: glow, strokeWidth: GLOW_W, opacity: 0.18 }));
|
|
1338
|
+
nodes.push(path({ id: `${jid}-shape`, d, x: 0, y: 0, fill, stroke: line2, strokeWidth: LINE_W }));
|
|
1339
|
+
return nodes;
|
|
1340
|
+
};
|
|
1341
|
+
const id = opts.id ?? "rig";
|
|
1342
|
+
const root = {
|
|
1343
|
+
name: "chest",
|
|
1344
|
+
at: [0, 0],
|
|
1345
|
+
shape: blob(`${id}-chest`, 44, 62, 22),
|
|
1346
|
+
children: [
|
|
1347
|
+
{ name: "head", at: [0, -42], rotation: 0, shape: blob(`${id}-head`, 40, 42, -34) },
|
|
1348
|
+
{ name: "armUpperL", at: [-42, -20], length: 60, width: 20, rotation: 10, children: [
|
|
1349
|
+
{ name: "armLowerL", at: [0, 60], length: 56, width: 16, rotation: 8 }
|
|
1350
|
+
] },
|
|
1351
|
+
{ name: "armUpperR", at: [42, -20], length: 60, width: 20, rotation: -10, children: [
|
|
1352
|
+
{ name: "armLowerR", at: [0, 60], length: 56, width: 16, rotation: -8 }
|
|
1353
|
+
] },
|
|
1354
|
+
{ name: "legUpperL", at: [-20, 76], length: 76, width: 26, rotation: 3, children: [
|
|
1355
|
+
{ name: "legLowerL", at: [0, 76], length: 72, width: 22, rotation: -2 }
|
|
1356
|
+
] },
|
|
1357
|
+
{ name: "legUpperR", at: [20, 76], length: 76, width: 26, rotation: -3, children: [
|
|
1358
|
+
{ name: "legLowerR", at: [0, 76], length: 72, width: 22, rotation: 2 }
|
|
1359
|
+
] }
|
|
1360
|
+
]
|
|
1361
|
+
};
|
|
1362
|
+
return rig(root, opts);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
// ../core/src/characterPreset.ts
|
|
1366
|
+
var CHARACTER_PRESET_NAMES = ["walk", "run", "jump", "dance", "wave", "cheer"];
|
|
1367
|
+
var THIGH = 76;
|
|
1368
|
+
var SHIN = 72;
|
|
1369
|
+
var clamp012 = (x) => Math.max(0, Math.min(1, x));
|
|
1370
|
+
function makeRng2(seed) {
|
|
1371
|
+
let a = seed >>> 0 || 2654435769;
|
|
1372
|
+
return () => {
|
|
1373
|
+
a = a + 1831565813 | 0;
|
|
1374
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
1375
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
1376
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
var dur2 = (base, sp) => base / sp;
|
|
1380
|
+
function ctx2(o) {
|
|
1381
|
+
const rand2 = makeRng2((o.seed ?? 0) + 1);
|
|
1382
|
+
return {
|
|
1383
|
+
g: o.target,
|
|
1384
|
+
label: o.label,
|
|
1385
|
+
e: clamp012(o.energy ?? 0.5),
|
|
1386
|
+
sp: Math.max(0.25, o.speed ?? 1),
|
|
1387
|
+
cycles: Math.max(1, Math.round(o.cycles ?? 4)),
|
|
1388
|
+
facing: o.facing ?? 1,
|
|
1389
|
+
at: o.at ?? [0, 0],
|
|
1390
|
+
travel: o.travel,
|
|
1391
|
+
rand: rand2,
|
|
1392
|
+
jit: (amp) => (rand2() - 0.5) * 2 * amp
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
var round = (v) => Math.round(v * 1e3) / 1e3;
|
|
1396
|
+
function footPos(p, stride, lift) {
|
|
1397
|
+
p = (p % 1 + 1) % 1;
|
|
1398
|
+
if (p < 0.5) {
|
|
1399
|
+
const u2 = p / 0.5;
|
|
1400
|
+
return [stride * (1 - 2 * u2), 138];
|
|
1401
|
+
}
|
|
1402
|
+
const u = (p - 0.5) / 0.5;
|
|
1403
|
+
return [-stride + 2 * stride * u, 138 - Math.sin(Math.PI * u) * lift];
|
|
1404
|
+
}
|
|
1405
|
+
function gaitPose(ph, stride, lift, armSwing, facing) {
|
|
1406
|
+
const fl = footPos(ph, stride, lift);
|
|
1407
|
+
const fr = footPos(ph + 0.5, stride, lift);
|
|
1408
|
+
const [hipL, kneeL] = ikReach(THIGH, SHIN, facing * fl[0], fl[1], facing < 0);
|
|
1409
|
+
const [hipR, kneeR] = ikReach(THIGH, SHIN, facing * fr[0], fr[1], facing < 0);
|
|
1410
|
+
const swing = Math.cos(2 * Math.PI * ph);
|
|
1411
|
+
return {
|
|
1412
|
+
legUpperL: round(hipL),
|
|
1413
|
+
legLowerL: round(kneeL),
|
|
1414
|
+
legUpperR: round(hipR),
|
|
1415
|
+
legLowerR: round(kneeR),
|
|
1416
|
+
armUpperR: round(-10 - armSwing * swing),
|
|
1417
|
+
armLowerR: -16,
|
|
1418
|
+
armUpperL: round(10 + armSwing * swing),
|
|
1419
|
+
armLowerL: 16
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
function gait(c, run) {
|
|
1423
|
+
const stride = (run ? 34 : 24) + (run ? 40 : 30) * c.e + c.jit(3);
|
|
1424
|
+
const lift = run ? 40 : 26;
|
|
1425
|
+
const armSwing = (run ? 26 : 16) + 20 * c.e;
|
|
1426
|
+
const halfDur = (run ? 0.26 : 0.42) + c.jit(0.02);
|
|
1427
|
+
const lean = run ? c.facing * -6 : 0;
|
|
1428
|
+
const steps = c.cycles * 2;
|
|
1429
|
+
const d = dur2(halfDur, c.sp);
|
|
1430
|
+
const intro = dur2(0.16, c.sp);
|
|
1431
|
+
const keys = [];
|
|
1432
|
+
for (let k = 0; k <= steps; k++) {
|
|
1433
|
+
const pose = { ...gaitPose(k / 2, stride, lift, armSwing, c.facing), chest: lean };
|
|
1434
|
+
keys.push(poseTo(c.g, pose, { duration: k === 0 ? intro : d, ease: k === 0 ? "easeOutQuad" : "linear" }));
|
|
1435
|
+
}
|
|
1436
|
+
const total = intro + steps * d;
|
|
1437
|
+
const travel = c.travel ?? stride * 2;
|
|
1438
|
+
const children = [seq(...keys)];
|
|
1439
|
+
if (travel !== 0) {
|
|
1440
|
+
children.push(tween(c.g, { x: c.at[0] + c.facing * travel * c.cycles }, { duration: total, ease: "linear", label: "travel" }));
|
|
1441
|
+
}
|
|
1442
|
+
return beat(run ? "run" : "walk", {}, [par(...children)]);
|
|
1443
|
+
}
|
|
1444
|
+
function jumpBeat(c) {
|
|
1445
|
+
const h = 120 + 150 * c.e;
|
|
1446
|
+
const [y0] = [c.at[1]];
|
|
1447
|
+
const CROUCH = { legUpperL: 18, legLowerL: 54, legUpperR: -18, legLowerR: 54, armUpperL: 28, armUpperR: -28 };
|
|
1448
|
+
const LAUNCH = { legUpperL: 0, legLowerL: 0, legUpperR: 0, legLowerR: 0, armUpperL: 150, armUpperR: -150 };
|
|
1449
|
+
const TUCK = { legUpperL: -28, legLowerL: 66, legUpperR: -28, legLowerR: 66, armUpperL: 124, armUpperR: -124 };
|
|
1450
|
+
const REST = { legUpperL: 3, legLowerL: -2, legUpperR: -3, legLowerR: 2, armUpperL: 10, armLowerL: 8, armUpperR: -10, armLowerR: -8 };
|
|
1451
|
+
const j = c.jit(0.03);
|
|
1452
|
+
return beat("jump", {}, [
|
|
1453
|
+
seq(
|
|
1454
|
+
par(poseTo(c.g, CROUCH, { duration: dur2(0.24, c.sp), ease: "easeOutQuad" }), tween(c.g, { y: y0 + 26 }, { duration: dur2(0.24, c.sp), ease: "easeOutQuad" })),
|
|
1455
|
+
par(poseTo(c.g, LAUNCH, { duration: dur2(0.22 + j, c.sp), ease: "easeOutCubic" }), tween(c.g, { y: y0 - h }, { duration: dur2(0.36, c.sp), ease: "easeOutCubic", label: "launch" })),
|
|
1456
|
+
poseTo(c.g, TUCK, { duration: dur2(0.22, c.sp) }),
|
|
1457
|
+
par(poseTo(c.g, CROUCH, { duration: dur2(0.28, c.sp), ease: "easeInQuad" }), tween(c.g, { y: y0 + 18 }, { duration: dur2(0.3, c.sp), ease: "easeInCubic", label: "land" })),
|
|
1458
|
+
par(poseTo(c.g, REST, { duration: dur2(0.45, c.sp), ease: "easeOutBack" }), tween(c.g, { y: y0 }, { duration: dur2(0.45, c.sp), ease: "easeOutBack" }))
|
|
1459
|
+
)
|
|
1460
|
+
]);
|
|
1461
|
+
}
|
|
1462
|
+
function danceBeat(c) {
|
|
1463
|
+
const y0 = c.at[1];
|
|
1464
|
+
const sway = 8 + 6 * c.e;
|
|
1465
|
+
const armUp = 130 + 30 * c.e;
|
|
1466
|
+
const A = { chest: sway, head: -sway * 0.5, armUpperR: -armUp, armLowerR: -20, armUpperL: 40, armLowerL: 30, legUpperL: 8, legUpperR: -2 };
|
|
1467
|
+
const B = { chest: -sway, head: sway * 0.5, armUpperL: armUp, armLowerL: 20, armUpperR: -40, armLowerR: -30, legUpperL: 2, legUpperR: -8 };
|
|
1468
|
+
const d = dur2(0.34, c.sp);
|
|
1469
|
+
const keys = [];
|
|
1470
|
+
for (let k = 0; k < c.cycles * 2; k++) {
|
|
1471
|
+
const pose = k % 2 === 0 ? A : B;
|
|
1472
|
+
keys.push(par(
|
|
1473
|
+
poseTo(c.g, pose, { duration: d, ease: "easeInOutQuad" }),
|
|
1474
|
+
tween(c.g, { y: y0 - (k % 2 === 0 ? 14 : 0) }, { duration: d, ease: "easeInOutQuad" })
|
|
1475
|
+
));
|
|
1476
|
+
}
|
|
1477
|
+
keys.push(tween(c.g, { y: y0 }, { duration: d }));
|
|
1478
|
+
return beat("dance", {}, [seq(...keys)]);
|
|
1479
|
+
}
|
|
1480
|
+
function waveBeat(c) {
|
|
1481
|
+
const n3 = 3 + Math.round(c.rand() * 2);
|
|
1482
|
+
const amp = 16 + 10 * c.e;
|
|
1483
|
+
const steps = [poseTo(c.g, { armUpperR: -150, armLowerR: -24 }, { duration: dur2(0.4, c.sp), ease: "easeOutBack" })];
|
|
1484
|
+
for (let k = 0; k < n3; k++) {
|
|
1485
|
+
steps.push(poseTo(c.g, { armLowerR: -24 + (k % 2 === 0 ? amp : -amp) }, { duration: dur2(0.22, c.sp), ease: "easeInOutQuad" }));
|
|
1486
|
+
}
|
|
1487
|
+
steps.push(poseTo(c.g, { armUpperR: -10, armLowerR: -8 }, { duration: dur2(0.4, c.sp), ease: "easeInOutCubic" }));
|
|
1488
|
+
return beat("wave", {}, [seq(...steps)]);
|
|
1489
|
+
}
|
|
1490
|
+
function cheerBeat(c) {
|
|
1491
|
+
const y0 = c.at[1];
|
|
1492
|
+
const UP = { armUpperL: 152, armLowerL: 8, armUpperR: -152, armLowerR: -8 };
|
|
1493
|
+
const d = dur2(0.3, c.sp);
|
|
1494
|
+
const keys = [poseTo(c.g, UP, { duration: dur2(0.35, c.sp), ease: "easeOutBack" })];
|
|
1495
|
+
for (let k = 0; k < c.cycles; k++) {
|
|
1496
|
+
keys.push(par(tween(c.g, { y: y0 - 28 }, { duration: d, ease: "easeOutQuad" }), poseTo(c.g, { armUpperL: 160, armUpperR: -160 }, { duration: d })));
|
|
1497
|
+
keys.push(par(tween(c.g, { y: y0 }, { duration: d, ease: "easeInQuad" }), poseTo(c.g, { armUpperL: 145, armUpperR: -145 }, { duration: d })));
|
|
1498
|
+
}
|
|
1499
|
+
return beat("cheer", {}, [seq(...keys)]);
|
|
1500
|
+
}
|
|
1501
|
+
function characterPreset(name, opts) {
|
|
1502
|
+
const c = ctx2(opts);
|
|
1503
|
+
let tl;
|
|
1504
|
+
switch (name) {
|
|
1505
|
+
case "walk":
|
|
1506
|
+
tl = gait(c, false);
|
|
1507
|
+
break;
|
|
1508
|
+
case "run":
|
|
1509
|
+
tl = gait(c, true);
|
|
1510
|
+
break;
|
|
1511
|
+
case "jump":
|
|
1512
|
+
tl = jumpBeat(c);
|
|
1513
|
+
break;
|
|
1514
|
+
case "dance":
|
|
1515
|
+
tl = danceBeat(c);
|
|
1516
|
+
break;
|
|
1517
|
+
case "wave":
|
|
1518
|
+
tl = waveBeat(c);
|
|
1519
|
+
break;
|
|
1520
|
+
case "cheer":
|
|
1521
|
+
tl = cheerBeat(c);
|
|
1522
|
+
break;
|
|
1523
|
+
default: {
|
|
1524
|
+
const _exhaustive = name;
|
|
1525
|
+
throw new Error(`unknown characterPreset "${_exhaustive}"`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return c.label && tl.kind === "beat" ? { ...tl, name: c.label } : tl;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
// ../core/src/figure.ts
|
|
1532
|
+
var K2 = 0.5523;
|
|
1533
|
+
var n2 = (v) => Number(v.toFixed(2));
|
|
1534
|
+
function limb(a, b, y0, y1) {
|
|
1535
|
+
const ka = n2(a * K2), kb = n2(b * K2);
|
|
1536
|
+
return `M ${-a} ${y0} C ${-a} ${n2(y0 - ka)} ${-ka} ${n2(y0 - a)} 0 ${n2(y0 - a)} C ${ka} ${n2(y0 - a)} ${a} ${n2(y0 - ka)} ${a} ${y0} L ${b} ${y1} C ${b} ${n2(y1 + kb)} ${kb} ${n2(y1 + b)} 0 ${n2(y1 + b)} C ${-kb} ${n2(y1 + b)} ${-b} ${n2(y1 + kb)} ${-b} ${y1} Z`;
|
|
1537
|
+
}
|
|
1538
|
+
function rrect(a, b, y0, y1, r) {
|
|
1539
|
+
return `M ${n2(-a + r)} ${y0} L ${n2(a - r)} ${y0} Q ${a} ${y0} ${a} ${n2(y0 + r)} L ${b} ${n2(y1 - r)} Q ${b} ${y1} ${n2(b - r)} ${y1} L ${n2(-b + r)} ${y1} Q ${-b} ${y1} ${-b} ${n2(y1 - r)} L ${-a} ${n2(y0 + r)} Q ${-a} ${y0} ${n2(-a + r)} ${y0} Z`;
|
|
1540
|
+
}
|
|
1541
|
+
function darken(hex, f) {
|
|
1542
|
+
const h = hex.replace("#", "");
|
|
1543
|
+
const v = parseInt(h.length === 3 ? [...h].map((c) => c + c).join("") : h, 16);
|
|
1544
|
+
const ch = (s) => Math.max(0, Math.min(255, Math.round((v >> s & 255) * (1 - f))));
|
|
1545
|
+
const hx = (x) => x.toString(16).padStart(2, "0");
|
|
1546
|
+
return `#${hx(ch(16))}${hx(ch(8))}${hx(ch(0))}`;
|
|
1547
|
+
}
|
|
1548
|
+
var DEF = {
|
|
1549
|
+
clean: { skin: "#E9B58E", hair: "#2B313F", top: "#E86C4A", pants: "#39425C", shoe: "#20242F", accent: "#E86C4A" },
|
|
1550
|
+
cute: { skin: "#FFD2A6", hair: "#5B4636", top: "#FF7E5F", pants: "#3E6F8E", shoe: "#272B38", accent: "#FF7E5F" }
|
|
1551
|
+
};
|
|
1552
|
+
function resolvePal(style, p = {}) {
|
|
1553
|
+
const d = DEF[style];
|
|
1554
|
+
const accent = p.accent ?? d.accent;
|
|
1555
|
+
const top = p.top ?? (style === "clean" ? accent : d.top);
|
|
1556
|
+
const skin = p.skin ?? d.skin;
|
|
1557
|
+
const hair = p.hair ?? d.hair;
|
|
1558
|
+
const pants = p.pants ?? d.pants;
|
|
1559
|
+
const shoe = p.shoe ?? d.shoe;
|
|
1560
|
+
return {
|
|
1561
|
+
skin,
|
|
1562
|
+
skinSh: darken(skin, 0.12),
|
|
1563
|
+
hair,
|
|
1564
|
+
hairSh: darken(hair, 0.14),
|
|
1565
|
+
top,
|
|
1566
|
+
topSh: darken(top, 0.12),
|
|
1567
|
+
pants,
|
|
1568
|
+
pantsSh: darken(pants, 0.14),
|
|
1569
|
+
shoe,
|
|
1570
|
+
shoeSh: darken(shoe, 0.22),
|
|
1571
|
+
eye: "#2B313F",
|
|
1572
|
+
cheek: "#FF9E7E",
|
|
1573
|
+
white: "#FFFFFF",
|
|
1574
|
+
mouth: "#8A4233"
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
var fp = (id, d, fill, stroke, sw = 0, opacity = 1) => path({ id, d, x: 0, y: 0, fill, opacity, ...stroke && sw > 0 ? { stroke, strokeWidth: sw } : {} });
|
|
1578
|
+
function cleanParts(p, face) {
|
|
1579
|
+
const HC = -42;
|
|
1580
|
+
return {
|
|
1581
|
+
upperArm: (j) => [fp(`${j}-sleeve`, limb(12, 10, 2, 58), p.top)],
|
|
1582
|
+
forearm: (j) => [
|
|
1583
|
+
fp(`${j}-elbow`, ovalPath(10, 10, 0, 3), p.skin),
|
|
1584
|
+
fp(`${j}-fore`, limb(10, 8, 2, 48), p.skin),
|
|
1585
|
+
fp(`${j}-hand`, ovalPath(11, 12, 0, 50), p.skin)
|
|
1586
|
+
],
|
|
1587
|
+
thigh: (j) => [fp(`${j}-thigh`, limb(15, 13, 2, 72), p.pants)],
|
|
1588
|
+
shin: (j) => [
|
|
1589
|
+
fp(`${j}-knee`, ovalPath(13, 13, 0, 2), p.pants),
|
|
1590
|
+
fp(`${j}-shin`, limb(13, 11, 2, 62), p.pants),
|
|
1591
|
+
fp(`${j}-shoe`, ovalPath(15, 9, 4, 67), p.shoe)
|
|
1592
|
+
],
|
|
1593
|
+
torso: (j) => [
|
|
1594
|
+
fp(`${j}-shadow`, rrect(38, 26, -28, 52, 20), p.topSh),
|
|
1595
|
+
fp(`${j}-top`, rrect(40, 27, -30, 52, 22), p.top),
|
|
1596
|
+
fp(`${j}-pelvis`, rrect(29, 24, 46, 104, 14), p.pants)
|
|
1597
|
+
],
|
|
1598
|
+
head: (j) => [
|
|
1599
|
+
fp(`${j}-neck`, rrect(9, 9, 2, 22, 5), p.skin),
|
|
1600
|
+
fp(`${j}-skin`, ovalPath(42, 46, 0, HC), p.skin),
|
|
1601
|
+
fp(`${j}-hair`, ovalPath(44, 27, 0, HC - 31), p.hair),
|
|
1602
|
+
fp(`${j}-hairL`, ovalPath(8, 14, -39, HC - 18), p.hair),
|
|
1603
|
+
fp(`${j}-hairR`, ovalPath(8, 14, 39, HC - 18), p.hair),
|
|
1604
|
+
...face ? [fp(`${j}-eyeL`, ovalPath(5, 7, -14, HC + 2), p.eye), fp(`${j}-eyeR`, ovalPath(5, 7, 14, HC + 2), p.eye)] : []
|
|
1605
|
+
]
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
var CUTE_HAIR = "M -64 -54 C -78 -96 -50 -126 0 -126 C 50 -126 78 -96 64 -54 C 60 -34 48 -28 41 -33 C 35 -54 23 -60 9 -60 C 3 -60 -3 -60 -9 -60 C -23 -60 -35 -54 -41 -33 C -48 -28 -60 -34 -64 -54 Z";
|
|
1609
|
+
function cuteParts(p, face) {
|
|
1610
|
+
const HC = -50;
|
|
1611
|
+
return {
|
|
1612
|
+
upperArm: (j) => [fp(`${j}-sleeve`, limb(15, 13, 2, 58), p.top, p.topSh, 2.5)],
|
|
1613
|
+
forearm: (j) => [
|
|
1614
|
+
fp(`${j}-elbow`, ovalPath(12, 12, 0, 3), p.skin, p.skinSh, 2.5),
|
|
1615
|
+
fp(`${j}-fore`, limb(12, 10, 2, 46), p.skin, p.skinSh, 2.5),
|
|
1616
|
+
fp(`${j}-hand`, ovalPath(13, 14, 0, 50), p.skin, p.skinSh, 2.5)
|
|
1617
|
+
],
|
|
1618
|
+
thigh: (j) => [fp(`${j}-thigh`, limb(19, 16, 2, 72), p.pants, p.pantsSh, 2.5)],
|
|
1619
|
+
shin: (j) => [
|
|
1620
|
+
fp(`${j}-knee`, ovalPath(16, 16, 0, 2), p.pants, p.pantsSh, 2.5),
|
|
1621
|
+
fp(`${j}-shin`, limb(15, 12, 2, 60), p.pants, p.pantsSh, 2.5),
|
|
1622
|
+
fp(`${j}-shoe`, ovalPath(18, 11, 5, 66), p.shoe, darken(p.shoe, 0.25), 2.5)
|
|
1623
|
+
],
|
|
1624
|
+
torso: (j) => [
|
|
1625
|
+
fp(`${j}-shadow`, rrect(40, 34, -18, 52, 16), p.topSh),
|
|
1626
|
+
fp(`${j}-top`, rrect(42, 35, -20, 52, 18), p.top, p.topSh, 2.5),
|
|
1627
|
+
fp(`${j}-pelvis`, rrect(36, 30, 46, 104, 16), p.pants, p.pantsSh, 2.5)
|
|
1628
|
+
],
|
|
1629
|
+
head: (j) => [
|
|
1630
|
+
fp(`${j}-neck`, ovalPath(15, 12, 0, 12), p.skinSh),
|
|
1631
|
+
fp(`${j}-skin`, ovalPath(42, 46, 0, HC + 4), p.skin, p.skinSh, 2.5),
|
|
1632
|
+
fp(`${j}-cheekL`, ovalPath(11, 8, -40, HC + 22), p.cheek, void 0, 0, 0.5),
|
|
1633
|
+
fp(`${j}-cheekR`, ovalPath(11, 8, 40, HC + 22), p.cheek, void 0, 0, 0.5),
|
|
1634
|
+
fp(`${j}-hair`, CUTE_HAIR, p.hair, p.hairSh, 2),
|
|
1635
|
+
...face ? [
|
|
1636
|
+
fp(`${j}-eyeL`, ovalPath(10, 13, -25, HC + 8), p.eye),
|
|
1637
|
+
fp(`${j}-eyeR`, ovalPath(10, 13, 25, HC + 8), p.eye),
|
|
1638
|
+
fp(`${j}-glL`, ovalPath(3.4, 3.4, -28, HC + 3), p.white),
|
|
1639
|
+
fp(`${j}-glR`, ovalPath(3.4, 3.4, 22, HC + 3), p.white),
|
|
1640
|
+
path({ id: `${j}-mouth`, d: "M -15 0 Q 0 15 15 0", x: 0, y: HC + 28, fill: "none", stroke: p.mouth, strokeWidth: 5 })
|
|
1641
|
+
] : []
|
|
1642
|
+
]
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
function buildSkeleton(id, S) {
|
|
1646
|
+
const arm = (side, x, r1, r2) => ({
|
|
1647
|
+
name: `armUpper${side}`,
|
|
1648
|
+
at: [x, -14],
|
|
1649
|
+
length: 60,
|
|
1650
|
+
width: 0,
|
|
1651
|
+
rotation: r1,
|
|
1652
|
+
shape: S.upperArm(`${id}-armUpper${side}`),
|
|
1653
|
+
children: [{ name: `armLower${side}`, at: [0, 60], length: 56, width: 0, rotation: r2, shape: S.forearm(`${id}-armLower${side}`) }]
|
|
1654
|
+
});
|
|
1655
|
+
const leg = (side, x, r1, r2) => ({
|
|
1656
|
+
name: `legUpper${side}`,
|
|
1657
|
+
at: [x, 76],
|
|
1658
|
+
length: 76,
|
|
1659
|
+
width: 0,
|
|
1660
|
+
rotation: r1,
|
|
1661
|
+
shape: S.thigh(`${id}-legUpper${side}`),
|
|
1662
|
+
children: [{ name: `legLower${side}`, at: [0, 76], length: 72, width: 0, rotation: r2, shape: S.shin(`${id}-legLower${side}`) }]
|
|
1663
|
+
});
|
|
1664
|
+
return {
|
|
1665
|
+
name: "chest",
|
|
1666
|
+
at: [0, 0],
|
|
1667
|
+
shape: S.torso(`${id}-chest`),
|
|
1668
|
+
children: [
|
|
1669
|
+
{ name: "head", at: [0, -42], rotation: 0, shape: S.head(`${id}-head`) },
|
|
1670
|
+
arm("L", -40, 8, 6),
|
|
1671
|
+
arm("R", 40, -8, -6),
|
|
1672
|
+
leg("L", -20, 3, -2),
|
|
1673
|
+
leg("R", 20, -3, 2)
|
|
1674
|
+
]
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
function figure(opts = {}) {
|
|
1678
|
+
const style = opts.style ?? "clean";
|
|
1679
|
+
const pal = resolvePal(style, opts.palette);
|
|
1680
|
+
const face = opts.face ?? true;
|
|
1681
|
+
const id = opts.id ?? "figure";
|
|
1682
|
+
const parts = style === "clean" ? cleanParts(pal, face) : cuteParts(pal, face);
|
|
1683
|
+
const rigOpts = { id };
|
|
1684
|
+
if (opts.x !== void 0) rigOpts.x = opts.x;
|
|
1685
|
+
if (opts.y !== void 0) rigOpts.y = opts.y;
|
|
1686
|
+
if (opts.scale !== void 0) rigOpts.scale = opts.scale;
|
|
1687
|
+
if (opts.opacity !== void 0) rigOpts.opacity = opts.opacity;
|
|
1688
|
+
return rig(buildSkeleton(id, parts), rigOpts);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// ../core/src/textMetrics.ts
|
|
1692
|
+
var INTER_ADVANCE = {
|
|
1693
|
+
"400": {
|
|
1694
|
+
"0": 63.09,
|
|
1695
|
+
"1": 40.67,
|
|
1696
|
+
"2": 60.99,
|
|
1697
|
+
"3": 61.77,
|
|
1698
|
+
"4": 64.6,
|
|
1699
|
+
"5": 59.33,
|
|
1700
|
+
"6": 62.01,
|
|
1701
|
+
"7": 56.59,
|
|
1702
|
+
"8": 61.87,
|
|
1703
|
+
"9": 62.01,
|
|
1704
|
+
" ": 28.13,
|
|
1705
|
+
"!": 28.76,
|
|
1706
|
+
'"': 46.58,
|
|
1707
|
+
"#": 63.33,
|
|
1708
|
+
"$": 64.16,
|
|
1709
|
+
"%": 98.19,
|
|
1710
|
+
"&": 64.4,
|
|
1711
|
+
"'": 29.98,
|
|
1712
|
+
"(": 36.47,
|
|
1713
|
+
")": 36.47,
|
|
1714
|
+
"*": 50.1,
|
|
1715
|
+
"+": 66.16,
|
|
1716
|
+
",": 28.81,
|
|
1717
|
+
"-": 46,
|
|
1718
|
+
".": 28.81,
|
|
1719
|
+
"/": 36.04,
|
|
1720
|
+
":": 28.81,
|
|
1721
|
+
";": 30.18,
|
|
1722
|
+
"<": 66.16,
|
|
1723
|
+
"=": 66.16,
|
|
1724
|
+
">": 66.16,
|
|
1725
|
+
"?": 51.12,
|
|
1726
|
+
"@": 96.58,
|
|
1727
|
+
"A": 68.99,
|
|
1728
|
+
"B": 65.43,
|
|
1729
|
+
"C": 73.05,
|
|
1730
|
+
"D": 72.17,
|
|
1731
|
+
"E": 60.11,
|
|
1732
|
+
"F": 59.03,
|
|
1733
|
+
"G": 74.61,
|
|
1734
|
+
"H": 74.32,
|
|
1735
|
+
"I": 26.86,
|
|
1736
|
+
"J": 57.08,
|
|
1737
|
+
"K": 67.19,
|
|
1738
|
+
"L": 56.54,
|
|
1739
|
+
"M": 90.33,
|
|
1740
|
+
"N": 75.34,
|
|
1741
|
+
"O": 76.46,
|
|
1742
|
+
"P": 63.87,
|
|
1743
|
+
"Q": 76.46,
|
|
1744
|
+
"R": 64.36,
|
|
1745
|
+
"S": 64.16,
|
|
1746
|
+
"T": 64.55,
|
|
1747
|
+
"U": 74.41,
|
|
1748
|
+
"V": 68.99,
|
|
1749
|
+
"W": 98.54,
|
|
1750
|
+
"X": 68.21,
|
|
1751
|
+
"Y": 67.87,
|
|
1752
|
+
"Z": 62.89,
|
|
1753
|
+
"[": 36.47,
|
|
1754
|
+
"\\": 36.04,
|
|
1755
|
+
"]": 36.47,
|
|
1756
|
+
"^": 47.12,
|
|
1757
|
+
"_": 45.61,
|
|
1758
|
+
"`": 32.28,
|
|
1759
|
+
"a": 56.15,
|
|
1760
|
+
"b": 61.23,
|
|
1761
|
+
"c": 57.13,
|
|
1762
|
+
"d": 61.23,
|
|
1763
|
+
"e": 58.3,
|
|
1764
|
+
"f": 37.01,
|
|
1765
|
+
"g": 61.33,
|
|
1766
|
+
"h": 59.13,
|
|
1767
|
+
"i": 24.22,
|
|
1768
|
+
"j": 24.22,
|
|
1769
|
+
"k": 54.88,
|
|
1770
|
+
"l": 24.22,
|
|
1771
|
+
"m": 87.6,
|
|
1772
|
+
"n": 59.08,
|
|
1773
|
+
"o": 59.96,
|
|
1774
|
+
"p": 61.23,
|
|
1775
|
+
"q": 61.23,
|
|
1776
|
+
"r": 37.65,
|
|
1777
|
+
"s": 52.78,
|
|
1778
|
+
"t": 32.71,
|
|
1779
|
+
"u": 59.13,
|
|
1780
|
+
"v": 56.2,
|
|
1781
|
+
"w": 81.84,
|
|
1782
|
+
"x": 54.59,
|
|
1783
|
+
"y": 56.2,
|
|
1784
|
+
"z": 55.22,
|
|
1785
|
+
"{": 42.63,
|
|
1786
|
+
"|": 33.25,
|
|
1787
|
+
"}": 42.63,
|
|
1788
|
+
"~": 66.16
|
|
1789
|
+
},
|
|
1790
|
+
"700": {
|
|
1791
|
+
"0": 67.43,
|
|
1792
|
+
"1": 43.12,
|
|
1793
|
+
"2": 62.94,
|
|
1794
|
+
"3": 64.55,
|
|
1795
|
+
"4": 67.63,
|
|
1796
|
+
"5": 62.21,
|
|
1797
|
+
"6": 64.94,
|
|
1798
|
+
"7": 58.15,
|
|
1799
|
+
"8": 65.09,
|
|
1800
|
+
"9": 64.94,
|
|
1801
|
+
" ": 23.68,
|
|
1802
|
+
"!": 33.79,
|
|
1803
|
+
'"': 55.13,
|
|
1804
|
+
"#": 64.89,
|
|
1805
|
+
"$": 65.48,
|
|
1806
|
+
"%": 101.56,
|
|
1807
|
+
"&": 67.19,
|
|
1808
|
+
"'": 33.89,
|
|
1809
|
+
"(": 37.7,
|
|
1810
|
+
")": 37.7,
|
|
1811
|
+
"*": 55.91,
|
|
1812
|
+
"+": 67.87,
|
|
1813
|
+
",": 33.4,
|
|
1814
|
+
"-": 46.78,
|
|
1815
|
+
".": 33.4,
|
|
1816
|
+
"/": 38.82,
|
|
1817
|
+
":": 33.4,
|
|
1818
|
+
";": 34.28,
|
|
1819
|
+
"<": 67.87,
|
|
1820
|
+
"=": 67.87,
|
|
1821
|
+
">": 67.87,
|
|
1822
|
+
"?": 55.96,
|
|
1823
|
+
"@": 101.61,
|
|
1824
|
+
"A": 74.66,
|
|
1825
|
+
"B": 66.16,
|
|
1826
|
+
"C": 73.97,
|
|
1827
|
+
"D": 72.22,
|
|
1828
|
+
"E": 60.74,
|
|
1829
|
+
"F": 58.69,
|
|
1830
|
+
"G": 75.05,
|
|
1831
|
+
"H": 74.71,
|
|
1832
|
+
"I": 28.08,
|
|
1833
|
+
"J": 58.45,
|
|
1834
|
+
"K": 71.92,
|
|
1835
|
+
"L": 56.54,
|
|
1836
|
+
"M": 93.16,
|
|
1837
|
+
"N": 76.22,
|
|
1838
|
+
"O": 77.05,
|
|
1839
|
+
"P": 64.79,
|
|
1840
|
+
"Q": 77.69,
|
|
1841
|
+
"R": 65.67,
|
|
1842
|
+
"S": 65.48,
|
|
1843
|
+
"T": 66.75,
|
|
1844
|
+
"U": 73.19,
|
|
1845
|
+
"V": 74.66,
|
|
1846
|
+
"W": 103.76,
|
|
1847
|
+
"X": 73.83,
|
|
1848
|
+
"Y": 73.1,
|
|
1849
|
+
"Z": 66.41,
|
|
1850
|
+
"[": 37.7,
|
|
1851
|
+
"\\": 38.82,
|
|
1852
|
+
"]": 37.7,
|
|
1853
|
+
"^": 48.68,
|
|
1854
|
+
"_": 47.61,
|
|
1855
|
+
"`": 36.52,
|
|
1856
|
+
"a": 58.06,
|
|
1857
|
+
"b": 63.04,
|
|
1858
|
+
"c": 58.84,
|
|
1859
|
+
"d": 63.04,
|
|
1860
|
+
"e": 59.57,
|
|
1861
|
+
"f": 39.79,
|
|
1862
|
+
"g": 63.18,
|
|
1863
|
+
"h": 62.26,
|
|
1864
|
+
"i": 27.1,
|
|
1865
|
+
"j": 27.1,
|
|
1866
|
+
"k": 58.01,
|
|
1867
|
+
"l": 27.1,
|
|
1868
|
+
"m": 91.26,
|
|
1869
|
+
"n": 62.26,
|
|
1870
|
+
"o": 61.33,
|
|
1871
|
+
"p": 63.04,
|
|
1872
|
+
"q": 63.04,
|
|
1873
|
+
"r": 40.72,
|
|
1874
|
+
"s": 56.01,
|
|
1875
|
+
"t": 36.62,
|
|
1876
|
+
"u": 62.26,
|
|
1877
|
+
"v": 59.96,
|
|
1878
|
+
"w": 85.01,
|
|
1879
|
+
"x": 58.01,
|
|
1880
|
+
"y": 60.21,
|
|
1881
|
+
"z": 57.28,
|
|
1882
|
+
"{": 46.88,
|
|
1883
|
+
"|": 37.16,
|
|
1884
|
+
"}": 46.88,
|
|
1885
|
+
"~": 67.87
|
|
1886
|
+
},
|
|
1887
|
+
"800": {
|
|
1888
|
+
"0": 69.19,
|
|
1889
|
+
"1": 44.14,
|
|
1890
|
+
"2": 63.77,
|
|
1891
|
+
"3": 65.67,
|
|
1892
|
+
"4": 68.85,
|
|
1893
|
+
"5": 63.38,
|
|
1894
|
+
"6": 66.16,
|
|
1895
|
+
"7": 58.79,
|
|
1896
|
+
"8": 66.41,
|
|
1897
|
+
"9": 66.16,
|
|
1898
|
+
" ": 21.88,
|
|
1899
|
+
"!": 35.84,
|
|
1900
|
+
'"': 58.64,
|
|
1901
|
+
"#": 65.53,
|
|
1902
|
+
"$": 66.02,
|
|
1903
|
+
"%": 102.93,
|
|
1904
|
+
"&": 68.31,
|
|
1905
|
+
"'": 35.45,
|
|
1906
|
+
"(": 38.23,
|
|
1907
|
+
")": 38.23,
|
|
1908
|
+
"*": 58.25,
|
|
1909
|
+
"+": 68.55,
|
|
1910
|
+
",": 35.25,
|
|
1911
|
+
"-": 47.12,
|
|
1912
|
+
".": 35.25,
|
|
1913
|
+
"/": 39.99,
|
|
1914
|
+
":": 35.25,
|
|
1915
|
+
";": 35.99,
|
|
1916
|
+
"<": 68.55,
|
|
1917
|
+
"=": 68.55,
|
|
1918
|
+
">": 68.55,
|
|
1919
|
+
"?": 57.91,
|
|
1920
|
+
"@": 103.61,
|
|
1921
|
+
"A": 76.95,
|
|
1922
|
+
"B": 66.46,
|
|
1923
|
+
"C": 74.37,
|
|
1924
|
+
"D": 72.27,
|
|
1925
|
+
"E": 60.99,
|
|
1926
|
+
"F": 58.54,
|
|
1927
|
+
"G": 75.24,
|
|
1928
|
+
"H": 74.85,
|
|
1929
|
+
"I": 28.56,
|
|
1930
|
+
"J": 58.98,
|
|
1931
|
+
"K": 73.83,
|
|
1932
|
+
"L": 56.54,
|
|
1933
|
+
"M": 94.34,
|
|
1934
|
+
"N": 76.56,
|
|
1935
|
+
"O": 77.29,
|
|
1936
|
+
"P": 65.19,
|
|
1937
|
+
"Q": 78.17,
|
|
1938
|
+
"R": 66.21,
|
|
1939
|
+
"S": 66.02,
|
|
1940
|
+
"T": 67.68,
|
|
1941
|
+
"U": 72.71,
|
|
1942
|
+
"V": 76.95,
|
|
1943
|
+
"W": 105.86,
|
|
1944
|
+
"X": 76.12,
|
|
1945
|
+
"Y": 75.2,
|
|
1946
|
+
"Z": 67.87,
|
|
1947
|
+
"[": 38.23,
|
|
1948
|
+
"\\": 39.99,
|
|
1949
|
+
"]": 38.23,
|
|
1950
|
+
"^": 49.32,
|
|
1951
|
+
"_": 48.44,
|
|
1952
|
+
"`": 38.23,
|
|
1953
|
+
"a": 58.84,
|
|
1954
|
+
"b": 63.77,
|
|
1955
|
+
"c": 59.52,
|
|
1956
|
+
"d": 63.77,
|
|
1957
|
+
"e": 60.06,
|
|
1958
|
+
"f": 40.97,
|
|
1959
|
+
"g": 63.92,
|
|
1960
|
+
"h": 63.53,
|
|
1961
|
+
"i": 28.32,
|
|
1962
|
+
"j": 28.32,
|
|
1963
|
+
"k": 59.28,
|
|
1964
|
+
"l": 28.32,
|
|
1965
|
+
"m": 92.72,
|
|
1966
|
+
"n": 63.53,
|
|
1967
|
+
"o": 61.91,
|
|
1968
|
+
"p": 63.77,
|
|
1969
|
+
"q": 63.77,
|
|
1970
|
+
"r": 41.99,
|
|
1971
|
+
"s": 57.32,
|
|
1972
|
+
"t": 38.18,
|
|
1973
|
+
"u": 63.53,
|
|
1974
|
+
"v": 61.52,
|
|
1975
|
+
"w": 86.28,
|
|
1976
|
+
"x": 59.42,
|
|
1977
|
+
"y": 61.82,
|
|
1978
|
+
"z": 58.11,
|
|
1979
|
+
"{": 48.63,
|
|
1980
|
+
"|": 38.77,
|
|
1981
|
+
"}": 48.63,
|
|
1982
|
+
"~": 68.55
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
var INTER_FALLBACK = {
|
|
1986
|
+
"400": 56.16,
|
|
1987
|
+
"700": 58.74,
|
|
1988
|
+
"800": 59.79
|
|
1989
|
+
};
|
|
1990
|
+
|
|
1991
|
+
// ../core/src/textFx.ts
|
|
1992
|
+
var clamp013 = (v) => Math.max(0, Math.min(1, v));
|
|
1993
|
+
var fract = (v) => v - Math.floor(v);
|
|
1994
|
+
var rand = (i, salt) => fract(Math.sin(i * 127.1 + salt * 311.7) * 43758.5453);
|
|
1995
|
+
var dur3 = (base, sp) => base / sp;
|
|
1996
|
+
var SCRAMBLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#%&@";
|
|
1997
|
+
var advance = (ch, weight, fontSize) => (INTER_ADVANCE[weight]?.[ch] ?? INTER_FALLBACK[weight]) * (fontSize / 100);
|
|
1998
|
+
function splitText(textStr, opts) {
|
|
1999
|
+
const { id, x, y, fontSize } = opts;
|
|
2000
|
+
const weight = opts.fontWeight ?? 800;
|
|
2001
|
+
const fill = opts.fill ?? "#FFFFFF";
|
|
2002
|
+
const ls = opts.letterSpacing ?? 0;
|
|
2003
|
+
const align = opts.align ?? "center";
|
|
2004
|
+
const unit = opts.unit ?? "glyph";
|
|
2005
|
+
const opacity = opts.opacity ?? 0;
|
|
2006
|
+
const chars = [...textStr];
|
|
2007
|
+
let total = 0;
|
|
2008
|
+
chars.forEach((ch, i) => {
|
|
2009
|
+
total += advance(ch, weight, fontSize) + (i < chars.length - 1 ? ls : 0);
|
|
2010
|
+
});
|
|
2011
|
+
let cursor = align === "center" ? x - total / 2 : x;
|
|
2012
|
+
const glyphs = [];
|
|
2013
|
+
const nodes = [];
|
|
2014
|
+
const mk = (ch, cx, adv, lsProp) => {
|
|
2015
|
+
const g = { id: `${id}-${glyphs.length}`, ch, x: cx, y, advance: adv, i: glyphs.length };
|
|
2016
|
+
glyphs.push(g);
|
|
2017
|
+
nodes.push(
|
|
2018
|
+
text({
|
|
2019
|
+
id: g.id,
|
|
2020
|
+
x: cx,
|
|
2021
|
+
y,
|
|
2022
|
+
content: ch,
|
|
2023
|
+
fontFamily: "Inter",
|
|
2024
|
+
fontSize,
|
|
2025
|
+
fontWeight: weight,
|
|
2026
|
+
fill,
|
|
2027
|
+
anchor: "center",
|
|
2028
|
+
opacity,
|
|
2029
|
+
...lsProp ? { letterSpacing: lsProp } : {}
|
|
2030
|
+
})
|
|
2031
|
+
);
|
|
2032
|
+
};
|
|
2033
|
+
if (unit === "word") {
|
|
2034
|
+
let i = 0;
|
|
2035
|
+
while (i < chars.length) {
|
|
2036
|
+
if (chars[i] === " ") {
|
|
2037
|
+
cursor += advance(" ", weight, fontSize) + ls;
|
|
2038
|
+
i++;
|
|
2039
|
+
continue;
|
|
2040
|
+
}
|
|
2041
|
+
let word = "";
|
|
2042
|
+
let w = 0;
|
|
2043
|
+
const startCursor = cursor;
|
|
2044
|
+
while (i < chars.length && chars[i] !== " ") {
|
|
2045
|
+
const a = advance(chars[i], weight, fontSize);
|
|
2046
|
+
word += chars[i];
|
|
2047
|
+
w += a + (chars[i + 1] && chars[i + 1] !== " " ? ls : 0);
|
|
2048
|
+
i++;
|
|
2049
|
+
}
|
|
2050
|
+
mk(word, startCursor + w / 2, w, ls);
|
|
2051
|
+
cursor = startCursor + w + ls;
|
|
2052
|
+
}
|
|
2053
|
+
} else {
|
|
2054
|
+
chars.forEach((ch) => {
|
|
2055
|
+
const a = advance(ch, weight, fontSize);
|
|
2056
|
+
if (ch !== " ") mk(ch, cursor + a / 2, a);
|
|
2057
|
+
cursor += a + ls;
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
return { nodes, glyphs, ids: glyphs.map((g) => g.id), width: total, x, y, fontSize };
|
|
2061
|
+
}
|
|
2062
|
+
var ctx3 = (o) => ({
|
|
2063
|
+
sp: Math.max(0.25, o.speed ?? 1),
|
|
2064
|
+
e: clamp013(o.energy ?? 0.5),
|
|
2065
|
+
seed: o.seed ?? 0,
|
|
2066
|
+
fs: 0,
|
|
2067
|
+
stag: o.stagger
|
|
2068
|
+
});
|
|
2069
|
+
var IN_STAGGER = { typewriter: 0.065, cascade: 0.04, rise: 0.03, bounce: 0.045, assemble: 0.05, decode: 0.05 };
|
|
2070
|
+
function glyphIn(name, g, c) {
|
|
2071
|
+
const set = (props) => tween(g.id, props, { duration: 1e-3 });
|
|
2072
|
+
const rs = (salt) => rand(g.i, salt + c.seed);
|
|
2073
|
+
switch (name) {
|
|
2074
|
+
case "typewriter":
|
|
2075
|
+
return tween(g.id, { opacity: 1 }, { duration: dur3(0.04, c.sp), ease: "linear" });
|
|
2076
|
+
case "cascade":
|
|
2077
|
+
return seq(
|
|
2078
|
+
set({ y: g.y + 56, opacity: 0 }),
|
|
2079
|
+
par(
|
|
2080
|
+
tween(g.id, { opacity: 1 }, { duration: dur3(0.22, c.sp), ease: "easeOutQuad" }),
|
|
2081
|
+
tween(g.id, { y: g.y }, { duration: dur3(0.34, c.sp), ease: "easeOutCubic" })
|
|
2082
|
+
)
|
|
2083
|
+
);
|
|
2084
|
+
case "rise":
|
|
2085
|
+
return seq(
|
|
2086
|
+
set({ y: g.y + 36, opacity: 0 }),
|
|
2087
|
+
par(
|
|
2088
|
+
tween(g.id, { opacity: 1 }, { duration: dur3(0.3, c.sp), ease: "easeOutQuad" }),
|
|
2089
|
+
tween(g.id, { y: g.y }, { duration: dur3(0.4, c.sp), ease: "easeOutQuad" })
|
|
2090
|
+
)
|
|
2091
|
+
);
|
|
2092
|
+
case "bounce":
|
|
2093
|
+
return seq(
|
|
2094
|
+
set({ y: g.y - 80 * (0.6 + c.e), opacity: 0, scale: 0.7 }),
|
|
2095
|
+
par(
|
|
2096
|
+
tween(g.id, { opacity: 1 }, { duration: dur3(0.2, c.sp), ease: "easeOutQuad" }),
|
|
2097
|
+
tween(g.id, { y: g.y, scale: 1 }, { duration: dur3(0.7, c.sp), ease: "easeOutBounce" })
|
|
2098
|
+
)
|
|
2099
|
+
);
|
|
2100
|
+
case "assemble":
|
|
2101
|
+
return seq(
|
|
2102
|
+
set({ x: g.x + (rs(11) - 0.5) * 1e3 * (0.5 + c.e), y: g.y + (rs(12) - 0.5) * 640, rotation: (rs(13) - 0.5) * 200, scale: 0.4, opacity: 0 }),
|
|
2103
|
+
par(
|
|
2104
|
+
tween(g.id, { opacity: 1 }, { duration: dur3(0.4, c.sp), ease: "easeOutQuad" }),
|
|
2105
|
+
tween(g.id, { x: g.x, y: g.y, rotation: 0, scale: 1 }, { duration: dur3(0.8, c.sp), ease: "easeOutExpo" })
|
|
2106
|
+
)
|
|
2107
|
+
);
|
|
2108
|
+
case "decode": {
|
|
2109
|
+
const steps = 4 + Math.floor(rs(7) * 3);
|
|
2110
|
+
const flicker = [set({ opacity: 1 })];
|
|
2111
|
+
for (let k = 0; k < steps; k++) {
|
|
2112
|
+
flicker.push(tween(g.id, { content: SCRAMBLE[Math.floor(rand(g.i, 20 + k + c.seed) * SCRAMBLE.length)] }, { duration: dur3(0.05, c.sp), ease: "linear" }));
|
|
2113
|
+
}
|
|
2114
|
+
flicker.push(tween(g.id, { content: g.ch }, { duration: dur3(0.05, c.sp), ease: "linear" }));
|
|
2115
|
+
return seq(...flicker);
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
function textIn(name, block, opts = {}) {
|
|
2120
|
+
const c = { ...ctx3(opts), fs: block.fontSize };
|
|
2121
|
+
const interval = (c.stag ?? IN_STAGGER[name]) / c.sp;
|
|
2122
|
+
return beat(opts.label ?? `text-in-${name}`, {}, [stagger(interval, ...block.glyphs.map((g) => glyphIn(name, g, c)))]);
|
|
2123
|
+
}
|
|
2124
|
+
function textLoop(name, block, opts = {}) {
|
|
2125
|
+
const win = { ...opts.from !== void 0 && { from: opts.from }, ...opts.until !== void 0 && { until: opts.until }, ...opts.ramp !== void 0 && { ramp: opts.ramp } };
|
|
2126
|
+
const f = opts.frequency ?? (name === "wave" ? 0.9 : name === "shimmer" ? 1.4 : 0.7);
|
|
2127
|
+
const ps = opts.phaseStep ?? 0.55;
|
|
2128
|
+
return block.glyphs.map((g, i) => {
|
|
2129
|
+
switch (name) {
|
|
2130
|
+
case "wave":
|
|
2131
|
+
return oscillate(g.id, "y", { amplitude: opts.amplitude ?? 9, frequency: f, phase: i * ps }, win);
|
|
2132
|
+
case "shimmer":
|
|
2133
|
+
return oscillate(g.id, "opacity", { amplitude: opts.amplitude ?? 0.25, frequency: f, phase: i * ps }, win);
|
|
2134
|
+
case "wobble":
|
|
2135
|
+
return oscillate(g.id, "rotation", { amplitude: opts.amplitude ?? 6, frequency: f, phase: i * ps }, win);
|
|
2136
|
+
case "float":
|
|
2137
|
+
return oscillate(g.id, "y", { amplitude: opts.amplitude ?? 5, frequency: f, phase: i * ps }, win);
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
var OUT_STAGGER = { shatter: 0.02, fly: 0.012, dissolve: 0, fall: 0.02, collapse: 0.02 };
|
|
2142
|
+
function glyphOut(name, g, c, block, dir) {
|
|
2143
|
+
const rs = (salt) => rand(g.i, salt + c.seed);
|
|
2144
|
+
switch (name) {
|
|
2145
|
+
case "shatter":
|
|
2146
|
+
return par(
|
|
2147
|
+
tween(g.id, { x: g.x + (rs(21) - 0.5) * 1100 * (0.6 + c.e), y: g.y + (rs(22) - 0.5) * 760 }, { duration: dur3(0.7, c.sp), ease: "easeInCubic" }),
|
|
2148
|
+
tween(g.id, { rotation: (rs(23) - 0.5) * 300, opacity: 0 }, { duration: dur3(0.7, c.sp), ease: "easeInQuad" })
|
|
2149
|
+
);
|
|
2150
|
+
case "fly":
|
|
2151
|
+
return par(
|
|
2152
|
+
tween(g.id, { x: g.x + dir[0] * 1200, y: g.y + dir[1] * 1200 }, { duration: dur3(0.6, c.sp), ease: "easeInCubic" }),
|
|
2153
|
+
tween(g.id, { opacity: 0 }, { duration: dur3(0.5, c.sp), ease: "easeInQuad" })
|
|
2154
|
+
);
|
|
2155
|
+
case "dissolve":
|
|
2156
|
+
return seq(wait(rs(31) * 0.5), par(
|
|
2157
|
+
tween(g.id, { opacity: 0 }, { duration: dur3(0.4, c.sp), ease: "easeInQuad" }),
|
|
2158
|
+
tween(g.id, { scale: 1.4 }, { duration: dur3(0.4, c.sp), ease: "easeOutQuad" })
|
|
2159
|
+
));
|
|
2160
|
+
case "fall":
|
|
2161
|
+
return par(
|
|
2162
|
+
tween(g.id, { y: g.y + 700 + rs(41) * 200 }, { duration: dur3(0.8, c.sp), ease: "easeInQuad" }),
|
|
2163
|
+
tween(g.id, { rotation: (rs(42) - 0.5) * 120, opacity: 0 }, { duration: dur3(0.8, c.sp), ease: "easeInQuad" })
|
|
2164
|
+
);
|
|
2165
|
+
case "collapse":
|
|
2166
|
+
return par(
|
|
2167
|
+
tween(g.id, { x: block.x, y: block.y, scale: 0.2 }, { duration: dur3(0.5, c.sp), ease: "easeInBack" }),
|
|
2168
|
+
tween(g.id, { opacity: 0 }, { duration: dur3(0.5, c.sp), ease: "easeInQuad" })
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
function textOut(name, block, opts = {}) {
|
|
2173
|
+
const c = { ...ctx3(opts), fs: block.fontSize };
|
|
2174
|
+
const dir = opts.dir ?? [0, -1];
|
|
2175
|
+
const steps = block.glyphs.map((g) => glyphOut(name, g, c, block, dir));
|
|
2176
|
+
const interval = (c.stag ?? OUT_STAGGER[name]) / c.sp;
|
|
2177
|
+
const body = interval > 0 ? stagger(interval, ...steps) : par(...steps);
|
|
2178
|
+
return beat(opts.label ?? `text-out-${name}`, {}, [body]);
|
|
2179
|
+
}
|
|
2180
|
+
function textTypeCues(block, opts) {
|
|
2181
|
+
const interval = opts.interval ?? 0.065;
|
|
2182
|
+
const gain = opts.gain ?? 0.4;
|
|
2183
|
+
const off = opts.offset ?? 0;
|
|
2184
|
+
const KEYS = ["001", "004", "007", "010", "014"];
|
|
2185
|
+
return block.glyphs.map((g, i) => ({
|
|
2186
|
+
at: opts.at,
|
|
2187
|
+
offset: off + i * interval,
|
|
2188
|
+
file: `keypress-${KEYS[i % KEYS.length]}.wav`,
|
|
2189
|
+
gain: gain + 0.2 * rand(i, 31)
|
|
2190
|
+
}));
|
|
2191
|
+
}
|
|
2192
|
+
|
|
1266
2193
|
// ../core/src/motionOps.ts
|
|
1267
2194
|
var MOTION_OPS = ["rotate", "zoom", "ken-burns", "slide-in", "fade", "draw-on", "pulse"];
|
|
1268
|
-
var
|
|
2195
|
+
var clamp014 = (n3) => Math.max(0, Math.min(1, n3));
|
|
1269
2196
|
function settleEase2(e) {
|
|
1270
2197
|
return e < 0.34 ? "easeOutCubic" : e < 0.67 ? "easeOutBack" : "easeOutElastic";
|
|
1271
2198
|
}
|
|
@@ -1283,7 +2210,7 @@ function fromVec2(from, dist) {
|
|
|
1283
2210
|
}
|
|
1284
2211
|
var motionOpLabel = (name, target) => `op-${name}-${target}`;
|
|
1285
2212
|
function motionOp(name, target, opts = {}) {
|
|
1286
|
-
const e =
|
|
2213
|
+
const e = clamp014(opts.energy ?? 0.5);
|
|
1287
2214
|
const sp = Math.max(0.25, opts.speed ?? 1);
|
|
1288
2215
|
const amt = opts.amount ?? 1;
|
|
1289
2216
|
const b = { scale: 1, x: 0, y: 0, rotation: 0, ...opts.base };
|
|
@@ -1493,8 +2420,8 @@ function valueNoise(x, seed) {
|
|
|
1493
2420
|
const b = hash01(i + 1, seed) * 2 - 1;
|
|
1494
2421
|
return a + (b - a) * u;
|
|
1495
2422
|
}
|
|
1496
|
-
function hash01(
|
|
1497
|
-
let h =
|
|
2423
|
+
function hash01(n3, seed) {
|
|
2424
|
+
let h = n3 * 374761393 + seed * 668265263 | 0;
|
|
1498
2425
|
h = h ^ h >>> 13 | 0;
|
|
1499
2426
|
h = Math.imul(h, 1274126177);
|
|
1500
2427
|
h = (h ^ h >>> 16) >>> 0;
|
|
@@ -1587,8 +2514,8 @@ function isColor(v) {
|
|
|
1587
2514
|
function parseColor(hex) {
|
|
1588
2515
|
let h = hex.slice(1);
|
|
1589
2516
|
if (h.length <= 4) h = [...h].map((c) => c + c).join("");
|
|
1590
|
-
const
|
|
1591
|
-
return [
|
|
2517
|
+
const n3 = parseInt(h.padEnd(8, "f"), 16);
|
|
2518
|
+
return [n3 >>> 24 & 255, n3 >>> 16 & 255, n3 >>> 8 & 255, n3 & 255];
|
|
1592
2519
|
}
|
|
1593
2520
|
function formatColor([r, g, b, a]) {
|
|
1594
2521
|
const hex = (v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0");
|
|
@@ -1608,19 +2535,68 @@ function lerpValue(from, to2, u) {
|
|
|
1608
2535
|
a[3] + (b[3] - a[3]) * u
|
|
1609
2536
|
]);
|
|
1610
2537
|
}
|
|
2538
|
+
if (looksLikePath(from) && looksLikePath(to2)) {
|
|
2539
|
+
const a = tokenizePath(from);
|
|
2540
|
+
const b = tokenizePath(to2);
|
|
2541
|
+
if (a && b && morphCompatible(a, b)) return morphPath(a, b, u);
|
|
2542
|
+
return u < 0.5 ? from : to2;
|
|
2543
|
+
}
|
|
1611
2544
|
return to2;
|
|
1612
2545
|
}
|
|
2546
|
+
var PATH_BODY = /^[\sMmLlHhVvCcSsQqTtAaZz0-9.,eE+-]+$/;
|
|
2547
|
+
function looksLikePath(v) {
|
|
2548
|
+
return typeof v === "string" && /^\s*[Mm]/.test(v) && PATH_BODY.test(v);
|
|
2549
|
+
}
|
|
2550
|
+
var PATH_TOKEN = /([MmLlHhVvCcSsQqTtAaZz])|(-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/g;
|
|
2551
|
+
function tokenizePath(d) {
|
|
2552
|
+
const out = [];
|
|
2553
|
+
let cur = null;
|
|
2554
|
+
let m;
|
|
2555
|
+
PATH_TOKEN.lastIndex = 0;
|
|
2556
|
+
while (m = PATH_TOKEN.exec(d)) {
|
|
2557
|
+
if (m[1]) out.push(cur = { cmd: m[1], nums: [] });
|
|
2558
|
+
else if (m[2]) {
|
|
2559
|
+
if (!cur) return null;
|
|
2560
|
+
cur.nums.push(parseFloat(m[2]));
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
return out.length ? out : null;
|
|
2564
|
+
}
|
|
2565
|
+
function morphCompatible(a, b) {
|
|
2566
|
+
if (a.length !== b.length) return false;
|
|
2567
|
+
for (let i = 0; i < a.length; i++) {
|
|
2568
|
+
const ca = a[i];
|
|
2569
|
+
const cb = b[i];
|
|
2570
|
+
if (ca.cmd !== cb.cmd || ca.nums.length !== cb.nums.length) return false;
|
|
2571
|
+
if (ca.cmd === "A" || ca.cmd === "a") return false;
|
|
2572
|
+
}
|
|
2573
|
+
return true;
|
|
2574
|
+
}
|
|
2575
|
+
var fmtNum = (v) => {
|
|
2576
|
+
const r = Number(v.toFixed(3));
|
|
2577
|
+
return Object.is(r, -0) ? "0" : String(r);
|
|
2578
|
+
};
|
|
2579
|
+
function morphPath(a, b, u) {
|
|
2580
|
+
let s = "";
|
|
2581
|
+
for (let i = 0; i < a.length; i++) {
|
|
2582
|
+
const an = a[i].nums;
|
|
2583
|
+
const bn = b[i].nums;
|
|
2584
|
+
s += (i ? " " : "") + a[i].cmd;
|
|
2585
|
+
for (let j = 0; j < an.length; j++) s += " " + fmtNum(an[j] + (bn[j] - an[j]) * u);
|
|
2586
|
+
}
|
|
2587
|
+
return s;
|
|
2588
|
+
}
|
|
1613
2589
|
|
|
1614
2590
|
// ../core/src/evaluate.ts
|
|
1615
2591
|
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
1616
|
-
function multiply(m,
|
|
2592
|
+
function multiply(m, n3) {
|
|
1617
2593
|
return [
|
|
1618
|
-
m[0] *
|
|
1619
|
-
m[1] *
|
|
1620
|
-
m[0] *
|
|
1621
|
-
m[1] *
|
|
1622
|
-
m[0] *
|
|
1623
|
-
m[1] *
|
|
2594
|
+
m[0] * n3[0] + m[2] * n3[1],
|
|
2595
|
+
m[1] * n3[0] + m[3] * n3[1],
|
|
2596
|
+
m[0] * n3[2] + m[2] * n3[3],
|
|
2597
|
+
m[1] * n3[2] + m[3] * n3[3],
|
|
2598
|
+
m[0] * n3[4] + m[2] * n3[5] + m[4],
|
|
2599
|
+
m[1] * n3[4] + m[3] * n3[5] + m[5]
|
|
1624
2600
|
];
|
|
1625
2601
|
}
|
|
1626
2602
|
function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg = 0, skewYDeg = 0) {
|
|
@@ -1635,9 +2611,9 @@ function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg
|
|
|
1635
2611
|
const tx = Math.tan(skewXDeg * Math.PI / 180);
|
|
1636
2612
|
const ty = Math.tan(skewYDeg * Math.PI / 180);
|
|
1637
2613
|
const R = [c, s, -s, c, 0, 0];
|
|
1638
|
-
const
|
|
2614
|
+
const K3 = [1, ty, tx, 1, 0, 0];
|
|
1639
2615
|
const S = [scale * scaleX, 0, 0, scale * scaleY, 0, 0];
|
|
1640
|
-
const m = multiply(R, multiply(
|
|
2616
|
+
const m = multiply(R, multiply(K3, S));
|
|
1641
2617
|
return [m[0], m[1], m[2], m[3], x, y];
|
|
1642
2618
|
}
|
|
1643
2619
|
var ANCHOR_FACTORS = {
|
|
@@ -1937,29 +2913,29 @@ function sketchToTimeline(sketch, nodeIds) {
|
|
|
1937
2913
|
const steps = [];
|
|
1938
2914
|
events.forEach((ev, i) => {
|
|
1939
2915
|
const node = nodeIds[i % nodeIds.length];
|
|
1940
|
-
const
|
|
2916
|
+
const dur4 = Math.max(0.05, ev.t1 - ev.t0);
|
|
1941
2917
|
const ease = easeFor(ev.easing);
|
|
1942
2918
|
let motion;
|
|
1943
2919
|
switch (ev.kind) {
|
|
1944
2920
|
case "enter":
|
|
1945
|
-
motion = tween(node, { opacity: 1 }, { duration:
|
|
2921
|
+
motion = tween(node, { opacity: 1 }, { duration: dur4, ease });
|
|
1946
2922
|
break;
|
|
1947
2923
|
case "exit":
|
|
1948
|
-
motion = tween(node, { opacity: 0 }, { duration:
|
|
2924
|
+
motion = tween(node, { opacity: 0 }, { duration: dur4, ease });
|
|
1949
2925
|
break;
|
|
1950
2926
|
case "emphasis": {
|
|
1951
2927
|
const peak = 1 + Math.max(0.08, Math.min(0.5, ev.magnitude));
|
|
1952
2928
|
motion = seq(
|
|
1953
|
-
tween(node, { scale: peak }, { duration:
|
|
1954
|
-
tween(node, { scale: 1 }, { duration:
|
|
2929
|
+
tween(node, { scale: peak }, { duration: dur4 / 2, ease: "easeOutCubic" }),
|
|
2930
|
+
tween(node, { scale: 1 }, { duration: dur4 / 2, ease: "easeInOutQuad" })
|
|
1955
2931
|
);
|
|
1956
2932
|
break;
|
|
1957
2933
|
}
|
|
1958
2934
|
case "scale":
|
|
1959
|
-
motion = tween(node, { scale: 1 + Math.max(-0.5, Math.min(0.5, ev.magnitude)) }, { duration:
|
|
2935
|
+
motion = tween(node, { scale: 1 + Math.max(-0.5, Math.min(0.5, ev.magnitude)) }, { duration: dur4, ease });
|
|
1960
2936
|
break;
|
|
1961
2937
|
case "move":
|
|
1962
|
-
motion = tween(node, { opacity: 1 }, { duration:
|
|
2938
|
+
motion = tween(node, { opacity: 1 }, { duration: dur4, ease });
|
|
1963
2939
|
break;
|
|
1964
2940
|
}
|
|
1965
2941
|
steps.push(ev.t0 > 0 ? seq(wait(ev.t0), motion) : motion);
|
|
@@ -1967,6 +2943,7 @@ function sketchToTimeline(sketch, nodeIds) {
|
|
|
1967
2943
|
return par(...steps);
|
|
1968
2944
|
}
|
|
1969
2945
|
export {
|
|
2946
|
+
CHARACTER_PRESET_NAMES,
|
|
1970
2947
|
DEFAULT_CROSSFADE,
|
|
1971
2948
|
DEFAULT_FPS,
|
|
1972
2949
|
DEFAULT_MOTIONPATH_DURATION,
|
|
@@ -1980,6 +2957,7 @@ export {
|
|
|
1980
2957
|
SFX_DURATION,
|
|
1981
2958
|
SceneValidationError,
|
|
1982
2959
|
beat,
|
|
2960
|
+
characterPreset,
|
|
1983
2961
|
collectImageSrcs,
|
|
1984
2962
|
compileComposition,
|
|
1985
2963
|
compileScene,
|
|
@@ -1991,8 +2969,11 @@ export {
|
|
|
1991
2969
|
deviceScreenCenter,
|
|
1992
2970
|
ellipse,
|
|
1993
2971
|
evaluate,
|
|
2972
|
+
figure,
|
|
1994
2973
|
formatComposeReport,
|
|
1995
2974
|
group,
|
|
2975
|
+
humanoid,
|
|
2976
|
+
ikReach,
|
|
1996
2977
|
image,
|
|
1997
2978
|
isColor,
|
|
1998
2979
|
lerpValue,
|
|
@@ -2003,21 +2984,30 @@ export {
|
|
|
2003
2984
|
motionPreset,
|
|
2004
2985
|
nodeParentMatrix,
|
|
2005
2986
|
oscillate,
|
|
2987
|
+
ovalPath,
|
|
2006
2988
|
par,
|
|
2007
2989
|
path,
|
|
2008
2990
|
pathPoint,
|
|
2009
2991
|
pathTangentAngle,
|
|
2992
|
+
poseTo,
|
|
2010
2993
|
rect,
|
|
2011
2994
|
resolveAudioPlan,
|
|
2012
2995
|
resolveCompositionAudioPlan,
|
|
2013
2996
|
resolveEase,
|
|
2997
|
+
rig,
|
|
2998
|
+
rigPose,
|
|
2014
2999
|
sampleBehavior,
|
|
2015
3000
|
sampleProp,
|
|
2016
3001
|
scene,
|
|
2017
3002
|
seq,
|
|
2018
3003
|
sketchToTimeline,
|
|
3004
|
+
splitText,
|
|
2019
3005
|
stagger,
|
|
2020
3006
|
text,
|
|
3007
|
+
textIn,
|
|
3008
|
+
textLoop,
|
|
3009
|
+
textOut,
|
|
3010
|
+
textTypeCues,
|
|
2021
3011
|
to,
|
|
2022
3012
|
tween,
|
|
2023
3013
|
validateComposition,
|