@ikijs/editor 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -36,6 +36,8 @@ __export(index_exports, {
36
36
  LIP_INSIDE_ROLES: () => LIP_INSIDE_ROLES,
37
37
  LIP_ROLES: () => LIP_ROLES,
38
38
  LayerGeometryError: () => LayerGeometryError,
39
+ PatchError: () => PatchError,
40
+ SHUT_BY: () => SHUT_BY,
39
41
  SPECK_CORE_FRACTION: () => SPECK_CORE_FRACTION,
40
42
  SetDeformerBindings: () => SetDeformerBindings,
41
43
  SetDeformerParent: () => SetDeformerParent,
@@ -1560,8 +1562,8 @@ function foregroundSpan(mask, width, height, rowLo, rowHi) {
1560
1562
  }
1561
1563
  return { left, right };
1562
1564
  }
1563
- function headHalfOf(span) {
1564
- return (span.right - span.left + 1) / 2;
1565
+ function headHalfOf(span2) {
1566
+ return (span2.right - span2.left + 1) / 2;
1565
1567
  }
1566
1568
  var DARK_SHARE = 0.55;
1567
1569
  function jawRowsOf(rgba, canvasW, bbox, rowLeft, rowRight) {
@@ -1571,9 +1573,9 @@ function jawRowsOf(rgba, canvasW, bbox, rowLeft, rowRight) {
1571
1573
  let widest = bbox.y;
1572
1574
  let widestSpan = -1;
1573
1575
  for (let y = bbox.y; y < bbox.y + bbox.h; y++) {
1574
- const span = rowRight[y] - rowLeft[y];
1575
- if (span >= widestSpan) {
1576
- widestSpan = span;
1576
+ const span2 = rowRight[y] - rowLeft[y];
1577
+ if (span2 >= widestSpan) {
1578
+ widestSpan = span2;
1577
1579
  widest = y;
1578
1580
  }
1579
1581
  for (let x = bbox.x; x < bbox.x + bbox.w; x++) {
@@ -1742,14 +1744,14 @@ function createLayerSetMeasurer(canvas) {
1742
1744
  }
1743
1745
  function finish() {
1744
1746
  const eyeRow = eyeBandRowOf(layerInputs);
1745
- const span = foregroundSpan(
1747
+ const span2 = foregroundSpan(
1746
1748
  opaque,
1747
1749
  canvasW,
1748
1750
  canvasH,
1749
1751
  eyeRow - HEAD_BAND,
1750
1752
  eyeRow + HEAD_BAND
1751
1753
  );
1752
- const headHalfWidth = span.right > span.left ? headHalfOf(span) : void 0;
1754
+ const headHalfWidth = span2.right > span2.left ? headHalfOf(span2) : void 0;
1753
1755
  const headHalfWidthApplied = headHalfWidth !== void 0 && headHalfWidth > facePlateHalfOf(layerInputs);
1754
1756
  let headEdges;
1755
1757
  if (headHalfWidthApplied) {
@@ -1777,9 +1779,9 @@ function createLayerSetMeasurer(canvas) {
1777
1779
  const centre = iris.bbox.x + iris.bbox.w / 2;
1778
1780
  const otherX = other.bbox.x + other.bbox.w / 2 - half;
1779
1781
  const c = side < 0 ? Math.ceil(centre) - 1 : Math.floor(centre);
1780
- const span2 = rowSpansByRole.find((s) => s.role === iris.role);
1781
- if (span2.rowRight[r] < span2.rowLeft[r]) return void 0;
1782
- const minRun = STRAND_MIN_RUN_FRACTION * (span2.rowRight[r] + 1 - span2.rowLeft[r]);
1782
+ const span3 = rowSpansByRole.find((s) => s.role === iris.role);
1783
+ if (span3.rowRight[r] < span3.rowLeft[r]) return void 0;
1784
+ const minRun = STRAND_MIN_RUN_FRACTION * (span3.rowRight[r] + 1 - span3.rowLeft[r]);
1783
1785
  const strand = new Uint8Array(canvasW);
1784
1786
  const runs = r >= hairTop && r < hairTop + hairRuns.length ? hairRuns[r - hairTop] : [];
1785
1787
  for (let k = 0; k < runs.length; k += 2) {
@@ -1804,8 +1806,8 @@ function createLayerSetMeasurer(canvas) {
1804
1806
  while (strandAt(x)) x += side;
1805
1807
  return {
1806
1808
  y: canvasH / 2 - (r + 0.5),
1807
- irisOuter: (side < 0 ? span2.rowLeft[r] : span2.rowRight[r] + 1) - half,
1808
- irisInner: (side < 0 ? span2.rowRight[r] + 1 : span2.rowLeft[r]) - half,
1809
+ irisOuter: (side < 0 ? span3.rowLeft[r] : span3.rowRight[r] + 1) - half,
1810
+ irisInner: (side < 0 ? span3.rowRight[r] + 1 : span3.rowLeft[r]) - half,
1809
1811
  runOuter: outerBoundary(x - side),
1810
1812
  runFace
1811
1813
  };
@@ -2209,6 +2211,12 @@ var DEFAULT_TURN_TARGETS = Object.freeze({
2209
2211
  farEyeRatio: round2(TURN.eyeFarScale / TURN.eyeNearScale),
2210
2212
  silhouetteRatio: 1
2211
2213
  });
2214
+ var PatchError = class extends Error {
2215
+ constructor(message) {
2216
+ super(message);
2217
+ this.name = "PatchError";
2218
+ }
2219
+ };
2212
2220
 
2213
2221
  // src/auto-rig/arms.ts
2214
2222
  var import_format5 = require("@ikijs/format");
@@ -2834,7 +2842,7 @@ var ARM_IDS = {
2834
2842
  };
2835
2843
  function endPivot(layer, end) {
2836
2844
  const { bbox, canvasW, canvasH, rowRuns } = layer;
2837
- const span = runSpan(layer);
2845
+ const span2 = runSpan(layer);
2838
2846
  const from = (k) => end === "top" ? k : bbox.h - 1 - k;
2839
2847
  const painted = rowRuns?.flatMap((runs, k) => runs.length > 0 ? [k] : []) ?? [];
2840
2848
  const firstK = end === "top" ? painted[0] ?? 0 : painted.at(-1) ?? bbox.h - 1;
@@ -2842,13 +2850,13 @@ function endPivot(layer, end) {
2842
2850
  const hi = Math.max(lo, Math.floor(CAP_ROWS[1] * bbox.h));
2843
2851
  const widths = [];
2844
2852
  for (let k = lo; k <= hi; k++) {
2845
- const [s2, e2] = span(from(k));
2853
+ const [s2, e2] = span2(from(k));
2846
2854
  widths.push(e2 - s2);
2847
2855
  }
2848
2856
  widths.sort((p, q) => p - q);
2849
2857
  const radius = widths[widths.length >> 1] / 2;
2850
2858
  const ks = end === "top" ? firstK + radius : firstK - radius;
2851
- const [s, e] = span(Math.round(ks));
2859
+ const [s, e] = span2(Math.round(ks));
2852
2860
  return {
2853
2861
  point: {
2854
2862
  x: roundTo((s + e) / 2 - canvasW / 2, 0.01),
@@ -2873,9 +2881,9 @@ function runSpan(layer) {
2873
2881
  function armGeometry(layer, bodyAxisX) {
2874
2882
  const { bbox, canvasW, canvasH, rowRuns } = layer;
2875
2883
  const b = boxOfLayer(layer);
2876
- const span = runSpan(layer);
2884
+ const span2 = runSpan(layer);
2877
2885
  const centreX = (k) => {
2878
- const [s2, e2] = span(k);
2886
+ const [s2, e2] = span2(k);
2879
2887
  return (s2 + e2) / 2 - canvasW / 2;
2880
2888
  };
2881
2889
  const rowY = (k) => canvasH / 2 - (bbox.y + k + 0.5);
@@ -2889,7 +2897,7 @@ function armGeometry(layer, bodyAxisX) {
2889
2897
  );
2890
2898
  }
2891
2899
  const elbow = { x: roundTo(centreX(ke), 0.01), y: roundTo(rowY(ke), 0.01) };
2892
- const [s, e] = span(ke);
2900
+ const [s, e] = span2(ke);
2893
2901
  const capRadius = Math.min(
2894
2902
  (e - s) / 2 + 1,
2895
2903
  elbow.x - b.x0,
@@ -2899,7 +2907,7 @@ function armGeometry(layer, bodyAxisX) {
2899
2907
  const inside = (x, y) => {
2900
2908
  const k = Math.floor(y) - bbox.y;
2901
2909
  if (k < 0 || k >= bbox.h) return false;
2902
- const [rs, re] = span(k);
2910
+ const [rs, re] = span2(k);
2903
2911
  return rs < x && x < re;
2904
2912
  };
2905
2913
  const capRays = Array.from({ length: CAP_SEGMENTS + 1 }, (_, i) => {
@@ -3106,13 +3114,24 @@ function forearmPoseDeformer(role, arm) {
3106
3114
  }
3107
3115
 
3108
3116
  // src/auto-rig/mouth.ts
3109
- var import_format7 = require("@ikijs/format");
3117
+ var import_format8 = require("@ikijs/format");
3110
3118
 
3111
3119
  // src/auto-rig/roles.ts
3120
+ var import_format7 = require("@ikijs/format");
3112
3121
  var LIP_ROLES = ["mouth_inner", "lip_lower", "lip_upper"];
3113
3122
  var isLipRole = (role) => LIP_ROLES.includes(role);
3114
3123
  var LIP_INSIDE_ROLES = ["mouth_tongue", "mouth_teeth"];
3115
3124
  var isLipInsideRole = (role) => LIP_INSIDE_ROLES.includes(role);
3125
+ var SHUT_BY = new Map([
3126
+ ["eye_L", import_format7.StandardParameter.EyeOpenLeft],
3127
+ ["lash_lower_L", import_format7.StandardParameter.EyeOpenLeft],
3128
+ ["eye_R", import_format7.StandardParameter.EyeOpenRight],
3129
+ ["lash_lower_R", import_format7.StandardParameter.EyeOpenRight],
3130
+ ...[...LIP_ROLES, ...LIP_INSIDE_ROLES].map((id) => [
3131
+ id,
3132
+ import_format7.StandardParameter.MouthOpen
3133
+ ])
3134
+ ]);
3116
3135
  var ROLE_TABLE = [
3117
3136
  { role: "hair_back", family: "hair_back" },
3118
3137
  { role: "body", family: "body" },
@@ -3457,7 +3476,7 @@ function columnOfKnot(knot, opening) {
3457
3476
  function mouthFoldWarp(role, mesh, xs, box, opening) {
3458
3477
  const fold = mouthFold(role, opening);
3459
3478
  return localWarp(
3460
- import_format7.StandardParameter.MouthOpen,
3479
+ import_format8.StandardParameter.MouthOpen,
3461
3480
  mesh,
3462
3481
  box,
3463
3482
  [0, 1],
@@ -3466,13 +3485,13 @@ function mouthFoldWarp(role, mesh, xs, box, opening) {
3466
3485
  }
3467
3486
  function mouthRestShift(byRole) {
3468
3487
  const rig = buildMouthRig(byRole);
3469
- const fields = /* @__PURE__ */ new Map();
3488
+ const fields2 = /* @__PURE__ */ new Map();
3470
3489
  for (const role of ["lip_upper", "lip_lower"]) {
3471
3490
  const box = boxOfLayer(byRole.get(role));
3472
3491
  const { mesh, xs } = mouthMesh(box, rig.knots);
3473
3492
  const warp = mouthFoldWarp(role, mesh, xs, box, rig.opening);
3474
3493
  const offsets = warp.keyforms[0].offsets;
3475
- fields.set(role, {
3494
+ fields2.set(role, {
3476
3495
  box,
3477
3496
  xs,
3478
3497
  rows: offsets.length / 2 / xs.length - 1,
@@ -3481,7 +3500,7 @@ function mouthRestShift(byRole) {
3481
3500
  }
3482
3501
  const { canvasW, canvasH } = byRole.get("lip_upper");
3483
3502
  return (role, col, row) => {
3484
- const { box, xs, rows, dy } = fields.get(role);
3503
+ const { box, xs, rows, dy } = fields2.get(role);
3485
3504
  const x = col + 0.5 - canvasW / 2;
3486
3505
  const y = canvasH / 2 - (row + 0.5);
3487
3506
  if (x < box.x0 || x > box.x1 || y < box.y0 || y > box.y1) return void 0;
@@ -3570,32 +3589,32 @@ function mouthAnchor(byRole) {
3570
3589
  }
3571
3590
 
3572
3591
  // src/auto-rig/generate.ts
3573
- var import_format10 = require("@ikijs/format");
3592
+ var import_format12 = require("@ikijs/format");
3574
3593
 
3575
3594
  // src/auto-rig/animations.ts
3576
- var import_format8 = require("@ikijs/format");
3595
+ var import_format9 = require("@ikijs/format");
3577
3596
  function browsY(y) {
3578
3597
  return [
3579
- { parameter: import_format8.StandardParameter.BrowLeftY, value: y, blend: "add" },
3580
- { parameter: import_format8.StandardParameter.BrowRightY, value: y, blend: "add" }
3598
+ { parameter: import_format9.StandardParameter.BrowLeftY, value: y, blend: "add" },
3599
+ { parameter: import_format9.StandardParameter.BrowRightY, value: y, blend: "add" }
3581
3600
  ];
3582
3601
  }
3583
3602
  function browsTilt(innerDown) {
3584
3603
  return [
3585
- { parameter: import_format8.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
3586
- { parameter: import_format8.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
3604
+ { parameter: import_format9.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
3605
+ { parameter: import_format9.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
3587
3606
  ];
3588
3607
  }
3589
3608
  function cheek(value) {
3590
- return { parameter: import_format8.StandardParameter.Cheek, value, blend: "add" };
3609
+ return { parameter: import_format9.StandardParameter.Cheek, value, blend: "add" };
3591
3610
  }
3592
- var BROWS = [import_format8.StandardParameter.BrowLeftY, import_format8.StandardParameter.BrowRightY, import_format8.StandardParameter.BrowLeftAngle, import_format8.StandardParameter.BrowRightAngle];
3611
+ var BROWS = [import_format9.StandardParameter.BrowLeftY, import_format9.StandardParameter.BrowRightY, import_format9.StandardParameter.BrowLeftAngle, import_format9.StandardParameter.BrowRightAngle];
3593
3612
  var EXPRESSIONS = [
3594
3613
  {
3595
3614
  id: "smile",
3596
3615
  description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
3597
3616
  parameters: [
3598
- { parameter: import_format8.StandardParameter.MouthForm, value: 1, blend: "add" },
3617
+ { parameter: import_format9.StandardParameter.MouthForm, value: 1, blend: "add" },
3599
3618
  ...browsY(0.25),
3600
3619
  cheek(0.4)
3601
3620
  ]
@@ -3604,10 +3623,10 @@ var EXPRESSIONS = [
3604
3623
  id: "laugh",
3605
3624
  description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
3606
3625
  parameters: [
3607
- { parameter: import_format8.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
3608
- { parameter: import_format8.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
3609
- { parameter: import_format8.StandardParameter.MouthForm, value: 1, blend: "add" },
3610
- { parameter: import_format8.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
3626
+ { parameter: import_format9.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
3627
+ { parameter: import_format9.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
3628
+ { parameter: import_format9.StandardParameter.MouthForm, value: 1, blend: "add" },
3629
+ { parameter: import_format9.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
3611
3630
  ...browsY(0.4),
3612
3631
  cheek(0.65)
3613
3632
  ]
@@ -3619,7 +3638,7 @@ var EXPRESSIONS = [
3619
3638
  parameters: [
3620
3639
  ...browsY(-0.5),
3621
3640
  ...browsTilt(0.8),
3622
- { parameter: import_format8.StandardParameter.MouthForm, value: -0.9, blend: "add" }
3641
+ { parameter: import_format9.StandardParameter.MouthForm, value: -0.9, blend: "add" }
3623
3642
  ]
3624
3643
  },
3625
3644
  {
@@ -3629,7 +3648,7 @@ var EXPRESSIONS = [
3629
3648
  parameters: [
3630
3649
  ...browsY(0.35),
3631
3650
  ...browsTilt(-0.8),
3632
- { parameter: import_format8.StandardParameter.MouthForm, value: -0.8, blend: "add" }
3651
+ { parameter: import_format9.StandardParameter.MouthForm, value: -0.8, blend: "add" }
3633
3652
  ]
3634
3653
  },
3635
3654
  {
@@ -3637,18 +3656,18 @@ var EXPRESSIONS = [
3637
3656
  description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
3638
3657
  parameters: [
3639
3658
  ...browsY(0.8),
3640
- { parameter: import_format8.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
3659
+ { parameter: import_format9.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
3641
3660
  ]
3642
3661
  },
3643
3662
  {
3644
3663
  id: "shy",
3645
3664
  description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
3646
- needs: [import_format8.StandardParameter.Cheek],
3665
+ needs: [import_format9.StandardParameter.Cheek],
3647
3666
  parameters: [
3648
3667
  cheek(1),
3649
3668
  // Gaze down.
3650
- { parameter: import_format8.StandardParameter.EyeballY, value: -0.65, blend: "add" },
3651
- { parameter: import_format8.StandardParameter.MouthForm, value: 0.4, blend: "add" },
3669
+ { parameter: import_format9.StandardParameter.EyeballY, value: -0.65, blend: "add" },
3670
+ { parameter: import_format9.StandardParameter.MouthForm, value: 0.4, blend: "add" },
3652
3671
  ...browsTilt(-0.25)
3653
3672
  ]
3654
3673
  }
@@ -3668,7 +3687,7 @@ var HEAD_MOTIONS = {
3668
3687
  duration: 1,
3669
3688
  curves: [
3670
3689
  {
3671
- parameter: import_format8.StandardParameter.AngleY,
3690
+ parameter: import_format9.StandardParameter.AngleY,
3672
3691
  keys: [
3673
3692
  [0, 0],
3674
3693
  [0.3, -18],
@@ -3689,7 +3708,7 @@ var HEAD_MOTIONS = {
3689
3708
  fadeIn: 0.15,
3690
3709
  curves: [
3691
3710
  {
3692
- parameter: import_format8.StandardParameter.AngleX,
3711
+ parameter: import_format9.StandardParameter.AngleX,
3693
3712
  keys: [
3694
3713
  [0, 0],
3695
3714
  [0.2, -18],
@@ -3708,7 +3727,7 @@ var HEAD_MOTIONS = {
3708
3727
  duration: 1.4,
3709
3728
  curves: [
3710
3729
  {
3711
- parameter: import_format8.StandardParameter.AngleZ,
3730
+ parameter: import_format9.StandardParameter.AngleZ,
3712
3731
  keys: [
3713
3732
  [0, 0],
3714
3733
  [0.35, 20],
@@ -3729,7 +3748,7 @@ var WAVE = {
3729
3748
  fadeOut: 0.15,
3730
3749
  curves: [
3731
3750
  {
3732
- parameter: import_format8.StandardParameter.ArmPoseRight,
3751
+ parameter: import_format9.StandardParameter.ArmPoseRight,
3733
3752
  interpolation: "linear",
3734
3753
  keys: [
3735
3754
  [0, 0],
@@ -3739,7 +3758,7 @@ var WAVE = {
3739
3758
  ]
3740
3759
  },
3741
3760
  {
3742
- parameter: import_format8.StandardParameter.ArmRight,
3761
+ parameter: import_format9.StandardParameter.ArmRight,
3743
3762
  keys: [
3744
3763
  [0, 0],
3745
3764
  [0.4, 10],
@@ -3748,7 +3767,7 @@ var WAVE = {
3748
3767
  ]
3749
3768
  },
3750
3769
  {
3751
- parameter: import_format8.StandardParameter.ArmPoseAngleRight,
3770
+ parameter: import_format9.StandardParameter.ArmPoseAngleRight,
3752
3771
  keys: [
3753
3772
  [0, 0],
3754
3773
  [0.5, 0],
@@ -3764,7 +3783,7 @@ var WAVE = {
3764
3783
  ]
3765
3784
  };
3766
3785
  function defaultMotions(declared) {
3767
- const waves = [import_format8.StandardParameter.ArmRight, import_format8.StandardParameter.ArmPoseRight, import_format8.StandardParameter.ArmPoseAngleRight].every(
3786
+ const waves = [import_format9.StandardParameter.ArmRight, import_format9.StandardParameter.ArmPoseRight, import_format9.StandardParameter.ArmPoseAngleRight].every(
3768
3787
  (id) => declared.has(id)
3769
3788
  );
3770
3789
  return waves ? { ...HEAD_MOTIONS, ...WAVE } : HEAD_MOTIONS;
@@ -4000,7 +4019,7 @@ function checkStrandEdges(strand, irises, hair) {
4000
4019
  }
4001
4020
 
4002
4021
  // src/auto-rig/context.ts
4003
- var import_format9 = require("@ikijs/format");
4022
+ var import_format10 = require("@ikijs/format");
4004
4023
 
4005
4024
  // src/auto-rig/head.ts
4006
4025
  function outerEdge(runs, axisX, side) {
@@ -4109,14 +4128,14 @@ function buildHeadFrame(layers, opts) {
4109
4128
  const rawRows = raw;
4110
4129
  const earless = (chin) => {
4111
4130
  const rowOf = (y) => Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);
4112
- const span = Math.max(1, eyeY - chin);
4131
+ const span2 = Math.max(1, eyeY - chin);
4113
4132
  const found = findEars(
4114
4133
  rawRows,
4115
4134
  wMax,
4116
4135
  Math.round(0.2 * rawRows.length),
4117
4136
  Math.min(rawRows.length - 1, rowOf(chin)),
4118
- Math.round(0.1 * span),
4119
- Math.round(0.8 * span)
4137
+ Math.round(0.1 * span2),
4138
+ Math.round(0.8 * span2)
4120
4139
  );
4121
4140
  if (found === void 0) return profile;
4122
4141
  const { top, bottom } = found;
@@ -4150,16 +4169,16 @@ function buildHeadFrame(layers, opts) {
4150
4169
  }
4151
4170
  }
4152
4171
  if (neckRow >= 0 && n - neckRow >= 0.12 * n) {
4153
- let span = 0;
4172
+ let span2 = 0;
4154
4173
  let waist = Infinity;
4155
4174
  for (let r = neckRow; r < n; r++) {
4156
- span = Math.max(span, profile[r]);
4175
+ span2 = Math.max(span2, profile[r]);
4157
4176
  if (r < n - tail) waist = Math.min(waist, profile[r]);
4158
4177
  }
4159
4178
  neck = {
4160
4179
  topY: rowY(neckRow),
4161
4180
  half: profile[neckRow],
4162
- span,
4181
+ span: span2,
4163
4182
  waist: Math.min(waist, profile[neckRow])
4164
4183
  };
4165
4184
  }
@@ -4359,22 +4378,22 @@ function earField(m) {
4359
4378
  const dy = face(x, y, 0, ay)[1];
4360
4379
  const d = Math.abs(x - f.axisX);
4361
4380
  const attach = ears.attachAt(y);
4362
- const span = Math.max(1, ears.outer - attach);
4381
+ const span2 = Math.max(1, ears.outer - attach);
4363
4382
  if (sideOf(m, x, s) === "far") {
4364
4383
  const rim2 = TURN.earFar * m.face;
4365
4384
  const root2 = earRoot(m, face, y, s);
4366
4385
  const lead = Math.max(
4367
4386
  0,
4368
- Math.min((1 - m.earFarScale) * span, root2 - rim2)
4387
+ Math.min((1 - m.earFarScale) * span2, root2 - rim2)
4369
4388
  );
4370
- let along = rim2 + lead * (ears.outer - d) / span;
4389
+ let along = rim2 + lead * (ears.outer - d) / span2;
4371
4390
  if (d < attach) along = Math.min(along, s * face(x, y, 30 * s, 0)[0]);
4372
4391
  return [s * a * along, dy];
4373
4392
  }
4374
4393
  if (d <= attach) return [face(x, y, ax, 0)[0], dy];
4375
4394
  const root = face(f.axisX + Math.sign(x - f.axisX) * attach, y, ax, 0)[0];
4376
4395
  const rim = s * a * TURN.earNear * m.face;
4377
- const t = Math.min(1, (d - attach) / span);
4396
+ const t = Math.min(1, (d - attach) / span2);
4378
4397
  return [root + (rim - root) * t, dy];
4379
4398
  };
4380
4399
  }
@@ -5130,7 +5149,7 @@ function renderedLander(turn, parts, grids, from = /* @__PURE__ */ new Map()) {
5130
5149
  const family = roleSpec(role).family;
5131
5150
  const part = parts.find((p) => p.id === role);
5132
5151
  const g = grids.get(family);
5133
- const warp = part?.warps?.find((w) => w.parameter === import_format9.StandardParameter.AngleX);
5152
+ const warp = part?.warps?.find((w) => w.parameter === import_format10.StandardParameter.AngleX);
5134
5153
  if (part === void 0 || part.mesh === void 0 || !g && !warp) {
5135
5154
  return x + field(role)(x, y, ax, 0)[0];
5136
5155
  }
@@ -5269,11 +5288,11 @@ function buildFaceMesh(frame, b, head, neckCells) {
5269
5288
  const indices = [];
5270
5289
  const neck = frame.neck;
5271
5290
  if (neck !== void 0) {
5272
- const span = neck.span + pad;
5273
- const nc = cellsFor(2 * span, neckCells.px, neckCells.min, neckCells.max);
5291
+ const span2 = neck.span + pad;
5292
+ const nc = cellsFor(2 * span2, neckCells.px, neckCells.min, neckCells.max);
5274
5293
  const xs2 = columns(
5275
- Math.max(b.x0, frame.axisX - span),
5276
- Math.min(b.x1, frame.axisX + span),
5294
+ Math.max(b.x0, frame.axisX - span2),
5295
+ Math.min(b.x1, frame.axisX + span2),
5277
5296
  nc
5278
5297
  );
5279
5298
  const sampleBelow = (x) => Math.max(
@@ -5409,6 +5428,9 @@ function buildFaceMesh(frame, b, head, neckCells) {
5409
5428
  return { mesh: { vertices, uvs, indices }, region, headStart };
5410
5429
  }
5411
5430
 
5431
+ // src/auto-rig/patches.ts
5432
+ var import_format11 = require("@ikijs/format");
5433
+
5412
5434
  // src/auto-rig/solve.ts
5413
5435
  var RANGES = {
5414
5436
  // [lo, hi, lo exclusive]
@@ -5839,6 +5861,235 @@ function buildTurn(frame, landmarks, q) {
5839
5861
  };
5840
5862
  }
5841
5863
 
5864
+ // src/auto-rig/patches.ts
5865
+ var OP_KEYS = ["target", "at", "region", "by", "falloff", "why"];
5866
+ var REGION_KEYS = ["role", "x", "y"];
5867
+ var BY_KEYS = ["dx", "dy"];
5868
+ var ROLLS = /* @__PURE__ */ new Set([import_format11.StandardParameter.AngleZ, import_format11.StandardParameter.BodyAngleZ]);
5869
+ var REST_IS_ART = "rest is the drawn art, which no patch changes (change it with the layout or by regenerating the layer)";
5870
+ function applyPatches(patches, ctx) {
5871
+ if (!Array.isArray(patches)) {
5872
+ throw new PatchError(
5873
+ `patches must be an array, got ${patches === null ? "null" : typeof patches}`
5874
+ );
5875
+ }
5876
+ const sums = /* @__PURE__ */ new Map();
5877
+ const reports = patches.map((op, i) => replay(op, i, ctx, sums));
5878
+ for (const [offsets, s] of sums) {
5879
+ s.terms.forEach((t, k) => {
5880
+ if (t.length === 0) return;
5881
+ const d = t.sort((a, b) => a - b).reduce((a, b) => a + b, 0);
5882
+ offsets[k] = roundTo(offsets[k] + d / s.scale[k % 2], s.step);
5883
+ });
5884
+ }
5885
+ return reports;
5886
+ }
5887
+ function replay(op, i, ctx, sums) {
5888
+ const name = `patches[${i}]`;
5889
+ const o = fields(name, op, OP_KEYS);
5890
+ const target = text(`${name}.target`, o.target);
5891
+ const at = numbers(`${name}.at`, o.at);
5892
+ const region = fields(`${name}.region`, o.region, REGION_KEYS);
5893
+ const role = text(`${name}.region.role`, region.role);
5894
+ const x = span(`${name}.region.x`, region.x);
5895
+ const y = span(`${name}.region.y`, region.y);
5896
+ const by = fields(`${name}.by`, o.by, BY_KEYS);
5897
+ const dx = finite2(`${name}.by.dx`, by.dx);
5898
+ const dy = finite2(`${name}.by.dy`, by.dy);
5899
+ const falloff = o.falloff === void 0 ? 0 : finite2(`${name}.falloff`, o.falloff, 0);
5900
+ if (o.why !== void 0) text(`${name}.why`, o.why);
5901
+ const box = ctx.boxOf(role);
5902
+ if (box === void 0) {
5903
+ const roles = [...new Set(ctx.parts.map((p) => roleOfPart(p.id)))].filter(
5904
+ (r) => ctx.boxOf(r) !== void 0
5905
+ );
5906
+ throw new PatchError(
5907
+ `${name}.region.role "${role}" is not a layer of this set (roles: ${roles.join(", ")})`
5908
+ );
5909
+ }
5910
+ const stop = resolveStop(name, target, at, ctx);
5911
+ const { points } = stop;
5912
+ const weights = regionWeights(points, box, x, y, falloff * ctx.faceWidth);
5913
+ const hit = weights.flatMap((w, k) => w > 0 ? [k] : []);
5914
+ if (hit.length === 0) {
5915
+ const fx = points.map(([px]) => (px - box.x0) / bw(box));
5916
+ const fy = points.map(([, py]) => (box.y1 - py) / bh(box));
5917
+ const range = (v) => `[${roundTo(Math.min(...v), 0.01)}, ${roundTo(Math.max(...v), 0.01)}]`;
5918
+ throw new PatchError(
5919
+ `${name}.region (falloff ${falloff}) catches none of ${target}'s ${points.length} points; at rest they span x ${range(fx)}, y ${range(fy)} of ${role}'s box`
5920
+ );
5921
+ }
5922
+ let sum = sums.get(stop.offsets);
5923
+ if (sum === void 0) {
5924
+ sum = {
5925
+ terms: stop.offsets.map(() => []),
5926
+ scale: stop.scale,
5927
+ step: stop.step
5928
+ };
5929
+ sums.set(stop.offsets, sum);
5930
+ }
5931
+ const ddx = dx * ctx.faceWidth;
5932
+ const ddy = -dy * ctx.faceWidth;
5933
+ for (const k of hit) {
5934
+ sum.terms[2 * k].push(ddx * weights[k]);
5935
+ sum.terms[2 * k + 1].push(ddy * weights[k]);
5936
+ }
5937
+ const maxW = Math.max(...hit.map((k) => weights[k]));
5938
+ const report = {
5939
+ index: i,
5940
+ target,
5941
+ at,
5942
+ moved: hit.length,
5943
+ of: points.length,
5944
+ maxPx: roundTo(maxW * Math.hypot(dx, dy) * ctx.faceWidth, 0.1)
5945
+ };
5946
+ if (stop.stride !== void 0) {
5947
+ const { stride } = stop;
5948
+ const cols = hit.map((k) => k % stride);
5949
+ const rows = hit.map((k) => Math.floor(k / stride));
5950
+ report.cols = [Math.min(...cols), Math.max(...cols)];
5951
+ report.rows = [Math.min(...rows), Math.max(...rows)];
5952
+ }
5953
+ return report;
5954
+ }
5955
+ function resolveStop(name, target, at, ctx) {
5956
+ const grid = ctx.grids.get(target);
5957
+ if (grid !== void 0) {
5958
+ const l = grid.lattice.points;
5959
+ const points = [];
5960
+ for (let k = 0; k < l.length; k += 2) points.push([l[k], l[k + 1]]);
5961
+ return {
5962
+ offsets: gridStop(name, at, target, grid.keyforms),
5963
+ points,
5964
+ scale: [1, 1],
5965
+ step: 0.1,
5966
+ stride: grid.lattice.cols + 1
5967
+ };
5968
+ }
5969
+ const part = ctx.parts.find((p) => p.id === target);
5970
+ const b = ctx.boxOf(target);
5971
+ if (part?.mesh === void 0 || part.warps === void 0 || b === void 0) {
5972
+ const parts = ctx.parts.filter(
5973
+ (p) => p.mesh !== void 0 && p.warps !== void 0 && ctx.boxOf(p.id) !== void 0
5974
+ );
5975
+ throw new PatchError(
5976
+ `${name}.target "${target}" is neither a feature grid (${[...ctx.grids.keys()].join(", ")}) nor a mesh part with warps (${parts.map((p) => p.id).join(", ")}); bodyWarp and the matrix deformers are not patchable`
5977
+ );
5978
+ }
5979
+ return {
5980
+ offsets: partStop(name, at, part, part.warps, ctx),
5981
+ points: meshPoints(part.mesh, b),
5982
+ scale: [bw(b), bh(b)],
5983
+ step: 1e-4
5984
+ };
5985
+ }
5986
+ function gridStop(name, at, id, keyforms) {
5987
+ const i = X_STOPS.indexOf(at[import_format11.StandardParameter.AngleX]);
5988
+ const j = Y_STOPS.indexOf(at[import_format11.StandardParameter.AngleY]);
5989
+ if (Object.keys(at).length !== 2 || i < 0 || j < 0) {
5990
+ throw new PatchError(
5991
+ `${name}.at must name ${import_format11.StandardParameter.AngleX} in [${X_STOPS.join(", ")}] and ${import_format11.StandardParameter.AngleY} in [${Y_STOPS.join(", ")}] for the grid ${id}, got ${JSON.stringify(at)}`
5992
+ );
5993
+ }
5994
+ if (X_STOPS[i] === 0 && Y_STOPS[j] === 0) {
5995
+ throw new PatchError(
5996
+ `${name}.at ${import_format11.StandardParameter.AngleX}=0 ${import_format11.StandardParameter.AngleY}=0 is ${id}'s rest stop: ${REST_IS_ART}; patch a stop with ${import_format11.StandardParameter.AngleX} or ${import_format11.StandardParameter.AngleY} at \xB130 instead`
5997
+ );
5998
+ }
5999
+ return keyforms[j * X_STOPS.length + i];
6000
+ }
6001
+ function partStop(name, at, part, warps, ctx) {
6002
+ const keys = Object.keys(at);
6003
+ const [param] = keys;
6004
+ const value = at[param];
6005
+ const keyform = keys.length === 1 ? warps.filter((w) => w.parameter === param).flatMap((w) => w.keyforms).find((k) => k.value === value) : void 0;
6006
+ if (keyform === void 0) {
6007
+ throw new PatchError(
6008
+ `${name}.at must name one parameter at one of ${part.id}'s warp stops (${listStops(warps, () => true)}), got ${JSON.stringify(at)}`
6009
+ );
6010
+ }
6011
+ if (ROLLS.has(param)) {
6012
+ throw new PatchError(
6013
+ `${name}.at ${param}: that parameter rolls ${part.id}'s deformer chain, so a displacement at its stop is not on screen axes; patch another of its stops (${listStops(warps, (p) => !ROLLS.has(p))}) or its feature grid instead`
6014
+ );
6015
+ }
6016
+ const isRest = (p, v) => v === ctx.parameters.find((q) => q.id === p)?.default;
6017
+ const isShut = (p, v) => SHUT_BY.get(part.id) === p && v === 0;
6018
+ if (!isRest(param, value) && !isShut(param, value)) return keyform.offsets;
6019
+ const open = listStops(warps, (p, v) => !isRest(p, v) && !isShut(p, v));
6020
+ const grid = part.deformer !== void 0 && ctx.grids.has(part.deformer) ? `its feature grid ${part.deformer} at a ${import_format11.StandardParameter.AngleX} \xD7 ${import_format11.StandardParameter.AngleY} stop` : "";
6021
+ const instead = [open && `another of its stops (${open})`, grid].filter((s) => s !== "").join(" or ");
6022
+ const hint = instead === "" ? "" : `; patch ${instead} instead`;
6023
+ throw new PatchError(
6024
+ isRest(param, value) ? `${name}.at ${param}=${value} is that parameter's default, ${part.id}'s rest stop: ${REST_IS_ART}${hint}` : `${name}.at ${param}=0 is where the rig shuts ${part.id} on purpose, a closure the fold check exempts, so a fold a patch made there would never be reported${hint}`
6025
+ );
6026
+ }
6027
+ function listStops(warps, keep) {
6028
+ const stops = /* @__PURE__ */ new Map();
6029
+ for (const w of warps) {
6030
+ for (const k of w.keyforms) {
6031
+ if (!keep(w.parameter, k.value)) continue;
6032
+ const s = stops.get(w.parameter) ?? /* @__PURE__ */ new Set();
6033
+ s.add(k.value);
6034
+ stops.set(w.parameter, s);
6035
+ }
6036
+ }
6037
+ return [...stops].map(([p, s]) => `${p}@${[...s].sort((a, b) => a - b).join(",")}`).join(" ");
6038
+ }
6039
+ function regionWeights(points, box, x, y, fall) {
6040
+ const x0 = box.x0 + x[0] * bw(box);
6041
+ const x1 = box.x0 + x[1] * bw(box);
6042
+ const top = box.y1 - y[0] * bh(box);
6043
+ const bottom = box.y1 - y[1] * bh(box);
6044
+ return points.map(([px, py]) => {
6045
+ const d = Math.hypot(
6046
+ Math.max(x0 - px, 0, px - x1),
6047
+ Math.max(bottom - py, 0, py - top)
6048
+ );
6049
+ return d === 0 ? 1 : d < fall ? smoothstep(fall, 0, d) : 0;
6050
+ });
6051
+ }
6052
+ function asPatch(check) {
6053
+ try {
6054
+ return check();
6055
+ } catch (e) {
6056
+ throw e instanceof TurnTargetError ? new PatchError(e.message) : e;
6057
+ }
6058
+ }
6059
+ function fields(name, v, known) {
6060
+ if (v === void 0) throw new PatchError(`${name} is missing`);
6061
+ asPatch(() => checkedKeys(name, v, known));
6062
+ return v;
6063
+ }
6064
+ function numbers(name, v) {
6065
+ const o = fields(name, v, Object.keys(v ?? {}));
6066
+ return Object.fromEntries(
6067
+ Object.entries(o).map(([k, n]) => [k, finite2(`${name}.${k}`, n)])
6068
+ );
6069
+ }
6070
+ var finite2 = (name, v, lo = -Infinity) => asPatch(() => checkedNumber(name, v, lo, Infinity));
6071
+ function text(name, v) {
6072
+ if (typeof v !== "string") {
6073
+ throw new PatchError(`${name} must be a string, got ${String(v)}`);
6074
+ }
6075
+ return v;
6076
+ }
6077
+ function span(name, v) {
6078
+ if (!Array.isArray(v) || v.length !== 2) {
6079
+ throw new PatchError(
6080
+ `${name} must be [from, to], got ${JSON.stringify(v)}`
6081
+ );
6082
+ }
6083
+ const lo = finite2(`${name}[0]`, v[0]);
6084
+ const hi = finite2(`${name}[1]`, v[1]);
6085
+ if (lo > hi) {
6086
+ throw new PatchError(
6087
+ `${name} [${lo}, ${hi}] runs backwards: ${name}[0] must not exceed ${name}[1]`
6088
+ );
6089
+ }
6090
+ return [lo, hi];
6091
+ }
6092
+
5842
6093
  // src/auto-rig/generate.ts
5843
6094
  var MESH_CELLS = {
5844
6095
  face: { px: 28, min: 4, max: 24 },
@@ -6016,8 +6267,17 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
6016
6267
  ];
6017
6268
  }
6018
6269
  const parameters = declareParameters(new Set(byRole.keys()));
6270
+ const reports = options.patches === void 0 ? void 0 : applyPatches(options.patches, {
6271
+ grids: new Map(
6272
+ [...grids].map(([family, g]) => [WARP_ID[family], g])
6273
+ ),
6274
+ parts,
6275
+ boxOf: (role) => has(role) ? box(role) : void 0,
6276
+ faceWidth: byRole.get("face").cropW,
6277
+ parameters
6278
+ });
6019
6279
  const model = {
6020
- version: import_format10.IKI_FORMAT_VERSION,
6280
+ version: import_format12.IKI_FORMAT_VERSION,
6021
6281
  name: "auto-rigged",
6022
6282
  canvas: { width: canvas.width, height: canvas.height },
6023
6283
  parameters,
@@ -6027,7 +6287,8 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
6027
6287
  expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),
6028
6288
  motions: defaultMotions(new Set(parameters.map((p) => p.id)))
6029
6289
  };
6030
- const valid = (0, import_format10.parseIkiModel)(model);
6290
+ const valid = (0, import_format12.parseIkiModel)(model);
6291
+ if (reports !== void 0) options.onPatchesApplied?.(reports);
6031
6292
  if (hasNose && options.onTurnSolved) {
6032
6293
  options.onTurnSolved(
6033
6294
  turnReport(
@@ -6042,14 +6303,14 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
6042
6303
  function turnWarps(mesh, b, fieldOf) {
6043
6304
  return [
6044
6305
  localWarp(
6045
- import_format10.StandardParameter.AngleX,
6306
+ import_format12.StandardParameter.AngleX,
6046
6307
  mesh,
6047
6308
  b,
6048
6309
  X_STOPS,
6049
6310
  ([x, y], v, i) => v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0]
6050
6311
  ),
6051
6312
  localWarp(
6052
- import_format10.StandardParameter.AngleY,
6313
+ import_format12.StandardParameter.AngleY,
6053
6314
  mesh,
6054
6315
  b,
6055
6316
  Y_STOPS,
@@ -6100,7 +6361,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6100
6361
  }
6101
6362
  if (mesh !== void 0) part.mesh = mesh;
6102
6363
  const side = spec.role.endsWith("_L") ? "L" : "R";
6103
- const eyeOpen = side === "L" ? import_format10.StandardParameter.EyeOpenLeft : import_format10.StandardParameter.EyeOpenRight;
6364
+ const eyeOpen = side === "L" ? import_format12.StandardParameter.EyeOpenLeft : import_format12.StandardParameter.EyeOpenRight;
6104
6365
  const hh = frame.hh;
6105
6366
  switch (spec.role) {
6106
6367
  case "face":
@@ -6115,7 +6376,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6115
6376
  headOwnRoll(byRole.has("body"))
6116
6377
  ),
6117
6378
  localWarp(
6118
- import_format10.StandardParameter.Breath,
6379
+ import_format12.StandardParameter.Breath,
6119
6380
  mesh,
6120
6381
  b,
6121
6382
  [0, 1],
@@ -6162,8 +6423,8 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6162
6423
  if (byRole.has("mouth_open")) {
6163
6424
  warps.push(mouthWiden(mesh, b));
6164
6425
  bindings.push(
6165
- { parameter: import_format10.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 },
6166
- { parameter: import_format10.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 }
6426
+ { parameter: import_format12.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 },
6427
+ { parameter: import_format12.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 }
6167
6428
  );
6168
6429
  extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
6169
6430
  } else {
@@ -6173,19 +6434,19 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6173
6434
  );
6174
6435
  bindings.push(
6175
6436
  {
6176
- parameter: import_format10.StandardParameter.MouthOpen,
6437
+ parameter: import_format12.StandardParameter.MouthOpen,
6177
6438
  channel: "scaleY",
6178
6439
  from: 0,
6179
6440
  to: roundTo(grow, 0.01)
6180
6441
  },
6181
6442
  {
6182
- parameter: import_format10.StandardParameter.MouthOpen,
6443
+ parameter: import_format12.StandardParameter.MouthOpen,
6183
6444
  channel: "scaleX",
6184
6445
  from: 0,
6185
6446
  to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01)
6186
6447
  },
6187
6448
  {
6188
- parameter: import_format10.StandardParameter.MouthOpen,
6449
+ parameter: import_format12.StandardParameter.MouthOpen,
6189
6450
  channel: "translateY",
6190
6451
  from: 0,
6191
6452
  to: -roundTo(grow * bh(b) / 2, 0.01)
@@ -6197,7 +6458,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6197
6458
  case "mouth_open":
6198
6459
  warps.push(mouthForm(mesh, b), mouthOpenGrow(mesh, b));
6199
6460
  bindings.push({
6200
- parameter: import_format10.StandardParameter.MouthOpen,
6461
+ parameter: import_format12.StandardParameter.MouthOpen,
6201
6462
  channel: "opacity",
6202
6463
  from: 0,
6203
6464
  to: 1
@@ -6219,7 +6480,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6219
6480
  case "blush_L":
6220
6481
  case "blush_R":
6221
6482
  bindings.push({
6222
- parameter: import_format10.StandardParameter.Cheek,
6483
+ parameter: import_format12.StandardParameter.Cheek,
6223
6484
  channel: "opacity",
6224
6485
  from: AMPLITUDE.blushRest,
6225
6486
  to: 1
@@ -6230,8 +6491,8 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid, lips) {
6230
6491
  if (byRole.has("hair_front")) {
6231
6492
  const amp = style.sway * AMPLITUDE.sway * hh;
6232
6493
  warps.push(
6233
- hairSway(import_format10.StandardParameter.HairSwayX, mesh, b, amp),
6234
- hairSway(import_format10.StandardParameter.HairSwayZ, mesh, b, amp)
6494
+ hairSway(import_format12.StandardParameter.HairSwayX, mesh, b, amp),
6495
+ hairSway(import_format12.StandardParameter.HairSwayZ, mesh, b, amp)
6235
6496
  );
6236
6497
  }
6237
6498
  warps.push(tiltHang(mesh, b, pivot, hairHangWeight(frame.chinY, b.y0)));
@@ -6297,9 +6558,9 @@ function deformers(frame, grids, bodyWarp, arms, byRole) {
6297
6558
  pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },
6298
6559
  bindings: [
6299
6560
  // AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.
6300
- { parameter: import_format10.StandardParameter.AngleZ, channel: "rotate", from: roll, to: -roll },
6561
+ { parameter: import_format12.StandardParameter.AngleZ, channel: "rotate", from: roll, to: -roll },
6301
6562
  {
6302
- parameter: import_format10.StandardParameter.Breath,
6563
+ parameter: import_format12.StandardParameter.Breath,
6303
6564
  channel: "translateY",
6304
6565
  from: 0,
6305
6566
  to: roundTo(headOwnBreath(hasBody) * frame.hh, 0.01)
@@ -6317,8 +6578,8 @@ function deformers(frame, grids, bodyWarp, arms, byRole) {
6317
6578
  points: g.lattice.points
6318
6579
  },
6319
6580
  warp2d: {
6320
- parameter: import_format10.StandardParameter.AngleX,
6321
- parameterY: import_format10.StandardParameter.AngleY,
6581
+ parameter: import_format12.StandardParameter.AngleX,
6582
+ parameterY: import_format12.StandardParameter.AngleY,
6322
6583
  valuesX: X_STOPS,
6323
6584
  valuesY: Y_STOPS,
6324
6585
  keyforms2d: g.keyforms.map((offsets) => ({ offsets }))
@@ -6331,16 +6592,16 @@ function hairPhysics() {
6331
6592
  return [
6332
6593
  {
6333
6594
  id: "hairSway",
6334
- input: { parameter: import_format10.StandardParameter.AngleX, weight: 1 },
6335
- output: { parameter: import_format10.StandardParameter.HairSwayX, scale: 5 },
6595
+ input: { parameter: import_format12.StandardParameter.AngleX, weight: 1 },
6596
+ output: { parameter: import_format12.StandardParameter.HairSwayX, scale: 5 },
6336
6597
  mass: 1,
6337
6598
  stiffness: 30,
6338
6599
  damping: 3
6339
6600
  },
6340
6601
  {
6341
6602
  id: "hairTilt",
6342
- input: { parameter: import_format10.StandardParameter.AngleZ, weight: 1 },
6343
- output: { parameter: import_format10.StandardParameter.HairSwayZ, scale: 8 },
6603
+ input: { parameter: import_format12.StandardParameter.AngleZ, weight: 1 },
6604
+ output: { parameter: import_format12.StandardParameter.HairSwayZ, scale: 8 },
6344
6605
  mass: 1,
6345
6606
  stiffness: 25,
6346
6607
  damping: 2.5
@@ -6350,13 +6611,13 @@ function hairPhysics() {
6350
6611
  function declareParameters(roles) {
6351
6612
  const out = [];
6352
6613
  const add = (id, name, min, max, def) => out.push({ id, name, min, max, default: def });
6353
- add(import_format10.StandardParameter.AngleX, "Head Angle", -30, 30, 0);
6354
- add(import_format10.StandardParameter.AngleY, "Head Angle Y", -30, 30, 0);
6355
- add(import_format10.StandardParameter.AngleZ, "Head Angle Z", -30, 30, 0);
6614
+ add(import_format12.StandardParameter.AngleX, "Head Angle", -30, 30, 0);
6615
+ add(import_format12.StandardParameter.AngleY, "Head Angle Y", -30, 30, 0);
6616
+ add(import_format12.StandardParameter.AngleZ, "Head Angle Z", -30, 30, 0);
6356
6617
  if (roles.has("body")) {
6357
- add(import_format10.StandardParameter.BodyAngleX, "Body Angle X", -10, 10, 0);
6358
- add(import_format10.StandardParameter.BodyAngleY, "Body Angle Y", -10, 10, 0);
6359
- add(import_format10.StandardParameter.BodyAngleZ, "Body Angle Z", -10, 10, 0);
6618
+ add(import_format12.StandardParameter.BodyAngleX, "Body Angle X", -10, 10, 0);
6619
+ add(import_format12.StandardParameter.BodyAngleY, "Body Angle Y", -10, 10, 0);
6620
+ add(import_format12.StandardParameter.BodyAngleZ, "Body Angle Z", -10, 10, 0);
6360
6621
  }
6361
6622
  const addPose = (side, pose, angle) => {
6362
6623
  add(pose, `Arm Pose ${side}`, 0, 1, 0);
@@ -6365,40 +6626,40 @@ function declareParameters(roles) {
6365
6626
  const [armMin, armMax] = ARM_RANGE;
6366
6627
  const [elbowMin, elbowMax] = ELBOW_RANGE;
6367
6628
  if (roles.has("arm_L")) {
6368
- add(import_format10.StandardParameter.ArmLeft, "Arm L", armMin, armMax, 0);
6369
- add(import_format10.StandardParameter.ElbowLeft, "Elbow L", elbowMin, elbowMax, 0);
6629
+ add(import_format12.StandardParameter.ArmLeft, "Arm L", armMin, armMax, 0);
6630
+ add(import_format12.StandardParameter.ElbowLeft, "Elbow L", elbowMin, elbowMax, 0);
6370
6631
  if (roles.has("forearm_pose_L"))
6371
- addPose("L", import_format10.StandardParameter.ArmPoseLeft, import_format10.StandardParameter.ArmPoseAngleLeft);
6632
+ addPose("L", import_format12.StandardParameter.ArmPoseLeft, import_format12.StandardParameter.ArmPoseAngleLeft);
6372
6633
  }
6373
6634
  if (roles.has("arm_R")) {
6374
- add(import_format10.StandardParameter.ArmRight, "Arm R", armMin, armMax, 0);
6375
- add(import_format10.StandardParameter.ElbowRight, "Elbow R", elbowMin, elbowMax, 0);
6635
+ add(import_format12.StandardParameter.ArmRight, "Arm R", armMin, armMax, 0);
6636
+ add(import_format12.StandardParameter.ElbowRight, "Elbow R", elbowMin, elbowMax, 0);
6376
6637
  if (roles.has("forearm_pose_R"))
6377
- addPose("R", import_format10.StandardParameter.ArmPoseRight, import_format10.StandardParameter.ArmPoseAngleRight);
6638
+ addPose("R", import_format12.StandardParameter.ArmPoseRight, import_format12.StandardParameter.ArmPoseAngleRight);
6378
6639
  }
6379
- add(import_format10.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
6380
- add(import_format10.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
6640
+ add(import_format12.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
6641
+ add(import_format12.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
6381
6642
  if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {
6382
- add(import_format10.StandardParameter.EyeballX, "Gaze X", -1, 1, 0);
6383
- add(import_format10.StandardParameter.EyeballY, "Gaze Y", -1, 1, 0);
6643
+ add(import_format12.StandardParameter.EyeballX, "Gaze X", -1, 1, 0);
6644
+ add(import_format12.StandardParameter.EyeballY, "Gaze Y", -1, 1, 0);
6384
6645
  }
6385
- add(import_format10.StandardParameter.MouthOpen, "Mouth Open", 0, 1, 0);
6386
- add(import_format10.StandardParameter.MouthForm, "Mouth Form", -1, 1, 0);
6646
+ add(import_format12.StandardParameter.MouthOpen, "Mouth Open", 0, 1, 0);
6647
+ add(import_format12.StandardParameter.MouthForm, "Mouth Form", -1, 1, 0);
6387
6648
  if (roles.has("brow_L")) {
6388
- add(import_format10.StandardParameter.BrowLeftY, "Brow L Y", -1, 1, 0);
6389
- add(import_format10.StandardParameter.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
6649
+ add(import_format12.StandardParameter.BrowLeftY, "Brow L Y", -1, 1, 0);
6650
+ add(import_format12.StandardParameter.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
6390
6651
  }
6391
6652
  if (roles.has("brow_R")) {
6392
- add(import_format10.StandardParameter.BrowRightY, "Brow R Y", -1, 1, 0);
6393
- add(import_format10.StandardParameter.BrowRightAngle, "Brow R Angle", -1, 1, 0);
6653
+ add(import_format12.StandardParameter.BrowRightY, "Brow R Y", -1, 1, 0);
6654
+ add(import_format12.StandardParameter.BrowRightAngle, "Brow R Angle", -1, 1, 0);
6394
6655
  }
6395
6656
  if (roles.has("blush_L") || roles.has("blush_R")) {
6396
- add(import_format10.StandardParameter.Cheek, "Cheek", 0, 1, 0);
6657
+ add(import_format12.StandardParameter.Cheek, "Cheek", 0, 1, 0);
6397
6658
  }
6398
- add(import_format10.StandardParameter.Breath, "Breath", 0, 1, 0);
6659
+ add(import_format12.StandardParameter.Breath, "Breath", 0, 1, 0);
6399
6660
  if (roles.has("hair_front")) {
6400
- add(import_format10.StandardParameter.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
6401
- add(import_format10.StandardParameter.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
6661
+ add(import_format12.StandardParameter.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
6662
+ add(import_format12.StandardParameter.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
6402
6663
  }
6403
6664
  return out;
6404
6665
  }
@@ -6420,6 +6681,8 @@ function declareParameters(roles) {
6420
6681
  LIP_INSIDE_ROLES,
6421
6682
  LIP_ROLES,
6422
6683
  LayerGeometryError,
6684
+ PatchError,
6685
+ SHUT_BY,
6423
6686
  SPECK_CORE_FRACTION,
6424
6687
  SetDeformerBindings,
6425
6688
  SetDeformerParent,