@ikijs/editor 0.7.0 → 0.8.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
@@ -1776,6 +1776,45 @@ function validateLayerInputs(layers, canvas) {
1776
1776
  }
1777
1777
  }
1778
1778
  }
1779
+ if (layer.denseCore !== void 0) {
1780
+ const where = `auto-rig: validateLayerInputs: role "${role}" denseCore`;
1781
+ const core = layer.denseCore;
1782
+ if (typeof core !== "object" || core === null || Array.isArray(core)) {
1783
+ throw new Error(`${where} must be a plain object { x, y, w, h }`);
1784
+ }
1785
+ for (const field of ["x", "y", "w", "h"]) {
1786
+ const v = core[field];
1787
+ const size = field === "w" || field === "h";
1788
+ if (typeof v !== "number" || !Number.isFinite(v) || size && v <= 0) {
1789
+ throw new Error(
1790
+ `${where}.${field} is ${String(v)}, not a finite number${size ? " > 0" : ""}`
1791
+ );
1792
+ }
1793
+ }
1794
+ const { x, y, w, h } = layer.denseCore;
1795
+ const right = bbox.x + bbox.w;
1796
+ const bottom = bbox.y + bbox.h;
1797
+ if (x < bbox.x) {
1798
+ throw new Error(
1799
+ `${where}.x (${x}) lies left of the bbox's left edge (${bbox.x})`
1800
+ );
1801
+ }
1802
+ if (y < bbox.y) {
1803
+ throw new Error(
1804
+ `${where}.y (${y}) lies above the bbox's top edge (${bbox.y})`
1805
+ );
1806
+ }
1807
+ if (x + w > right) {
1808
+ throw new Error(
1809
+ `${where}.w (${w}) puts its right edge at ${x + w}, past the bbox's right edge (${right})`
1810
+ );
1811
+ }
1812
+ if (y + h > bottom) {
1813
+ throw new Error(
1814
+ `${where}.h (${h}) puts its bottom edge at ${y + h}, past the bbox's bottom edge (${bottom})`
1815
+ );
1816
+ }
1817
+ }
1779
1818
  }
1780
1819
  }
1781
1820
  function validateStrandEdges(layers, strandEdges) {
@@ -2330,12 +2369,17 @@ function resolveTurnTargets(targets = {}) {
2330
2369
  defaulted
2331
2370
  };
2332
2371
  }
2372
+ function noseDrawnBox(layer) {
2373
+ return layer.denseCore ?? layer.bbox;
2374
+ }
2333
2375
  function turnLandmarks(layers, carriers) {
2334
2376
  const markOf = (role) => {
2335
2377
  const layer = layers.find((l) => l.role === role);
2336
2378
  if (!layer) return void 0;
2337
- const t = bboxToTransform(layer.bbox, layer.canvasW, layer.canvasH, role);
2338
- const mark = { x: t.x, y: t.y, w: layer.cropW };
2379
+ const drawn = role === "nose" ? noseDrawnBox(layer) : layer.bbox;
2380
+ const t = bboxToTransform(drawn, layer.canvasW, layer.canvasH, role);
2381
+ const w = drawn === layer.bbox ? layer.cropW : drawn.w;
2382
+ const mark = { x: t.x, y: t.y, w };
2339
2383
  const carrier = carriers?.get(role);
2340
2384
  if (carrier !== void 0) mark.carrier = carrier;
2341
2385
  return mark;
@@ -3286,6 +3330,7 @@ function solveTurnModel(targets, landmarks, lattice, faceCenterX, faceHalfWidth,
3286
3330
  var EYE_STACK_PREFIXES = ["eye_", "iris_", "pupil_", "highlight_"];
3287
3331
  var HAIR_FRONT_DEPTH = 0.1;
3288
3332
  var MOUTH_TURN_TILT_DEG = 5;
3333
+ var NOSE_TURN_TILT_DEG = 6;
3289
3334
  var NOD_TRAVEL = 30;
3290
3335
  var NOD_BEND = 0.5;
3291
3336
  var HAIR_BACK_NOD_DEPTH = -0.135;
@@ -3898,11 +3943,31 @@ function turnSetup(layers) {
3898
3943
  y: mouthAt.y,
3899
3944
  tiltDeg: MOUTH_TURN_TILT_DEG
3900
3945
  };
3946
+ const noseLayer = layers.find((l) => l.role === "nose");
3947
+ let noseAnchor;
3948
+ if (noseLayer) {
3949
+ const drawn = noseDrawnBox(noseLayer);
3950
+ const at = bboxToTransform(
3951
+ drawn,
3952
+ noseLayer.canvasW,
3953
+ noseLayer.canvasH,
3954
+ "nose"
3955
+ );
3956
+ noseAnchor = {
3957
+ x: at.x,
3958
+ y: at.y + drawn.h / 2,
3959
+ tiltDeg: NOSE_TURN_TILT_DEG
3960
+ };
3961
+ }
3901
3962
  const carriers = new Map(
3902
- members.map((m) => [
3903
- m.role,
3904
- m.group === "mouthWarp" ? { grid: groupGrids.get(m.group), part: m.part, anchor: mouthAnchor } : { grid: groupGrids.get(m.group), part: m.part }
3905
- ])
3963
+ members.map((m) => {
3964
+ const grid = groupGrids.get(m.group);
3965
+ const anchor = m.group === "mouthWarp" ? mouthAnchor : m.group === "noseWarp" ? noseAnchor : void 0;
3966
+ return [
3967
+ m.role,
3968
+ anchor === void 0 ? { grid, part: m.part } : { grid, part: m.part, anchor }
3969
+ ];
3970
+ })
3906
3971
  );
3907
3972
  const maxShift = Math.max(turnShift.eye, turnShift.nose, turnShift.mouth);
3908
3973
  let reach = 0;