@ikijs/editor 0.32.1 → 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/README.md +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +42 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ the turn's amount, the eyes' foreshortening, the hair's width, a feature's own
|
|
|
97
97
|
shift. With none given the profile itself renders (`DEFAULT_TURN_TARGETS`
|
|
98
98
|
expresses it in the cues' units). `options.rigPlan` tunes a character from the
|
|
99
99
|
profile in three groups (`turn`, `hair`, `eyes`: the whole turn, the
|
|
100
|
-
features' lead, the front hair's follow and its outline's, the blink and the
|
|
100
|
+
features' lead, the far ear's follow, the front hair's follow and its outline's, the blink and the
|
|
101
101
|
hair sway), validated against `RIG_PLAN_FIELDS`. `options.patches` adds displacements to a generated rig's keyform
|
|
102
102
|
stops (`RigPatch`), replayed on every rig and reported through
|
|
103
103
|
`options.onPatchesApplied`; a refused op throws `PatchError`. `options.customParts` adds parts the
|
package/dist/index.d.mts
CHANGED
|
@@ -709,6 +709,9 @@ interface RigPlan {
|
|
|
709
709
|
/** How far the nose leads the plate (turn only — the nod keeps the
|
|
710
710
|
* profile's nose depth). */
|
|
711
711
|
noseLead?: number;
|
|
712
|
+
/** How far the far ear's outer edge follows the face (0: it holds and
|
|
713
|
+
* the head slides over it; 1: it rides with the face and stays whole). */
|
|
714
|
+
farEar?: number;
|
|
712
715
|
};
|
|
713
716
|
hair?: {
|
|
714
717
|
/** The front hair's share of the face's turn. */
|
package/dist/index.d.ts
CHANGED
|
@@ -709,6 +709,9 @@ interface RigPlan {
|
|
|
709
709
|
/** How far the nose leads the plate (turn only — the nod keeps the
|
|
710
710
|
* profile's nose depth). */
|
|
711
711
|
noseLead?: number;
|
|
712
|
+
/** How far the far ear's outer edge follows the face (0: it holds and
|
|
713
|
+
* the head slides over it; 1: it rides with the face and stays whole). */
|
|
714
|
+
farEar?: number;
|
|
712
715
|
};
|
|
713
716
|
hair?: {
|
|
714
717
|
/** The front hair's share of the face's turn. */
|
package/dist/index.js
CHANGED
|
@@ -3025,6 +3025,7 @@ function mouthAnchor(byRole) {
|
|
|
3025
3025
|
}
|
|
3026
3026
|
|
|
3027
3027
|
// src/auto-rig/head.ts
|
|
3028
|
+
var EAR_EDGE = 3;
|
|
3028
3029
|
function outerEdge(runs, axisX, side) {
|
|
3029
3030
|
if (runs.length === 0) return void 0;
|
|
3030
3031
|
const x = side > 0 ? runs[runs.length - 1] : runs[0];
|
|
@@ -3058,7 +3059,11 @@ function findEars(raw, wMax, firstRow, lastRow, minRows, maxRows) {
|
|
|
3058
3059
|
if (raw[t] - raw[t - EAR_ROWS] < step) continue;
|
|
3059
3060
|
for (let b = t + minRows; b <= Math.min(lastRow, t + maxRows); b++) {
|
|
3060
3061
|
if (raw[b - EAR_ROWS] - raw[b] >= step) {
|
|
3061
|
-
|
|
3062
|
+
let end = b;
|
|
3063
|
+
for (let k = b + 1; k <= Math.min(lastRow, b + minRows); k++) {
|
|
3064
|
+
if (raw[k - EAR_ROWS] - raw[k] >= step) end = k;
|
|
3065
|
+
}
|
|
3066
|
+
return { top: t - EAR_ROWS, bottom: end };
|
|
3062
3067
|
}
|
|
3063
3068
|
}
|
|
3064
3069
|
return void 0;
|
|
@@ -3136,6 +3141,7 @@ function buildHeadFrame(layers, opts) {
|
|
|
3136
3141
|
return rows[i] + (rows[j] - rows[i]) * clamp(r - i, 0, 1);
|
|
3137
3142
|
};
|
|
3138
3143
|
const rawRows = raw;
|
|
3144
|
+
let earRows;
|
|
3139
3145
|
const earless = (chin) => {
|
|
3140
3146
|
const rowOf = (y) => Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);
|
|
3141
3147
|
const span3 = Math.max(1, eyeY - chin);
|
|
@@ -3158,8 +3164,10 @@ function buildHeadFrame(layers, opts) {
|
|
|
3158
3164
|
top: rowY(top) + 0.5,
|
|
3159
3165
|
bottom: rowY(bottom) - 0.5,
|
|
3160
3166
|
attachAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)),
|
|
3161
|
-
outer
|
|
3167
|
+
outer,
|
|
3168
|
+
edgeAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)) + EAR_EDGE
|
|
3162
3169
|
};
|
|
3170
|
+
earRows = { top, bottom };
|
|
3163
3171
|
return smoothProfile(
|
|
3164
3172
|
rawRows.map((v, r) => r > top && r < bottom ? attach(r) : v)
|
|
3165
3173
|
);
|
|
@@ -3281,9 +3289,13 @@ function buildHeadFrame(layers, opts) {
|
|
|
3281
3289
|
headHalfAt = readRows(head);
|
|
3282
3290
|
headMax = Math.max(...head);
|
|
3283
3291
|
if (ears !== void 0) {
|
|
3292
|
+
const band = earRows;
|
|
3293
|
+
const edge = head.map(
|
|
3294
|
+
(w, r) => r >= band.top && r <= band.bottom ? w + EAR_EDGE : w
|
|
3295
|
+
);
|
|
3284
3296
|
const bottomOf = (d) => {
|
|
3285
|
-
for (let r =
|
|
3286
|
-
if (
|
|
3297
|
+
for (let r = edge.length - 1; r >= 0; r--) {
|
|
3298
|
+
if (edge[r] >= d) return rowY(r) - 0.5;
|
|
3287
3299
|
}
|
|
3288
3300
|
return face.y1;
|
|
3289
3301
|
};
|
|
@@ -3483,7 +3495,7 @@ function earField(m) {
|
|
|
3483
3495
|
const attach = ears.attachAt(y);
|
|
3484
3496
|
const span3 = Math.max(1, ears.outer - attach);
|
|
3485
3497
|
if (sideOf(m, x, s) === "far") {
|
|
3486
|
-
const rim2 =
|
|
3498
|
+
const rim2 = m.earFar * m.face;
|
|
3487
3499
|
const root2 = earRoot(m, face, y, s);
|
|
3488
3500
|
const lead = Math.max(
|
|
3489
3501
|
0,
|
|
@@ -3508,7 +3520,7 @@ function farEarCovered(m) {
|
|
|
3508
3520
|
const ears = m.frame.ears;
|
|
3509
3521
|
if (ears === void 0) return true;
|
|
3510
3522
|
const face = faceField(m);
|
|
3511
|
-
const rim =
|
|
3523
|
+
const rim = m.earFar * m.face;
|
|
3512
3524
|
const y0 = ears.bottom - 2;
|
|
3513
3525
|
const y1 = ears.top + 2;
|
|
3514
3526
|
const n = Math.max(1, Math.ceil(y1 - y0));
|
|
@@ -4349,6 +4361,7 @@ function fitTurn(ctx, targets, plan, build) {
|
|
|
4349
4361
|
lead: plan.turn.featureLead,
|
|
4350
4362
|
follow: plan.hair.follow,
|
|
4351
4363
|
outline: plan.hair.outlineFollow,
|
|
4364
|
+
earFar: plan.turn.farEar,
|
|
4352
4365
|
fore: targets.farEyeRatio === void 0 ? plan.turn.eyeForeshorten : 1,
|
|
4353
4366
|
shell: 1,
|
|
4354
4367
|
noseLead: targets.noseShift !== void 0 || plan.turn.noseLead === 1 ? void 0 : plan.turn.noseLead
|
|
@@ -4585,6 +4598,7 @@ function buildTurn(frame, landmarks, q, turn) {
|
|
|
4585
4598
|
hairOuter: q.outline * face,
|
|
4586
4599
|
hairBack: A * hh * turn.hairBack,
|
|
4587
4600
|
shellScale: q.shell,
|
|
4601
|
+
earFar: q.earFar,
|
|
4588
4602
|
earFarScale: 1 + A * (turn.earFarScale - 1),
|
|
4589
4603
|
...landmarks
|
|
4590
4604
|
};
|
|
@@ -4672,6 +4686,23 @@ var RIG_PLAN_FIELDS = [
|
|
|
4672
4686
|
migratedFrom: null,
|
|
4673
4687
|
what: "how far the nose leads the face plate on the turn \u2014 turn only, the nod keeps the profile's nose depth"
|
|
4674
4688
|
},
|
|
4689
|
+
{
|
|
4690
|
+
path: "turn.farEar",
|
|
4691
|
+
group: "turn",
|
|
4692
|
+
key: "farEar",
|
|
4693
|
+
kind: "absolute",
|
|
4694
|
+
unit: "share of the face plate's slide",
|
|
4695
|
+
default: PROFILE.TURN.earFar,
|
|
4696
|
+
range: [0, 1],
|
|
4697
|
+
recommended: [0, 0.5],
|
|
4698
|
+
step: 0.1,
|
|
4699
|
+
poses: TURN_POSES,
|
|
4700
|
+
cue: null,
|
|
4701
|
+
fitBy: null,
|
|
4702
|
+
provisional: false,
|
|
4703
|
+
migratedFrom: null,
|
|
4704
|
+
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)"
|
|
4705
|
+
},
|
|
4675
4706
|
{
|
|
4676
4707
|
path: "hair.follow",
|
|
4677
4708
|
group: "hair",
|
|
@@ -6758,6 +6789,11 @@ function buildFaceMesh(frame, b, head, neckCells) {
|
|
|
6758
6789
|
frame.axisX - frame.headMax + 0.5,
|
|
6759
6790
|
frame.axisX + frame.headMax - 0.5
|
|
6760
6791
|
];
|
|
6792
|
+
const ears2 = frame.ears;
|
|
6793
|
+
if (ears2 !== void 0 && neck2 === void 0) {
|
|
6794
|
+
const d = ears2.edgeAt(ears2.bottom);
|
|
6795
|
+
at.push(frame.axisX - d, frame.axisX + d);
|
|
6796
|
+
}
|
|
6761
6797
|
if (neck2 !== void 0) {
|
|
6762
6798
|
at.push(
|
|
6763
6799
|
frame.axisX,
|