@ikijs/editor 0.32.0 → 0.33.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.mjs CHANGED
@@ -1972,7 +1972,8 @@ var PROFILE_VALUES = {
1972
1972
  hairFollow: 1,
1973
1973
  fore: 0.2,
1974
1974
  backShare: 0.1,
1975
- earFar: 0.5,
1975
+ earFar: 0,
1976
+ earFore: 0.1,
1976
1977
  nodDown: 0.18,
1977
1978
  nodUp: 0.1,
1978
1979
  nodLead: 0.06,
@@ -2039,7 +2040,7 @@ function deriveProfile(v) {
2039
2040
  earNear: 1,
2040
2041
  /** The far ear's width at full turn, about its outer edge, where the head
2041
2042
  * leaves it room; less where it does not. */
2042
- earFarScale: 1 - v.fore
2043
+ earFarScale: 1 - v.earFore
2043
2044
  };
2044
2045
  const mid = v.nodDown * (1 + v.chinShare) / 2;
2045
2046
  const feature = (depth) => ({
@@ -2936,6 +2937,7 @@ function mouthAnchor(byRole) {
2936
2937
  }
2937
2938
 
2938
2939
  // src/auto-rig/head.ts
2940
+ var EAR_EDGE = 3;
2939
2941
  function outerEdge(runs, axisX, side) {
2940
2942
  if (runs.length === 0) return void 0;
2941
2943
  const x = side > 0 ? runs[runs.length - 1] : runs[0];
@@ -2969,7 +2971,11 @@ function findEars(raw, wMax, firstRow, lastRow, minRows, maxRows) {
2969
2971
  if (raw[t] - raw[t - EAR_ROWS] < step) continue;
2970
2972
  for (let b = t + minRows; b <= Math.min(lastRow, t + maxRows); b++) {
2971
2973
  if (raw[b - EAR_ROWS] - raw[b] >= step) {
2972
- return { top: t - EAR_ROWS, bottom: b };
2974
+ let end = b;
2975
+ for (let k = b + 1; k <= Math.min(lastRow, b + minRows); k++) {
2976
+ if (raw[k - EAR_ROWS] - raw[k] >= step) end = k;
2977
+ }
2978
+ return { top: t - EAR_ROWS, bottom: end };
2973
2979
  }
2974
2980
  }
2975
2981
  return void 0;
@@ -3047,6 +3053,7 @@ function buildHeadFrame(layers, opts) {
3047
3053
  return rows[i] + (rows[j] - rows[i]) * clamp(r - i, 0, 1);
3048
3054
  };
3049
3055
  const rawRows = raw;
3056
+ let earRows;
3050
3057
  const earless = (chin) => {
3051
3058
  const rowOf = (y) => Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);
3052
3059
  const span3 = Math.max(1, eyeY - chin);
@@ -3069,8 +3076,10 @@ function buildHeadFrame(layers, opts) {
3069
3076
  top: rowY(top) + 0.5,
3070
3077
  bottom: rowY(bottom) - 0.5,
3071
3078
  attachAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)),
3072
- outer
3079
+ outer,
3080
+ edgeAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)) + EAR_EDGE
3073
3081
  };
3082
+ earRows = { top, bottom };
3074
3083
  return smoothProfile(
3075
3084
  rawRows.map((v, r) => r > top && r < bottom ? attach(r) : v)
3076
3085
  );
@@ -3192,9 +3201,13 @@ function buildHeadFrame(layers, opts) {
3192
3201
  headHalfAt = readRows(head);
3193
3202
  headMax = Math.max(...head);
3194
3203
  if (ears !== void 0) {
3204
+ const band = earRows;
3205
+ const edge = head.map(
3206
+ (w, r) => r >= band.top && r <= band.bottom ? w + EAR_EDGE : w
3207
+ );
3195
3208
  const bottomOf = (d) => {
3196
- for (let r = head.length - 1; r >= 0; r--) {
3197
- if (head[r] >= d) return rowY(r) - 0.5;
3209
+ for (let r = edge.length - 1; r >= 0; r--) {
3210
+ if (edge[r] >= d) return rowY(r) - 0.5;
3198
3211
  }
3199
3212
  return face.y1;
3200
3213
  };
@@ -3394,7 +3407,7 @@ function earField(m) {
3394
3407
  const attach = ears.attachAt(y);
3395
3408
  const span3 = Math.max(1, ears.outer - attach);
3396
3409
  if (sideOf(m, x, s) === "far") {
3397
- const rim2 = TURN.earFar * m.face;
3410
+ const rim2 = m.earFar * m.face;
3398
3411
  const root2 = earRoot(m, face, y, s);
3399
3412
  const lead = Math.max(
3400
3413
  0,
@@ -3419,7 +3432,7 @@ function farEarCovered(m) {
3419
3432
  const ears = m.frame.ears;
3420
3433
  if (ears === void 0) return true;
3421
3434
  const face = faceField(m);
3422
- const rim = TURN.earFar * m.face;
3435
+ const rim = m.earFar * m.face;
3423
3436
  const y0 = ears.bottom - 2;
3424
3437
  const y1 = ears.top + 2;
3425
3438
  const n = Math.max(1, Math.ceil(y1 - y0));
@@ -4260,6 +4273,7 @@ function fitTurn(ctx, targets, plan, build) {
4260
4273
  lead: plan.turn.featureLead,
4261
4274
  follow: plan.hair.follow,
4262
4275
  outline: plan.hair.outlineFollow,
4276
+ earFar: plan.turn.farEar,
4263
4277
  fore: targets.farEyeRatio === void 0 ? plan.turn.eyeForeshorten : 1,
4264
4278
  shell: 1,
4265
4279
  noseLead: targets.noseShift !== void 0 || plan.turn.noseLead === 1 ? void 0 : plan.turn.noseLead
@@ -4496,6 +4510,7 @@ function buildTurn(frame, landmarks, q, turn) {
4496
4510
  hairOuter: q.outline * face,
4497
4511
  hairBack: A * hh * turn.hairBack,
4498
4512
  shellScale: q.shell,
4513
+ earFar: q.earFar,
4499
4514
  earFarScale: 1 + A * (turn.earFarScale - 1),
4500
4515
  ...landmarks
4501
4516
  };
@@ -4583,6 +4598,23 @@ var RIG_PLAN_FIELDS = [
4583
4598
  migratedFrom: null,
4584
4599
  what: "how far the nose leads the face plate on the turn \u2014 turn only, the nod keeps the profile's nose depth"
4585
4600
  },
4601
+ {
4602
+ path: "turn.farEar",
4603
+ group: "turn",
4604
+ key: "farEar",
4605
+ kind: "absolute",
4606
+ unit: "share of the face plate's slide",
4607
+ default: PROFILE.TURN.earFar,
4608
+ range: [0, 1],
4609
+ recommended: [0, 0.5],
4610
+ step: 0.1,
4611
+ poses: TURN_POSES,
4612
+ cue: null,
4613
+ fitBy: null,
4614
+ provisional: false,
4615
+ migratedFrom: null,
4616
+ what: "how far the far ear's outer edge follows the face on the turn (0: it holds and the head slides over it, about half of a default-sized ear going under the face; 1: it rides with the face and stays whole)"
4617
+ },
4586
4618
  {
4587
4619
  path: "hair.follow",
4588
4620
  group: "hair",
@@ -6681,6 +6713,11 @@ function buildFaceMesh(frame, b, head, neckCells) {
6681
6713
  frame.axisX - frame.headMax + 0.5,
6682
6714
  frame.axisX + frame.headMax - 0.5
6683
6715
  ];
6716
+ const ears2 = frame.ears;
6717
+ if (ears2 !== void 0 && neck2 === void 0) {
6718
+ const d = ears2.edgeAt(ears2.bottom);
6719
+ at.push(frame.axisX - d, frame.axisX + d);
6720
+ }
6684
6721
  if (neck2 !== void 0) {
6685
6722
  at.push(
6686
6723
  frame.axisX,