reframe-video 0.1.3 → 0.3.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.
Files changed (50) hide show
  1. package/assets/sfx/LICENSE.md +2 -1
  2. package/assets/sfx/bong_001.ogg +0 -0
  3. package/assets/sfx/click_001.ogg +0 -0
  4. package/assets/sfx/confirmation_002.ogg +0 -0
  5. package/assets/sfx/confirmation_003.ogg +0 -0
  6. package/assets/sfx/confirmation_004.ogg +0 -0
  7. package/assets/sfx/footstep_001.ogg +0 -0
  8. package/assets/sfx/footstep_002.ogg +0 -0
  9. package/assets/sfx/footstep_003.ogg +0 -0
  10. package/assets/sfx/glass_001.ogg +0 -0
  11. package/assets/sfx/maximize_001.ogg +0 -0
  12. package/assets/sfx/maximize_002.ogg +0 -0
  13. package/assets/sfx/maximize_005.ogg +0 -0
  14. package/assets/sfx/maximize_009.ogg +0 -0
  15. package/assets/sfx/open_001.ogg +0 -0
  16. package/assets/sfx/pluck_001.ogg +0 -0
  17. package/assets/sfx/pluck_002.ogg +0 -0
  18. package/assets/sfx/select_001.ogg +0 -0
  19. package/assets/sfx/select_002.ogg +0 -0
  20. package/assets/sfx/select_003.ogg +0 -0
  21. package/dist/bin.js +271 -49
  22. package/dist/browserEntry.js +179 -68
  23. package/dist/cli.js +445 -85
  24. package/dist/index.js +1187 -116
  25. package/dist/labels.js +606 -0
  26. package/dist/renderer-canvas.js +15 -0
  27. package/dist/trace-cli.js +9 -9
  28. package/dist/types/audio.d.ts +9 -0
  29. package/dist/types/characterPreset.d.ts +39 -0
  30. package/dist/types/compile.d.ts +1 -0
  31. package/dist/types/compose.d.ts +18 -2
  32. package/dist/types/composeComposition.d.ts +27 -0
  33. package/dist/types/devicePreset.d.ts +65 -0
  34. package/dist/types/dsl.d.ts +12 -1
  35. package/dist/types/evaluate.d.ts +32 -0
  36. package/dist/types/figure.d.ts +32 -0
  37. package/dist/types/index.d.ts +9 -3
  38. package/dist/types/interpolate.d.ts +3 -2
  39. package/dist/types/ir.d.ts +68 -0
  40. package/dist/types/motionOps.d.ts +36 -0
  41. package/dist/types/path.d.ts +7 -3
  42. package/dist/types/rig.d.ts +87 -0
  43. package/dist/types/validate.d.ts +4 -1
  44. package/guides/edsl-guide.md +54 -1
  45. package/guides/regen-contract.md +11 -0
  46. package/package.json +1 -1
  47. package/preview/index.html +56 -3
  48. package/preview/src/main.ts +1132 -46
  49. package/preview/src/panel.ts +478 -8
  50. package/preview/src/store.ts +323 -6
@@ -27,7 +27,7 @@
27
27
  if (n < 2) return 0;
28
28
  return closed ? n : n - 1;
29
29
  }
30
- function pathPoint(points, closed, u) {
30
+ function pathPoint(points, closed, u, curviness = 1) {
31
31
  const n = points.length;
32
32
  if (n === 0) return [0, 0];
33
33
  if (n === 1) return [points[0][0], points[0][1]];
@@ -36,19 +36,41 @@
36
36
  const [p0, p1, p2, p3] = controls(points, closed, i);
37
37
  const t2 = t * t;
38
38
  const t3 = t2 * t;
39
- 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);
40
- return [f(p0[0], p1[0], p2[0], p3[0]), f(p0[1], p1[1], p2[1], p3[1])];
39
+ if (curviness === 1) {
40
+ 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);
41
+ return [f(p0[0], p1[0], p2[0], p3[0]), f(p0[1], p1[1], p2[1], p3[1])];
42
+ }
43
+ const h00 = 2 * t3 - 3 * t2 + 1;
44
+ const h10 = t3 - 2 * t2 + t;
45
+ const h01 = -2 * t3 + 3 * t2;
46
+ const h11 = t3 - t2;
47
+ const k = curviness * 0.5;
48
+ const H = (a, b, c, d) => h00 * b + h10 * k * (c - a) + h01 * c + h11 * k * (d - b);
49
+ return [H(p0[0], p1[0], p2[0], p3[0]), H(p0[1], p1[1], p2[1], p3[1])];
41
50
  }
