@ikijs/editor 0.8.0 → 0.8.1
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.d.mts +12 -6
- package/dist/index.d.ts +12 -6
- package/dist/index.js +73 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1991,6 +1991,7 @@ function meshCellsFor(w, h) {
|
|
|
1991
1991
|
}
|
|
1992
1992
|
var FACE_PLATE_CELLS = 10;
|
|
1993
1993
|
var FEATURE_GRID_CELLS = 4;
|
|
1994
|
+
var MOUTH_GRID_CELL_PX = 32;
|
|
1994
1995
|
var TURN_LATTICE_CELL_PX = 16;
|
|
1995
1996
|
var GRID_MARGIN = 0.12;
|
|
1996
1997
|
var HEAD_CYLINDER_RADIUS_FACTOR = 0.6 / 0.5;
|
|
@@ -2141,31 +2142,33 @@ function turnColumnMap(grid, faceCenterX, radiusX, angleX, travel) {
|
|
|
2141
2142
|
x + boundedCylinderBend(x - faceCenterX, radiusX, theta) + slide
|
|
2142
2143
|
);
|
|
2143
2144
|
}
|
|
2144
|
-
const cellFor = (
|
|
2145
|
+
const cellFor = (x) => {
|
|
2145
2146
|
let lo = 0;
|
|
2146
2147
|
let hi = grid.cols - 1;
|
|
2147
2148
|
while (lo < hi) {
|
|
2148
2149
|
const mid = lo + hi >> 1;
|
|
2149
|
-
if (
|
|
2150
|
+
if (x < restX[mid + 1]) hi = mid;
|
|
2150
2151
|
else lo = mid + 1;
|
|
2151
2152
|
}
|
|
2152
2153
|
return lo;
|
|
2153
2154
|
};
|
|
2154
|
-
const sample = (edges, values, v) => {
|
|
2155
|
-
const c = cellFor(v, edges);
|
|
2156
|
-
const s = Math.max(
|
|
2157
|
-
0,
|
|
2158
|
-
Math.min(1, (v - edges[c]) / (edges[c + 1] - edges[c]))
|
|
2159
|
-
);
|
|
2160
|
-
if (s === 0) return values[c];
|
|
2161
|
-
if (s === 1) return values[c + 1];
|
|
2162
|
-
return values[c] + (values[c + 1] - values[c]) * s;
|
|
2163
|
-
};
|
|
2164
2155
|
return {
|
|
2165
2156
|
restX,
|
|
2166
2157
|
warpedX,
|
|
2167
|
-
|
|
2168
|
-
|
|
2158
|
+
// Piecewise-linear read of `warpedX` over `restX`, the within-cell
|
|
2159
|
+
// fraction clamped to [0,1] as sampleWarpGrid clamps (s, t). A node reads
|
|
2160
|
+
// its own warped x: `warpedX[c] + Δ·1` is `warpedX[c + 1]` only to an
|
|
2161
|
+
// ulp, and the columns a bake reads are nodes.
|
|
2162
|
+
mapX: (x) => {
|
|
2163
|
+
const c = cellFor(x);
|
|
2164
|
+
const s = Math.max(
|
|
2165
|
+
0,
|
|
2166
|
+
Math.min(1, (x - restX[c]) / (restX[c + 1] - restX[c]))
|
|
2167
|
+
);
|
|
2168
|
+
if (s === 0) return warpedX[c];
|
|
2169
|
+
if (s === 1) return warpedX[c + 1];
|
|
2170
|
+
return warpedX[c] + (warpedX[c + 1] - warpedX[c]) * s;
|
|
2171
|
+
}
|
|
2169
2172
|
};
|
|
2170
2173
|
}
|
|
2171
2174
|
function renderedLandingX(part, vertexLanding, px, py) {
|
|
@@ -2271,7 +2274,7 @@ function plateLandingOn(plate, mapAt) {
|
|
|
2271
2274
|
y
|
|
2272
2275
|
);
|
|
2273
2276
|
}
|
|
2274
|
-
function plateGuardRowsFor(face, hairFront) {
|
|
2277
|
+
function plateGuardRowsFor(face, hairFront, widestY = -Infinity) {
|
|
2275
2278
|
const rowsOf = (part, y) => {
|
|
2276
2279
|
const { rows } = meshCellsFor(part.cropW, part.cropH);
|
|
2277
2280
|
return Array.from(
|
|
@@ -2286,7 +2289,7 @@ function plateGuardRowsFor(face, hairFront) {
|
|
|
2286
2289
|
return [
|
|
2287
2290
|
...faceRows,
|
|
2288
2291
|
...rowsOf(hairFront, hairFront.centerY).map(
|
|
2289
|
-
(y) => Math.max(bottom, Math.min(top, y))
|
|
2292
|
+
(y) => Math.max(bottom, Math.min(top, Math.max(y, widestY)))
|
|
2290
2293
|
)
|
|
2291
2294
|
];
|
|
2292
2295
|
}
|
|
@@ -2298,7 +2301,7 @@ function plateGuardsOf(carriers, faceHalfWidth, profile, hairFront) {
|
|
|
2298
2301
|
return {
|
|
2299
2302
|
plate,
|
|
2300
2303
|
edgeAt: profile === void 0 ? () => faceHalfWidth : profile.at,
|
|
2301
|
-
plateGuardRows: plateGuardRowsFor(plate.part, hairFront)
|
|
2304
|
+
plateGuardRows: plateGuardRowsFor(plate.part, hairFront, profile?.widestY)
|
|
2302
2305
|
};
|
|
2303
2306
|
}
|
|
2304
2307
|
var TurnTargetError = class extends Error {
|
|
@@ -2476,14 +2479,15 @@ var TURN_SWEEP_SAMPLES = 32;
|
|
|
2476
2479
|
var HOLD_CLEARANCE = 1;
|
|
2477
2480
|
var TURN_HOLD_SAMPLES = 16;
|
|
2478
2481
|
var TURN_SETTLE_PASSES = 24;
|
|
2479
|
-
function hairFrontHoldTarget(x, y, deg, faceCenterX, plateLandingAt, edgeAt, holdBase, holdEdge) {
|
|
2482
|
+
function hairFrontHoldTarget(x, y, deg, faceCenterX, plateLandingAt, edgeAt, holdBase, holdEdge, widestY = -Infinity) {
|
|
2480
2483
|
const local = x - faceCenterX;
|
|
2481
2484
|
const dist = Math.abs(local);
|
|
2482
2485
|
const side = Math.sign(local);
|
|
2483
|
-
const
|
|
2484
|
-
|
|
2486
|
+
const row = Math.max(y, widestY);
|
|
2487
|
+
const painted = edgeAt(row);
|
|
2488
|
+
if (dist <= painted) return plateLandingAt(deg, x, row);
|
|
2485
2489
|
if (dist <= holdBase) {
|
|
2486
|
-
const inner = plateLandingAt(deg, faceCenterX + side * painted,
|
|
2490
|
+
const inner = plateLandingAt(deg, faceCenterX + side * painted, row);
|
|
2487
2491
|
const u = (dist - painted) / (holdBase - painted);
|
|
2488
2492
|
return inner + (faceCenterX + side * holdEdge - inner) * u;
|
|
2489
2493
|
}
|
|
@@ -2588,7 +2592,8 @@ function evaluateTurnCandidate(ctx, radius) {
|
|
|
2588
2592
|
plateLandingAt,
|
|
2589
2593
|
ctx.edgeAt,
|
|
2590
2594
|
hold.holdBase,
|
|
2591
|
-
hold.holdEdgeAt(deg)
|
|
2595
|
+
hold.holdEdgeAt(deg),
|
|
2596
|
+
ctx.profile?.widestY
|
|
2592
2597
|
),
|
|
2593
2598
|
leadShift
|
|
2594
2599
|
);
|
|
@@ -3563,7 +3568,7 @@ function plateReachAt(plateLandingAt, faceCenterX, edgeAt, plateGuardRows, deg)
|
|
|
3563
3568
|
)
|
|
3564
3569
|
);
|
|
3565
3570
|
}
|
|
3566
|
-
function bakeHairFrontSilhouetteWarp(mesh, partX, partY, faceCenterX, plateLandingAt, edgeAt, holdBase, holdEdgeAt, plateGuardRows) {
|
|
3571
|
+
function bakeHairFrontSilhouetteWarp(mesh, partX, partY, faceCenterX, plateLandingAt, edgeAt, holdBase, holdEdgeAt, plateGuardRows, widestY = -Infinity) {
|
|
3567
3572
|
if (holdEdgeAt(0) !== holdBase) {
|
|
3568
3573
|
throw new Error(
|
|
3569
3574
|
`auto-rig: bakeHairFrontSilhouetteWarp: holdEdgeAt(0) is ${holdEdgeAt(0)}, not the hold edge's own rest distance ${holdBase}, so the bangs would move in the rest pose`
|
|
@@ -3601,7 +3606,8 @@ function bakeHairFrontSilhouetteWarp(mesh, partX, partY, faceCenterX, plateLandi
|
|
|
3601
3606
|
plateLandingAt,
|
|
3602
3607
|
edgeAt,
|
|
3603
3608
|
holdBase,
|
|
3604
|
-
holdEdge
|
|
3609
|
+
holdEdge,
|
|
3610
|
+
widestY
|
|
3605
3611
|
) - x,
|
|
3606
3612
|
0
|
|
3607
3613
|
);
|
|
@@ -3780,7 +3786,7 @@ function defaultPoseOf(bindings) {
|
|
|
3780
3786
|
return binding.from + (binding.to - binding.from) * t;
|
|
3781
3787
|
});
|
|
3782
3788
|
}
|
|
3783
|
-
function groupGridFor(members, cells, turnShiftPx, nodShiftPx) {
|
|
3789
|
+
function groupGridFor(members, cells, turnShiftPx, nodShiftPx, cellPx) {
|
|
3784
3790
|
let minX = Infinity;
|
|
3785
3791
|
let maxX = -Infinity;
|
|
3786
3792
|
let minY = Infinity;
|
|
@@ -3815,24 +3821,50 @@ function groupGridFor(members, cells, turnShiftPx, nodShiftPx) {
|
|
|
3815
3821
|
}
|
|
3816
3822
|
}
|
|
3817
3823
|
}
|
|
3824
|
+
const extentMinX = minX;
|
|
3825
|
+
const extentMaxX = maxX;
|
|
3818
3826
|
minX -= turnShiftPx;
|
|
3819
3827
|
maxX += turnShiftPx;
|
|
3820
3828
|
minY -= nodShiftPx;
|
|
3821
3829
|
maxY += nodShiftPx;
|
|
3822
3830
|
const marginX = (maxX - minX) * GRID_MARGIN + 1;
|
|
3823
3831
|
const marginY = (maxY - minY) * GRID_MARGIN + 1;
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3832
|
+
const points = generateGridPoints(
|
|
3833
|
+
cells,
|
|
3834
|
+
cells,
|
|
3835
|
+
minX - marginX,
|
|
3836
|
+
maxX + marginX,
|
|
3837
|
+
minY - marginY,
|
|
3838
|
+
maxY + marginY
|
|
3839
|
+
);
|
|
3840
|
+
if (cellPx === void 0) return { cols: cells, rows: cells, points };
|
|
3841
|
+
const stride = cells + 1;
|
|
3842
|
+
const uniformXs = Array.from({ length: stride }, (_, c) => points[c * 2]);
|
|
3843
|
+
const ys = Array.from(
|
|
3844
|
+
{ length: stride },
|
|
3845
|
+
(_, r) => points[r * stride * 2 + 1]
|
|
3846
|
+
);
|
|
3847
|
+
const xs = [uniformXs[0]];
|
|
3848
|
+
for (let c = 0; c < cells; c++) {
|
|
3849
|
+
const left = uniformXs[c];
|
|
3850
|
+
const right = uniformXs[c + 1];
|
|
3851
|
+
const from = Math.max(left, extentMinX);
|
|
3852
|
+
const to = Math.min(right, extentMaxX);
|
|
3853
|
+
if (right - left > cellPx && from < to) {
|
|
3854
|
+
const steps = Math.ceil((to - from) / cellPx);
|
|
3855
|
+
if (from > left) xs.push(from);
|
|
3856
|
+
for (let k = 1; k < steps; k++) {
|
|
3857
|
+
xs.push(from + k * (to - from) / steps);
|
|
3858
|
+
}
|
|
3859
|
+
if (to < right) xs.push(to);
|
|
3860
|
+
}
|
|
3861
|
+
xs.push(right);
|
|
3862
|
+
}
|
|
3863
|
+
const merged = [];
|
|
3864
|
+
for (const y of ys) {
|
|
3865
|
+
for (const x of xs) merged.push(x, y);
|
|
3866
|
+
}
|
|
3867
|
+
return { cols: xs.length - 1, rows: cells, points: merged };
|
|
3836
3868
|
}
|
|
3837
3869
|
function eyelidFoldFor(layers, layer, mesh, t) {
|
|
3838
3870
|
const side = ROLE_TABLE[layer.role].eyeSide;
|
|
@@ -3933,7 +3965,8 @@ function turnSetup(layers) {
|
|
|
3933
3965
|
own,
|
|
3934
3966
|
isPlate ? FACE_PLATE_CELLS : FEATURE_GRID_CELLS,
|
|
3935
3967
|
isPlate ? 0 : turnShift[turnFamily(role)],
|
|
3936
|
-
nodShiftPx
|
|
3968
|
+
nodShiftPx,
|
|
3969
|
+
group === "mouthWarp" ? MOUTH_GRID_CELL_PX : void 0
|
|
3937
3970
|
)
|
|
3938
3971
|
);
|
|
3939
3972
|
}
|
|
@@ -4273,7 +4306,8 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
|
|
|
4273
4306
|
edgeAt,
|
|
4274
4307
|
holdBase,
|
|
4275
4308
|
turn?.holdEdgeAt ?? (() => holdBase),
|
|
4276
|
-
plateGuardRows
|
|
4309
|
+
plateGuardRows,
|
|
4310
|
+
profile?.widestY
|
|
4277
4311
|
)
|
|
4278
4312
|
);
|
|
4279
4313
|
ownWarps.push(
|