@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/README.md +2 -2
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +45 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +45 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ edge further outside the back hair painted behind it than the nod alone does —
|
|
|
78
78
|
and the back hair stays behind; the neck and the
|
|
79
79
|
ears the face layer paints are cut off into islands of the plate's own mesh,
|
|
80
80
|
drawn behind the head — the neck stays (only the chin's shade slides across
|
|
81
|
-
it), the ears lag the face, the far one
|
|
81
|
+
it), the ears lag the face, the far one held while the head slides partly over it (about half of an ear of the default size). AngleZ rolls the head 14° about the chin.
|
|
82
82
|
A `body` rides a body warp that breathes, follows the head's turn and tilt a
|
|
83
83
|
little and turns on `ParamBodyAngleX/Y/Z`, its legs planted, and the head
|
|
84
84
|
hangs from it. `arm_L` / `arm_R`, each a whole arm drawn hanging with its
|
|
@@ -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
|
@@ -2064,7 +2064,8 @@ var PROFILE_VALUES = {
|
|
|
2064
2064
|
hairFollow: 1,
|
|
2065
2065
|
fore: 0.2,
|
|
2066
2066
|
backShare: 0.1,
|
|
2067
|
-
earFar: 0
|
|
2067
|
+
earFar: 0,
|
|
2068
|
+
earFore: 0.1,
|
|
2068
2069
|
nodDown: 0.18,
|
|
2069
2070
|
nodUp: 0.1,
|
|
2070
2071
|
nodLead: 0.06,
|
|
@@ -2131,7 +2132,7 @@ function deriveProfile(v) {
|
|
|
2131
2132
|
earNear: 1,
|
|
2132
2133
|
/** The far ear's width at full turn, about its outer edge, where the head
|
|
2133
2134
|
* leaves it room; less where it does not. */
|
|
2134
|
-
earFarScale: 1 - v.
|
|
2135
|
+
earFarScale: 1 - v.earFore
|
|
2135
2136
|
};
|
|
2136
2137
|
const mid = v.nodDown * (1 + v.chinShare) / 2;
|
|
2137
2138
|
const feature = (depth) => ({
|
|
@@ -3024,6 +3025,7 @@ function mouthAnchor(byRole) {
|
|
|
3024
3025
|
}
|
|
3025
3026
|
|
|
3026
3027
|
// src/auto-rig/head.ts
|
|
3028
|
+
var EAR_EDGE = 3;
|
|
3027
3029
|
function outerEdge(runs, axisX, side) {
|
|
3028
3030
|
if (runs.length === 0) return void 0;
|
|
3029
3031
|
const x = side > 0 ? runs[runs.length - 1] : runs[0];
|
|
@@ -3057,7 +3059,11 @@ function findEars(raw, wMax, firstRow, lastRow, minRows, maxRows) {
|
|
|
3057
3059
|
if (raw[t] - raw[t - EAR_ROWS] < step) continue;
|
|
3058
3060
|
for (let b = t + minRows; b <= Math.min(lastRow, t + maxRows); b++) {
|
|
3059
3061
|
if (raw[b - EAR_ROWS] - raw[b] >= step) {
|
|
3060
|
-
|
|
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 };
|
|
3061
3067
|
}
|
|
3062
3068
|
}
|
|
3063
3069
|
return void 0;
|
|
@@ -3135,6 +3141,7 @@ function buildHeadFrame(layers, opts) {
|
|
|
3135
3141
|
return rows[i] + (rows[j] - rows[i]) * clamp(r - i, 0, 1);
|
|
3136
3142
|
};
|
|
3137
3143
|
const rawRows = raw;
|
|
3144
|
+
let earRows;
|
|
3138
3145
|
const earless = (chin) => {
|
|
3139
3146
|
const rowOf = (y) => Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);
|
|
3140
3147
|
const span3 = Math.max(1, eyeY - chin);
|
|
@@ -3157,8 +3164,10 @@ function buildHeadFrame(layers, opts) {
|
|
|
3157
3164
|
top: rowY(top) + 0.5,
|
|
3158
3165
|
bottom: rowY(bottom) - 0.5,
|
|
3159
3166
|
attachAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)),
|
|
3160
|
-
outer
|
|
3167
|
+
outer,
|
|
3168
|
+
edgeAt: (y) => attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)) + EAR_EDGE
|
|
3161
3169
|
};
|
|
3170
|
+
earRows = { top, bottom };
|
|
3162
3171
|
return smoothProfile(
|
|
3163
3172
|
rawRows.map((v, r) => r > top && r < bottom ? attach(r) : v)
|
|
3164
3173
|
);
|
|
@@ -3280,9 +3289,13 @@ function buildHeadFrame(layers, opts) {
|
|
|
3280
3289
|
headHalfAt = readRows(head);
|
|
3281
3290
|
headMax = Math.max(...head);
|
|
3282
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
|
+
);
|
|
3283
3296
|
const bottomOf = (d) => {
|
|
3284
|
-
for (let r =
|
|
3285
|
-
if (
|
|
3297
|
+
for (let r = edge.length - 1; r >= 0; r--) {
|
|
3298
|
+
if (edge[r] >= d) return rowY(r) - 0.5;
|
|
3286
3299
|
}
|
|
3287
3300
|
return face.y1;
|
|
3288
3301
|
};
|
|
@@ -3482,7 +3495,7 @@ function earField(m) {
|
|
|
3482
3495
|
const attach = ears.attachAt(y);
|
|
3483
3496
|
const span3 = Math.max(1, ears.outer - attach);
|
|
3484
3497
|
if (sideOf(m, x, s) === "far") {
|
|
3485
|
-
const rim2 =
|
|
3498
|
+
const rim2 = m.earFar * m.face;
|
|
3486
3499
|
const root2 = earRoot(m, face, y, s);
|
|
3487
3500
|
const lead = Math.max(
|
|
3488
3501
|
0,
|
|
@@ -3507,7 +3520,7 @@ function farEarCovered(m) {
|
|
|
3507
3520
|
const ears = m.frame.ears;
|
|
3508
3521
|
if (ears === void 0) return true;
|
|
3509
3522
|
const face = faceField(m);
|
|
3510
|
-
const rim =
|
|
3523
|
+
const rim = m.earFar * m.face;
|
|
3511
3524
|
const y0 = ears.bottom - 2;
|
|
3512
3525
|
const y1 = ears.top + 2;
|
|
3513
3526
|
const n = Math.max(1, Math.ceil(y1 - y0));
|
|
@@ -4348,6 +4361,7 @@ function fitTurn(ctx, targets, plan, build) {
|
|
|
4348
4361
|
lead: plan.turn.featureLead,
|
|
4349
4362
|
follow: plan.hair.follow,
|
|
4350
4363
|
outline: plan.hair.outlineFollow,
|
|
4364
|
+
earFar: plan.turn.farEar,
|
|
4351
4365
|
fore: targets.farEyeRatio === void 0 ? plan.turn.eyeForeshorten : 1,
|
|
4352
4366
|
shell: 1,
|
|
4353
4367
|
noseLead: targets.noseShift !== void 0 || plan.turn.noseLead === 1 ? void 0 : plan.turn.noseLead
|
|
@@ -4584,6 +4598,7 @@ function buildTurn(frame, landmarks, q, turn) {
|
|
|
4584
4598
|
hairOuter: q.outline * face,
|
|
4585
4599
|
hairBack: A * hh * turn.hairBack,
|
|
4586
4600
|
shellScale: q.shell,
|
|
4601
|
+
earFar: q.earFar,
|
|
4587
4602
|
earFarScale: 1 + A * (turn.earFarScale - 1),
|
|
4588
4603
|
...landmarks
|
|
4589
4604
|
};
|
|
@@ -4671,6 +4686,23 @@ var RIG_PLAN_FIELDS = [
|
|
|
4671
4686
|
migratedFrom: null,
|
|
4672
4687
|
what: "how far the nose leads the face plate on the turn \u2014 turn only, the nod keeps the profile's nose depth"
|
|
4673
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
|
+
},
|
|
4674
4706
|
{
|
|
4675
4707
|
path: "hair.follow",
|
|
4676
4708
|
group: "hair",
|
|
@@ -6757,6 +6789,11 @@ function buildFaceMesh(frame, b, head, neckCells) {
|
|
|
6757
6789
|
frame.axisX - frame.headMax + 0.5,
|
|
6758
6790
|
frame.axisX + frame.headMax - 0.5
|
|
6759
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
|
+
}
|
|
6760
6797
|
if (neck2 !== void 0) {
|
|
6761
6798
|
at.push(
|
|
6762
6799
|
frame.axisX,
|