42
- function pathTangentAngle(points, closed, u) {
51
+ function pathTangentAngle(points, closed, u, curviness = 1) {
43
52
  const n = points.length;
44
53
  if (n < 2) return 0;
45
54
  const segs = segCountOf(points, closed);
46
55
  const { i, t } = locate(segs, u);
47
56
  const [p0, p1, p2, p3] = controls(points, closed, i);
48
57
  const t2 = t * t;
49
- 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);
50
- const dx = d(p0[0], p1[0], p2[0], p3[0]);
51
- const dy = d(p0[1], p1[1], p2[1], p3[1]);
58
+ let dx;
59
+ let dy;
60
+ if (curviness === 1) {
61
+ 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);
62
+ dx = d(p0[0], p1[0], p2[0], p3[0]);
63
+ dy = d(p0[1], p1[1], p2[1], p3[1]);
64
+ } else {
65
+ const g00 = 6 * t2 - 6 * t;
66
+ const g10 = 3 * t2 - 4 * t + 1;
67
+ const g01 = -6 * t2 + 6 * t;
68
+ const g11 = 3 * t2 - 2 * t;
69
+ const k = curviness * 0.5;
70
+ const D = (a, b, c, e) => g00 * b + g10 * k * (c - a) + g01 * c + g11 * k * (e - b);
71
+ dx = D(p0[0], p1[0], p2[0], p3[0]);
72
+ dy = D(p0[1], p1[1], p2[1], p3[1]);
73
+ }
52
74
  if (dx === 0 && dy === 0) return 0;
53
75
  return Math.atan2(dy, dx) * 180 / Math.PI;
54
76
  }
@@ -125,8 +147,8 @@
125
147
  const currentValue = (target, prop) => {
126
148
  const v = current.get(key(target, prop));
127
149
  if (v !== void 0) return v;
128
- if (prop === "opacity" || prop === "scale" || prop === "progress") return 1;
129
- if (prop === "rotation") return 0;
150
+ if (prop === "opacity" || prop === "scale" || prop === "progress" || prop === "scaleX" || prop === "scaleY") return 1;
151
+ if (prop === "rotation" || prop === "skewX" || prop === "skewY") return 0;
130
152
  throw new Error(`cannot animate "${prop}" of "${target}": no base value to start from`);
131
153
  };
132
154
  const labelTimes = /* @__PURE__ */ new Map();
@@ -229,16 +251,17 @@
229
251
  const duration = tl.duration ?? DEFAULT_MOTIONPATH_DURATION;
230
252
  const points = tl.points;
231
253
  const closed = tl.closed ?? false;
254
+ const curviness = tl.curviness ?? 1;
232
255
  const autoRotate = tl.autoRotate ?? false;
233
256
  const rotateOffset = tl.rotateOffset ?? 0;
234
257
  let list = motionPaths.get(tl.target);
235
258
  if (!list) motionPaths.set(tl.target, list = []);
236
- list.push({ t0: start, t1: start + duration, points, closed, autoRotate, rotateOffset, ...tl.ease !== void 0 && { ease: tl.ease } });
259
+ list.push({ t0: start, t1: start + duration, points, closed, curviness, autoRotate, rotateOffset, ...tl.ease !== void 0 && { ease: tl.ease } });
237
260
  if (points.length > 0) {
238
- const [ex, ey] = pathPoint(points, closed, 1);
261
+ const [ex, ey] = pathPoint(points, closed, 1, curviness);
239
262
  current.set(key(tl.target, "x"), ex);
240
263
  current.set(key(tl.target, "y"), ey);
241
- if (autoRotate) current.set(key(tl.target, "rotation"), pathTangentAngle(points, closed, 1) + rotateOffset);
264
+ if (autoRotate) current.set(key(tl.target, "rotation"), pathTangentAngle(points, closed, 1, curviness) + rotateOffset);
242
265
  }
243
266
  return start + duration;
244
267
  }
@@ -285,7 +308,7 @@
285
308
  }
286
309
 
287
310
  // ../core/src/validate.ts
288
- var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "anchor"];
311
+ var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "anchor"];
289
312
  var PROPS_BY_TYPE = {
290
313
  rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
291
314
  ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
@@ -435,8 +458,57 @@
435
458
  a[3] + (b[3] - a[3]) * u
436
459
  ]);
437
460
  }
461
+ if (looksLikePath(from) && looksLikePath(to)) {
462
+ const a = tokenizePath(from);
463
+ const b = tokenizePath(to);
464
+ if (a && b && morphCompatible(a, b)) return morphPath(a, b, u);
465
+ return u < 0.5 ? from : to;
466
+ }
438
467
  return to;
439
468
  }
469
+ var PATH_BODY = /^[\sMmLlHhVvCcSsQqTtAaZz0-9.,eE+-]+$/;
470
+ function looksLikePath(v) {
471
+ return typeof v === "string" && /^\s*[Mm]/.test(v) && PATH_BODY.test(v);
472
+ }
473
+ var PATH_TOKEN = /([MmLlHhVvCcSsQqTtAaZz])|(-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?)/g;
474
+ function tokenizePath(d) {
475
+ const out = [];
476
+ let cur = null;
477
+ let m;
478
+ PATH_TOKEN.lastIndex = 0;
479
+ while (m = PATH_TOKEN.exec(d)) {
480
+ if (m[1]) out.push(cur = { cmd: m[1], nums: [] });
481
+ else if (m[2]) {
482
+ if (!cur) return null;
483
+ cur.nums.push(parseFloat(m[2]));
484
+ }
485
+ }
486
+ return out.length ? out : null;
487
+ }
488
+ function morphCompatible(a, b) {
489
+ if (a.length !== b.length) return false;
490
+ for (let i = 0; i < a.length; i++) {
491
+ const ca = a[i];
492
+ const cb = b[i];
493
+ if (ca.cmd !== cb.cmd || ca.nums.length !== cb.nums.length) return false;
494
+ if (ca.cmd === "A" || ca.cmd === "a") return false;
495
+ }
496
+ return true;
497
+ }
498
+ var fmtNum = (v) => {
499
+ const r = Number(v.toFixed(3));
500
+ return Object.is(r, -0) ? "0" : String(r);
501
+ };
502
+ function morphPath(a, b, u) {
503
+ let s = "";
504
+ for (let i = 0; i < a.length; i++) {
505
+ const an = a[i].nums;
506
+ const bn = b[i].nums;
507
+ s += (i ? " " : "") + a[i].cmd;
508
+ for (let j = 0; j < an.length; j++) s += " " + fmtNum(an[j] + (bn[j] - an[j]) * u);
509
+ }
510
+ return s;
511
+ }
440
512
 
441
513
  // ../core/src/evaluate.ts
442
514
  var IDENTITY = [1, 0, 0, 1, 0, 0];
@@ -450,11 +522,22 @@
450
522
  m[1] * n[4] + m[3] * n[5] + m[5]
451
523
  ];
452
524
  }
453
- function localMatrix(x, y, rotationDeg, scale) {
525
+ function localMatrix(x, y, rotationDeg, scale, scaleX = 1, scaleY = 1, skewXDeg = 0, skewYDeg = 0) {
454
526
  const r = rotationDeg * Math.PI / 180;
455
- const cos = Math.cos(r) * scale;
456
- const sin = Math.sin(r) * scale;
457
- return [cos, sin, -sin, cos, x, y];
527
+ if (scaleX === 1 && scaleY === 1 && skewXDeg === 0 && skewYDeg === 0) {
528
+ const cos = Math.cos(r) * scale;
529
+ const sin = Math.sin(r) * scale;
530
+ return [cos, sin, -sin, cos, x, y];
531
+ }
532
+ const c = Math.cos(r);
533
+ const s = Math.sin(r);
534
+ const tx = Math.tan(skewXDeg * Math.PI / 180);
535
+ const ty = Math.tan(skewYDeg * Math.PI / 180);
536
+ const R = [c, s, -s, c, 0, 0];
537
+ const K = [1, ty, tx, 1, 0, 0];
538
+ const S = [scale * scaleX, 0, 0, scale * scaleY, 0, 0];
539
+ const m = multiply(R, multiply(K, S));
540
+ return [m[0], m[1], m[2], m[3], x, y];
458
541
  }
459
542
  var ANCHOR_FACTORS = {
460
543
  "top-left": [0, 0],
@@ -479,53 +562,54 @@
479
562
  if (Number.isFinite(until) && ramp > 0) envelope = Math.min(envelope, (until - t) / ramp);
480
563
  return Math.max(0, Math.min(1, envelope));
481
564
  }
482
- function evaluate(compiled2, t) {
483
- const ops = [];
484
- const valueAt = (target, prop, fallback) => {
485
- let value = compiled2.initialValues.get(`${target}.${prop}`) ?? fallback;
486
- let segStart = Number.NEGATIVE_INFINITY;
487
- const segs = compiled2.segments.get(`${target}.${prop}`);
488
- if (segs) {
565
+ function sampleProp(compiled2, t, target, prop, fallback) {
566
+ let value = compiled2.initialValues.get(`${target}.${prop}`) ?? fallback;
567
+ let segStart = Number.NEGATIVE_INFINITY;
568
+ const segs = compiled2.segments.get(`${target}.${prop}`);
569
+ if (segs) {
570
+ let active;
571
+ for (const seg of segs) {
572
+ if (seg.t0 <= t) active = seg;
573
+ else break;
574
+ }
575
+ if (active) {
576
+ segStart = active.t0;
577
+ if (t >= active.t1) {
578
+ value = active.to;
579
+ } else {
580
+ const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
581
+ value = lerpValue(active.from, active.to, u);
582
+ }
583
+ }
584
+ }
585
+ if (prop === "x" || prop === "y" || prop === "rotation") {
586
+ const drivers = compiled2.motionPaths.get(target);
587
+ if (drivers) {
489
588
  let active;
490
- for (const seg of segs) {
491
- if (seg.t0 <= t) active = seg;
589
+ for (const d of drivers) {
590
+ if (d.t0 <= t) active = d;
492
591
  else break;
493
592
  }
494
- if (active) {
495
- segStart = active.t0;
496
- if (t >= active.t1) {
497
- value = active.to;
498
- } else {
499
- const u = resolveEase(active.ease)((t - active.t0) / (active.t1 - active.t0));
500
- value = lerpValue(active.from, active.to, u);
501
- }
502
- }
503
- }
504
- if (prop === "x" || prop === "y" || prop === "rotation") {
505
- const drivers = compiled2.motionPaths.get(target);
506
- if (drivers) {
507
- let active;
508
- for (const d of drivers) {
509
- if (d.t0 <= t) active = d;
510
- else break;
511
- }
512
- if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
513
- const span = active.t1 - active.t0;
514
- const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
515
- if (prop === "x") value = pathPoint(active.points, active.closed, u)[0];
516
- else if (prop === "y") value = pathPoint(active.points, active.closed, u)[1];
517
- else value = pathTangentAngle(active.points, active.closed, u) + active.rotateOffset;
518
- }
593
+ if (active && active.t0 >= segStart && (prop !== "rotation" || active.autoRotate) && active.points.length > 0) {
594
+ const span = active.t1 - active.t0;
595
+ const u = span <= 0 ? 1 : resolveEase(active.ease)(Math.max(0, Math.min(1, (t - active.t0) / span)));
596
+ if (prop === "x") value = pathPoint(active.points, active.closed, u, active.curviness)[0];
597
+ else if (prop === "y") value = pathPoint(active.points, active.closed, u, active.curviness)[1];
598
+ else value = pathTangentAngle(active.points, active.closed, u, active.curviness) + active.rotateOffset;
519
599
  }
520
600
  }
521
- for (const b of compiled2.ir.behaviors ?? []) {
522
- if (b.target === target && b.prop === prop && typeof value === "number") {
523
- const envelope = behaviorEnvelope(b, t);
524
- if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
525
- }
601
+ }
602
+ for (const b of compiled2.ir.behaviors ?? []) {
603
+ if (b.target === target && b.prop === prop && typeof value === "number") {
604
+ const envelope = behaviorEnvelope(b, t);
605
+ if (envelope > 0) value = value + envelope * sampleBehavior(b.behavior, t);
526
606
  }
527
- return value;
528
- };
607
+ }
608
+ return value;
609
+ }
610
+ function evaluate(compiled2, t) {
611
+ const ops = [];
612
+ const valueAt = (target, prop, fallback) => sampleProp(compiled2, t, target, prop, fallback);
529
613
  const num = (target, prop, fallback) => {
530
614
  const v = valueAt(target, prop, fallback);
531
615
  return typeof v === "number" ? v : fallback;
@@ -538,8 +622,9 @@
538
622
  const v = valueAt(target, prop, base ?? "");
539
623
  return v === "" && base === void 0 ? void 0 : String(v);
540
624
  };
541
- const walk = (node, parent, parentOpacity) => {
625
+ const walk = (node, parent, parentOpacity, clips) => {
542
626
  const id = node.id;
627
+ const clipSpread = clips.length > 0 ? { clips } : void 0;
543
628
  if (node.type === "line") {
544
629
  const opacity2 = parentOpacity * num(id, "opacity", node.props.opacity ?? 1);
545
630
  if (opacity2 <= 0) return;
@@ -556,7 +641,8 @@
556
641
  x2: x1 + (num(id, "x2", node.props.x2) - x1) * progress,
557
642
  y2: y1 + (num(id, "y2", node.props.y2) - y1) * progress,
558
643
  stroke: str(id, "stroke", node.props.stroke),
559
- strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1)
644
+ strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1),
645
+ ...clipSpread
560
646
  });
561
647
  return;
562
648
  }
@@ -568,13 +654,19 @@
568
654
  num(id, "x", node.props.x),
569
655
  num(id, "y", node.props.y),
570
656
  num(id, "rotation", node.props.rotation ?? 0),
571
- num(id, "scale", node.props.scale ?? 1)
657
+ num(id, "scale", node.props.scale ?? 1),
658
+ num(id, "scaleX", node.props.scaleX ?? 1),
659
+ num(id, "scaleY", node.props.scaleY ?? 1),
660
+ num(id, "skewX", node.props.skewX ?? 0),
661
+ num(id, "skewY", node.props.skewY ?? 0)
572
662
  )
573
663
  );
574
664
  switch (node.type) {
575
- case "group":
576
- for (const child of node.children) walk(child, matrix, opacity);
665
+ case "group": {
666
+ const childClips = node.props.clip ? [...clips, { transform: matrix, shape: node.props.clip }] : clips;
667
+ for (const child of node.children) walk(child, matrix, opacity, childClips);
577
668
  return;
669
+ }
578
670
  case "rect":
579
671
  case "ellipse": {
580
672
  const width = num(id, "width", node.props.width);
@@ -594,7 +686,8 @@
594
686
  offsetY: -height * ay,
595
687
  ...fill !== void 0 && { fill },
596
688
  ...stroke !== void 0 && { stroke, strokeWidth },
597
- ...node.type === "rect" && { radius: num(id, "radius", node.props.radius ?? 0) }
689
+ ...node.type === "rect" && { radius: num(id, "radius", node.props.radius ?? 0) },
690
+ ...clipSpread
598
691
  });
599
692
  return;
600
693
  }
@@ -611,7 +704,8 @@
611
704
  width,
612
705
  height,
613
706
  offsetX: -width * ax,
614
- offsetY: -height * ay
707
+ offsetY: -height * ay,
708
+ ...clipSpread
615
709
  });
616
710
  return;
617
711
  }
@@ -628,7 +722,8 @@
628
722
  d: str(id, "d", node.props.d),
629
723
  progress: Math.max(0, Math.min(1, num(id, "progress", node.props.progress ?? 1))),
630
724
  ...fill !== void 0 && { fill },
631
- ...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) }
725
+ ...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) },
726
+ ...clipSpread
632
727
  });
633
728
  return;
634
729
  }
@@ -651,13 +746,14 @@
651
746
  fill: str(id, "fill", node.props.fill ?? "#ffffff"),
652
747
  letterSpacing: num(id, "letterSpacing", node.props.letterSpacing ?? 0),
653
748
  align: TEXT_ALIGN[ax] ?? "left",
654
- baseline: TEXT_BASELINE[ay] ?? "top"
749
+ baseline: TEXT_BASELINE[ay] ?? "top",
750
+ ...clipSpread
655
751
  });
656
752
  return;
657
753
  }
658
754
  }
659
755
  };
660
- for (const node of compiled2.ir.nodes) walk(node, IDENTITY, 1);
756
+ for (const node of compiled2.ir.nodes) walk(node, IDENTITY, 1, []);
661
757
  return ops;
662
758
  }
663
759
 
@@ -675,6 +771,21 @@
675
771
  function drawDisplayList(ctx2, ops, images2) {
676
772
  for (const op of ops) {
677
773
  ctx2.save();
774
+ if (op.clips) {
775
+ for (const clip of op.clips) {
776
+ ctx2.setTransform(...clip.transform);
777
+ ctx2.beginPath();
778
+ const { shape } = clip;
779
+ if (shape.kind === "ellipse") {
780
+ ctx2.ellipse(shape.x + shape.width / 2, shape.y + shape.height / 2, Math.abs(shape.width / 2), Math.abs(shape.height / 2), 0, 0, Math.PI * 2);
781
+ } else if (shape.radius && shape.radius > 0) {
782
+ ctx2.roundRect(shape.x, shape.y, shape.width, shape.height, shape.radius);
783
+ } else {
784
+ ctx2.rect(shape.x, shape.y, shape.width, shape.height);
785
+ }
786
+ ctx2.clip();
787
+ }
788
+ }
678
789
  ctx2.setTransform(...op.transform);
679
790
  ctx2.globalAlpha = Math.max(0, Math.min(1, op.opacity));
680
791
  switch (op.type) {