@ikijs/editor 0.17.0 → 0.18.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 +13 -13
- package/dist/index.d.mts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +268 -266
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +273 -272
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2105,267 +2105,14 @@ var DEFAULT_TURN_TARGETS = Object.freeze({
|
|
|
2105
2105
|
silhouetteRatio: 1
|
|
2106
2106
|
});
|
|
2107
2107
|
|
|
2108
|
-
// src/auto-rig/roles.ts
|
|
2109
|
-
var ROLE_TABLE = [
|
|
2110
|
-
{ role: "hair_back", family: "hair_back" },
|
|
2111
|
-
{ role: "body", family: "body" },
|
|
2112
|
-
{ role: "arm_L", family: "arm", parts: ["arm_L", "forearm_L"] },
|
|
2113
|
-
{ role: "arm_R", family: "arm", parts: ["arm_R", "forearm_R"] },
|
|
2114
|
-
{ role: "face", family: "face", required: true },
|
|
2115
|
-
{ role: "blush_L", family: "face" },
|
|
2116
|
-
{ role: "blush_R", family: "face" },
|
|
2117
|
-
{ role: "nose", family: "nose" },
|
|
2118
|
-
{ role: "mouth", family: "mouth", required: true },
|
|
2119
|
-
{ role: "mouth_open", family: "mouth" },
|
|
2120
|
-
{ role: "eye_L", family: "eye_L", required: true },
|
|
2121
|
-
{ role: "eye_R", family: "eye_R", required: true },
|
|
2122
|
-
{ role: "iris_L", family: "eye_L" },
|
|
2123
|
-
{ role: "iris_R", family: "eye_R" },
|
|
2124
|
-
{ role: "pupil_L", family: "eye_L" },
|
|
2125
|
-
{ role: "pupil_R", family: "eye_R" },
|
|
2126
|
-
{ role: "highlight_L", family: "eye_L" },
|
|
2127
|
-
{ role: "highlight_R", family: "eye_R" },
|
|
2128
|
-
{ role: "lash_lower_L", family: "eye_L" },
|
|
2129
|
-
{ role: "lash_lower_R", family: "eye_R" },
|
|
2130
|
-
{ role: "lash_L", family: "eye_L" },
|
|
2131
|
-
{ role: "lash_R", family: "eye_R" },
|
|
2132
|
-
{ role: "brow_L", family: "brow_L" },
|
|
2133
|
-
{ role: "brow_R", family: "brow_R" },
|
|
2134
|
-
{ role: "hair_front", family: "hair_front" }
|
|
2135
|
-
];
|
|
2136
|
-
var REQUIRED_ROLES = ROLE_TABLE.filter(
|
|
2137
|
-
(r) => r.required
|
|
2138
|
-
).map((r) => r.role);
|
|
2139
|
-
var SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));
|
|
2140
|
-
function roleSpec(role) {
|
|
2141
|
-
const spec = SPEC_BY_ROLE.get(role);
|
|
2142
|
-
if (spec === void 0) throw new Error(`auto-rig: unknown role "${role}"`);
|
|
2143
|
-
return spec;
|
|
2144
|
-
}
|
|
2145
|
-
function partIdsOfRole(role) {
|
|
2146
|
-
return roleSpec(role).parts ?? [role];
|
|
2147
|
-
}
|
|
2148
|
-
var ROLE_BY_PART = new Map(
|
|
2149
|
-
ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role]))
|
|
2150
|
-
);
|
|
2151
|
-
function roleOfPart(partId) {
|
|
2152
|
-
return ROLE_BY_PART.get(partId) ?? partId;
|
|
2153
|
-
}
|
|
2154
|
-
var ALIASES = {
|
|
2155
|
-
eyebrow_L: "brow_L",
|
|
2156
|
-
eyebrow_R: "brow_R",
|
|
2157
|
-
eye_white_L: "eye_L",
|
|
2158
|
-
eye_white_R: "eye_R"
|
|
2159
|
-
};
|
|
2160
|
-
function roleOf(fileName) {
|
|
2161
|
-
const role = fileName.replace(/\.[^.]+$/, "").toLowerCase().replace(/[-\s]+/g, "_").replace(/_([lr])$/, (_, s) => `_${s.toUpperCase()}`);
|
|
2162
|
-
return ALIASES[role] ?? role;
|
|
2163
|
-
}
|
|
2164
|
-
function checkArmsHaveBody(roles) {
|
|
2165
|
-
const has = new Set(roles);
|
|
2166
|
-
if (has.has("body")) return;
|
|
2167
|
-
const arm = ROLE_TABLE.find((r) => r.family === "arm" && has.has(r.role));
|
|
2168
|
-
if (arm !== void 0) {
|
|
2169
|
-
throw new Error(
|
|
2170
|
-
`auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`
|
|
2171
|
-
);
|
|
2172
|
-
}
|
|
2173
|
-
}
|
|
2174
|
-
function parseLayerRoles(fileNames) {
|
|
2175
|
-
const seen = /* @__PURE__ */ new Map();
|
|
2176
|
-
const out = [];
|
|
2177
|
-
for (const fileName of fileNames) {
|
|
2178
|
-
const role = roleOf(fileName);
|
|
2179
|
-
if (!SPEC_BY_ROLE.has(role)) {
|
|
2180
|
-
throw new Error(
|
|
2181
|
-
`auto-rig: "${fileName}" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(", ")})`
|
|
2182
|
-
);
|
|
2183
|
-
}
|
|
2184
|
-
const prior = seen.get(role);
|
|
2185
|
-
if (prior !== void 0) {
|
|
2186
|
-
throw new Error(
|
|
2187
|
-
`auto-rig: role "${role}" is named twice ("${prior}" and "${fileName}")`
|
|
2188
|
-
);
|
|
2189
|
-
}
|
|
2190
|
-
seen.set(role, fileName);
|
|
2191
|
-
out.push({ role, fileName });
|
|
2192
|
-
}
|
|
2193
|
-
const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));
|
|
2194
|
-
if (missing.length > 0) {
|
|
2195
|
-
throw new Error(
|
|
2196
|
-
`auto-rig: missing required role${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`
|
|
2197
|
-
);
|
|
2198
|
-
}
|
|
2199
|
-
checkArmsHaveBody(seen.keys());
|
|
2200
|
-
return out;
|
|
2201
|
-
}
|
|
2202
|
-
|
|
2203
|
-
// src/auto-rig/generate.ts
|
|
2204
|
-
import {
|
|
2205
|
-
IKI_FORMAT_VERSION as IKI_FORMAT_VERSION2,
|
|
2206
|
-
StandardParameter as P6,
|
|
2207
|
-
parseIkiModel as parseIkiModel3
|
|
2208
|
-
} from "@ikijs/format";
|
|
2209
|
-
|
|
2210
|
-
// src/auto-rig/animations.ts
|
|
2211
|
-
import {
|
|
2212
|
-
StandardParameter as P
|
|
2213
|
-
} from "@ikijs/format";
|
|
2214
|
-
function browsY(y) {
|
|
2215
|
-
return [
|
|
2216
|
-
{ parameter: P.BrowLeftY, value: y, blend: "add" },
|
|
2217
|
-
{ parameter: P.BrowRightY, value: y, blend: "add" }
|
|
2218
|
-
];
|
|
2219
|
-
}
|
|
2220
|
-
function browsTilt(innerDown) {
|
|
2221
|
-
return [
|
|
2222
|
-
{ parameter: P.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
2223
|
-
{ parameter: P.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
2224
|
-
];
|
|
2225
|
-
}
|
|
2226
|
-
function cheek(value) {
|
|
2227
|
-
return { parameter: P.Cheek, value, blend: "add" };
|
|
2228
|
-
}
|
|
2229
|
-
var BROWS = [P.BrowLeftY, P.BrowRightY, P.BrowLeftAngle, P.BrowRightAngle];
|
|
2230
|
-
var EXPRESSIONS = [
|
|
2231
|
-
{
|
|
2232
|
-
id: "smile",
|
|
2233
|
-
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
2234
|
-
parameters: [
|
|
2235
|
-
{ parameter: P.MouthForm, value: 1, blend: "add" },
|
|
2236
|
-
...browsY(0.25),
|
|
2237
|
-
cheek(0.4)
|
|
2238
|
-
]
|
|
2239
|
-
},
|
|
2240
|
-
{
|
|
2241
|
-
id: "laugh",
|
|
2242
|
-
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
2243
|
-
parameters: [
|
|
2244
|
-
{ parameter: P.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
2245
|
-
{ parameter: P.EyeOpenRight, value: 0, blend: "multiply" },
|
|
2246
|
-
{ parameter: P.MouthForm, value: 1, blend: "add" },
|
|
2247
|
-
{ parameter: P.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
2248
|
-
...browsY(0.4),
|
|
2249
|
-
cheek(0.65)
|
|
2250
|
-
]
|
|
2251
|
-
},
|
|
2252
|
-
{
|
|
2253
|
-
id: "angry",
|
|
2254
|
-
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
2255
|
-
needs: BROWS,
|
|
2256
|
-
parameters: [
|
|
2257
|
-
...browsY(-0.5),
|
|
2258
|
-
...browsTilt(0.8),
|
|
2259
|
-
{ parameter: P.MouthForm, value: -0.9, blend: "add" }
|
|
2260
|
-
]
|
|
2261
|
-
},
|
|
2262
|
-
{
|
|
2263
|
-
id: "sad",
|
|
2264
|
-
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
2265
|
-
needs: BROWS,
|
|
2266
|
-
parameters: [
|
|
2267
|
-
...browsY(0.35),
|
|
2268
|
-
...browsTilt(-0.8),
|
|
2269
|
-
{ parameter: P.MouthForm, value: -0.8, blend: "add" }
|
|
2270
|
-
]
|
|
2271
|
-
},
|
|
2272
|
-
{
|
|
2273
|
-
id: "surprised",
|
|
2274
|
-
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
2275
|
-
parameters: [
|
|
2276
|
-
...browsY(0.8),
|
|
2277
|
-
{ parameter: P.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
2278
|
-
]
|
|
2279
|
-
},
|
|
2280
|
-
{
|
|
2281
|
-
id: "shy",
|
|
2282
|
-
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
2283
|
-
needs: [P.Cheek],
|
|
2284
|
-
parameters: [
|
|
2285
|
-
cheek(1),
|
|
2286
|
-
// Gaze down.
|
|
2287
|
-
{ parameter: P.EyeballY, value: -0.65, blend: "add" },
|
|
2288
|
-
{ parameter: P.MouthForm, value: 0.4, blend: "add" },
|
|
2289
|
-
...browsTilt(-0.25)
|
|
2290
|
-
]
|
|
2291
|
-
}
|
|
2292
|
-
];
|
|
2293
|
-
function defaultExpressions(declared) {
|
|
2294
|
-
return EXPRESSIONS.filter(
|
|
2295
|
-
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
2296
|
-
).map(({ needs: _needs, ...e }) => ({
|
|
2297
|
-
...e,
|
|
2298
|
-
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
2299
|
-
}));
|
|
2300
|
-
}
|
|
2301
|
-
var DEFAULT_MOTIONS = {
|
|
2302
|
-
Nod: [
|
|
2303
|
-
{
|
|
2304
|
-
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
2305
|
-
duration: 1,
|
|
2306
|
-
curves: [
|
|
2307
|
-
{
|
|
2308
|
-
parameter: P.AngleY,
|
|
2309
|
-
keys: [
|
|
2310
|
-
[0, 0],
|
|
2311
|
-
[0.3, -18],
|
|
2312
|
-
[0.6, 4],
|
|
2313
|
-
[0.8, -1],
|
|
2314
|
-
[1, 0]
|
|
2315
|
-
]
|
|
2316
|
-
}
|
|
2317
|
-
]
|
|
2318
|
-
}
|
|
2319
|
-
],
|
|
2320
|
-
Shake: [
|
|
2321
|
-
{
|
|
2322
|
-
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
2323
|
-
duration: 1.2,
|
|
2324
|
-
// The first swing peaks at 0.2 s, which the default fade would still
|
|
2325
|
-
// be damping.
|
|
2326
|
-
fadeIn: 0.15,
|
|
2327
|
-
curves: [
|
|
2328
|
-
{
|
|
2329
|
-
parameter: P.AngleX,
|
|
2330
|
-
keys: [
|
|
2331
|
-
[0, 0],
|
|
2332
|
-
[0.2, -18],
|
|
2333
|
-
[0.45, 18],
|
|
2334
|
-
[0.7, -16],
|
|
2335
|
-
[0.95, 10],
|
|
2336
|
-
[1.2, 0]
|
|
2337
|
-
]
|
|
2338
|
-
}
|
|
2339
|
-
]
|
|
2340
|
-
}
|
|
2341
|
-
],
|
|
2342
|
-
Tilt: [
|
|
2343
|
-
{
|
|
2344
|
-
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
2345
|
-
duration: 1.4,
|
|
2346
|
-
curves: [
|
|
2347
|
-
{
|
|
2348
|
-
parameter: P.AngleZ,
|
|
2349
|
-
keys: [
|
|
2350
|
-
[0, 0],
|
|
2351
|
-
[0.35, 20],
|
|
2352
|
-
[1, 20],
|
|
2353
|
-
[1.4, 0]
|
|
2354
|
-
]
|
|
2355
|
-
}
|
|
2356
|
-
]
|
|
2357
|
-
}
|
|
2358
|
-
]
|
|
2359
|
-
};
|
|
2360
|
-
|
|
2361
2108
|
// src/auto-rig/arms.ts
|
|
2362
2109
|
import {
|
|
2363
|
-
StandardParameter as
|
|
2110
|
+
StandardParameter as P3
|
|
2364
2111
|
} from "@ikijs/format";
|
|
2365
2112
|
|
|
2366
2113
|
// src/auto-rig/body.ts
|
|
2367
2114
|
import {
|
|
2368
|
-
StandardParameter as
|
|
2115
|
+
StandardParameter as P2
|
|
2369
2116
|
} from "@ikijs/format";
|
|
2370
2117
|
|
|
2371
2118
|
// src/auto-rig/layout.ts
|
|
@@ -2443,7 +2190,7 @@ function meshPoints(mesh, box) {
|
|
|
2443
2190
|
|
|
2444
2191
|
// src/auto-rig/drivers.ts
|
|
2445
2192
|
import {
|
|
2446
|
-
StandardParameter as
|
|
2193
|
+
StandardParameter as P
|
|
2447
2194
|
} from "@ikijs/format";
|
|
2448
2195
|
var SWAY_RANGE = 20;
|
|
2449
2196
|
var SWAY_CURVE = 1.4;
|
|
@@ -2522,13 +2269,13 @@ function gazeBindings(irisW, share = 1) {
|
|
|
2522
2269
|
const gy = AMPLITUDE.gazeY * irisW * share;
|
|
2523
2270
|
return [
|
|
2524
2271
|
{
|
|
2525
|
-
parameter:
|
|
2272
|
+
parameter: P.EyeballX,
|
|
2526
2273
|
channel: "translateX",
|
|
2527
2274
|
from: -round1(gx),
|
|
2528
2275
|
to: round1(gx)
|
|
2529
2276
|
},
|
|
2530
2277
|
{
|
|
2531
|
-
parameter:
|
|
2278
|
+
parameter: P.EyeballY,
|
|
2532
2279
|
channel: "translateY",
|
|
2533
2280
|
from: -round1(gy),
|
|
2534
2281
|
to: round1(gy)
|
|
@@ -2542,8 +2289,8 @@ function browReach(hh) {
|
|
|
2542
2289
|
return AMPLITUDE.brow * hh;
|
|
2543
2290
|
}
|
|
2544
2291
|
function browBindings(side, reach) {
|
|
2545
|
-
const y = side === "L" ?
|
|
2546
|
-
const a = side === "L" ?
|
|
2292
|
+
const y = side === "L" ? P.BrowLeftY : P.BrowRightY;
|
|
2293
|
+
const a = side === "L" ? P.BrowLeftAngle : P.BrowRightAngle;
|
|
2547
2294
|
return [
|
|
2548
2295
|
{
|
|
2549
2296
|
parameter: y,
|
|
@@ -2559,7 +2306,7 @@ function mouthForm(mesh, box) {
|
|
|
2559
2306
|
const a = 0.3 * bh(box);
|
|
2560
2307
|
const c = cx(box);
|
|
2561
2308
|
const half = bw(box) / 2;
|
|
2562
|
-
return localWarp(
|
|
2309
|
+
return localWarp(P.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
|
|
2563
2310
|
if (v === 0) return [0, 0];
|
|
2564
2311
|
const u = (x - c) / half;
|
|
2565
2312
|
const widen = v > 0 ? 0.05 : 0.03;
|
|
@@ -2569,7 +2316,7 @@ function mouthForm(mesh, box) {
|
|
|
2569
2316
|
function mouthOpenGrow(mesh, box) {
|
|
2570
2317
|
const c = cx(box);
|
|
2571
2318
|
return localWarp(
|
|
2572
|
-
|
|
2319
|
+
P.MouthOpen,
|
|
2573
2320
|
mesh,
|
|
2574
2321
|
box,
|
|
2575
2322
|
[0, 1],
|
|
@@ -2578,7 +2325,7 @@ function mouthOpenGrow(mesh, box) {
|
|
|
2578
2325
|
}
|
|
2579
2326
|
function mouthWiden(mesh, box) {
|
|
2580
2327
|
const c = cx(box);
|
|
2581
|
-
return localWarp(
|
|
2328
|
+
return localWarp(P.MouthOpen, mesh, box, [0, 1], ([x], v) => [
|
|
2582
2329
|
v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),
|
|
2583
2330
|
0
|
|
2584
2331
|
]);
|
|
@@ -2596,7 +2343,7 @@ function hairSway(param, mesh, box, amp) {
|
|
|
2596
2343
|
);
|
|
2597
2344
|
}
|
|
2598
2345
|
function tiltHang(mesh, box, pivot, weight, deg = ROLL_DEG) {
|
|
2599
|
-
return localWarp(
|
|
2346
|
+
return localWarp(P.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
|
|
2600
2347
|
const g = weight(y, i);
|
|
2601
2348
|
if (g === 0 || v === 0) return [0, 0];
|
|
2602
2349
|
const a = -g * rollOf(v, deg);
|
|
@@ -2845,16 +2592,16 @@ function buildBodyWarp({
|
|
|
2845
2592
|
points: ys.flatMap((y) => xs.flatMap((x) => [x, y]))
|
|
2846
2593
|
},
|
|
2847
2594
|
warps: [
|
|
2848
|
-
warp(
|
|
2849
|
-
warp(
|
|
2595
|
+
warp(P2.BodyAngleX, BODY_STOPS, (x, _y, t) => [turn(x, t), 0]),
|
|
2596
|
+
warp(P2.BodyAngleY, BODY_STOPS, (_x, _y, t) => [0, t * BODY.bow * hh]),
|
|
2850
2597
|
warp(
|
|
2851
|
-
|
|
2598
|
+
P2.BodyAngleZ,
|
|
2852
2599
|
BODY_STOPS,
|
|
2853
2600
|
(x, y, t) => roll(x, y, -t * BODY.rollDeg)
|
|
2854
2601
|
),
|
|
2855
|
-
warp(
|
|
2856
|
-
warp(
|
|
2857
|
-
warp(
|
|
2602
|
+
warp(P2.AngleX, X_STOPS, (x, _y, t) => [BODY.followX * turn(x, t), 0]),
|
|
2603
|
+
warp(P2.AngleZ, Z_STOPS, (x, y, t) => roll(x, y, -t * BODY.followRoll)),
|
|
2604
|
+
warp(P2.Breath, [0, 1], (_x, _y, t) => [0, t * AMPLITUDE.breathBody * hh])
|
|
2858
2605
|
]
|
|
2859
2606
|
};
|
|
2860
2607
|
refuseFold(body, deformer, anchor, [chin, ...pivots]);
|
|
@@ -2939,8 +2686,8 @@ var CAP_ROWS = [0.1, 0.3];
|
|
|
2939
2686
|
var CAP_SEGMENTS = 12;
|
|
2940
2687
|
var ARM_RANGE = [-30, 150];
|
|
2941
2688
|
var ARM_PARAMS = {
|
|
2942
|
-
arm_L: { arm:
|
|
2943
|
-
arm_R: { arm:
|
|
2689
|
+
arm_L: { arm: P3.ArmLeft, elbow: P3.ElbowLeft },
|
|
2690
|
+
arm_R: { arm: P3.ArmRight, elbow: P3.ElbowRight }
|
|
2944
2691
|
};
|
|
2945
2692
|
var ARM_IDS = {
|
|
2946
2693
|
arm_L: {
|
|
@@ -3088,6 +2835,259 @@ function armDeformers(role, g) {
|
|
|
3088
2835
|
];
|
|
3089
2836
|
}
|
|
3090
2837
|
|
|
2838
|
+
// src/auto-rig/roles.ts
|
|
2839
|
+
var ROLE_TABLE = [
|
|
2840
|
+
{ role: "hair_back", family: "hair_back" },
|
|
2841
|
+
{ role: "body", family: "body" },
|
|
2842
|
+
{ role: "arm_L", family: "arm", parts: ["arm_L", "forearm_L"] },
|
|
2843
|
+
{ role: "arm_R", family: "arm", parts: ["arm_R", "forearm_R"] },
|
|
2844
|
+
{ role: "face", family: "face", required: true },
|
|
2845
|
+
{ role: "blush_L", family: "face" },
|
|
2846
|
+
{ role: "blush_R", family: "face" },
|
|
2847
|
+
{ role: "nose", family: "nose" },
|
|
2848
|
+
{ role: "mouth", family: "mouth", required: true },
|
|
2849
|
+
{ role: "mouth_open", family: "mouth" },
|
|
2850
|
+
{ role: "eye_L", family: "eye_L", required: true },
|
|
2851
|
+
{ role: "eye_R", family: "eye_R", required: true },
|
|
2852
|
+
{ role: "iris_L", family: "eye_L" },
|
|
2853
|
+
{ role: "iris_R", family: "eye_R" },
|
|
2854
|
+
{ role: "pupil_L", family: "eye_L" },
|
|
2855
|
+
{ role: "pupil_R", family: "eye_R" },
|
|
2856
|
+
{ role: "highlight_L", family: "eye_L" },
|
|
2857
|
+
{ role: "highlight_R", family: "eye_R" },
|
|
2858
|
+
{ role: "lash_lower_L", family: "eye_L" },
|
|
2859
|
+
{ role: "lash_lower_R", family: "eye_R" },
|
|
2860
|
+
{ role: "lash_L", family: "eye_L" },
|
|
2861
|
+
{ role: "lash_R", family: "eye_R" },
|
|
2862
|
+
{ role: "brow_L", family: "brow_L" },
|
|
2863
|
+
{ role: "brow_R", family: "brow_R" },
|
|
2864
|
+
{ role: "hair_front", family: "hair_front" }
|
|
2865
|
+
];
|
|
2866
|
+
var REQUIRED_ROLES = ROLE_TABLE.filter(
|
|
2867
|
+
(r) => r.required
|
|
2868
|
+
).map((r) => r.role);
|
|
2869
|
+
var SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));
|
|
2870
|
+
function roleSpec(role) {
|
|
2871
|
+
const spec = SPEC_BY_ROLE.get(role);
|
|
2872
|
+
if (spec === void 0) throw new Error(`auto-rig: unknown role "${role}"`);
|
|
2873
|
+
return spec;
|
|
2874
|
+
}
|
|
2875
|
+
function partIdsOfRole(role) {
|
|
2876
|
+
return roleSpec(role).parts ?? [role];
|
|
2877
|
+
}
|
|
2878
|
+
var ROLE_BY_PART = new Map(
|
|
2879
|
+
ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role]))
|
|
2880
|
+
);
|
|
2881
|
+
function roleOfPart(partId) {
|
|
2882
|
+
return ROLE_BY_PART.get(partId) ?? partId;
|
|
2883
|
+
}
|
|
2884
|
+
var ALIASES = {
|
|
2885
|
+
eyebrow_L: "brow_L",
|
|
2886
|
+
eyebrow_R: "brow_R",
|
|
2887
|
+
eye_white_L: "eye_L",
|
|
2888
|
+
eye_white_R: "eye_R"
|
|
2889
|
+
};
|
|
2890
|
+
function roleOf(fileName) {
|
|
2891
|
+
const role = fileName.replace(/\.[^.]+$/, "").toLowerCase().replace(/[-\s]+/g, "_").replace(/_([lr])$/, (_, s) => `_${s.toUpperCase()}`);
|
|
2892
|
+
return ALIASES[role] ?? role;
|
|
2893
|
+
}
|
|
2894
|
+
function checkArmsHaveBody(roles) {
|
|
2895
|
+
const has = new Set(roles);
|
|
2896
|
+
if (has.has("body")) return;
|
|
2897
|
+
const arm = ROLE_TABLE.find((r) => r.family === "arm" && has.has(r.role));
|
|
2898
|
+
if (arm !== void 0) {
|
|
2899
|
+
throw new Error(
|
|
2900
|
+
`auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`
|
|
2901
|
+
);
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
function parseLayerRoles(fileNames) {
|
|
2905
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2906
|
+
const out = [];
|
|
2907
|
+
for (const fileName of fileNames) {
|
|
2908
|
+
const role = roleOf(fileName);
|
|
2909
|
+
if (!SPEC_BY_ROLE.has(role)) {
|
|
2910
|
+
throw new Error(
|
|
2911
|
+
`auto-rig: "${fileName}" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(", ")})`
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2914
|
+
const prior = seen.get(role);
|
|
2915
|
+
if (prior !== void 0) {
|
|
2916
|
+
throw new Error(
|
|
2917
|
+
`auto-rig: role "${role}" is named twice ("${prior}" and "${fileName}")`
|
|
2918
|
+
);
|
|
2919
|
+
}
|
|
2920
|
+
seen.set(role, fileName);
|
|
2921
|
+
out.push({ role, fileName });
|
|
2922
|
+
}
|
|
2923
|
+
const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));
|
|
2924
|
+
if (missing.length > 0) {
|
|
2925
|
+
throw new Error(
|
|
2926
|
+
`auto-rig: missing required role${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`
|
|
2927
|
+
);
|
|
2928
|
+
}
|
|
2929
|
+
checkArmsHaveBody(seen.keys());
|
|
2930
|
+
return out;
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
// src/auto-rig/generate.ts
|
|
2934
|
+
import {
|
|
2935
|
+
IKI_FORMAT_VERSION as IKI_FORMAT_VERSION2,
|
|
2936
|
+
StandardParameter as P6,
|
|
2937
|
+
parseIkiModel as parseIkiModel3
|
|
2938
|
+
} from "@ikijs/format";
|
|
2939
|
+
|
|
2940
|
+
// src/auto-rig/animations.ts
|
|
2941
|
+
import {
|
|
2942
|
+
StandardParameter as P4
|
|
2943
|
+
} from "@ikijs/format";
|
|
2944
|
+
function browsY(y) {
|
|
2945
|
+
return [
|
|
2946
|
+
{ parameter: P4.BrowLeftY, value: y, blend: "add" },
|
|
2947
|
+
{ parameter: P4.BrowRightY, value: y, blend: "add" }
|
|
2948
|
+
];
|
|
2949
|
+
}
|
|
2950
|
+
function browsTilt(innerDown) {
|
|
2951
|
+
return [
|
|
2952
|
+
{ parameter: P4.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
2953
|
+
{ parameter: P4.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
2954
|
+
];
|
|
2955
|
+
}
|
|
2956
|
+
function cheek(value) {
|
|
2957
|
+
return { parameter: P4.Cheek, value, blend: "add" };
|
|
2958
|
+
}
|
|
2959
|
+
var BROWS = [P4.BrowLeftY, P4.BrowRightY, P4.BrowLeftAngle, P4.BrowRightAngle];
|
|
2960
|
+
var EXPRESSIONS = [
|
|
2961
|
+
{
|
|
2962
|
+
id: "smile",
|
|
2963
|
+
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
2964
|
+
parameters: [
|
|
2965
|
+
{ parameter: P4.MouthForm, value: 1, blend: "add" },
|
|
2966
|
+
...browsY(0.25),
|
|
2967
|
+
cheek(0.4)
|
|
2968
|
+
]
|
|
2969
|
+
},
|
|
2970
|
+
{
|
|
2971
|
+
id: "laugh",
|
|
2972
|
+
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
2973
|
+
parameters: [
|
|
2974
|
+
{ parameter: P4.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
2975
|
+
{ parameter: P4.EyeOpenRight, value: 0, blend: "multiply" },
|
|
2976
|
+
{ parameter: P4.MouthForm, value: 1, blend: "add" },
|
|
2977
|
+
{ parameter: P4.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
2978
|
+
...browsY(0.4),
|
|
2979
|
+
cheek(0.65)
|
|
2980
|
+
]
|
|
2981
|
+
},
|
|
2982
|
+
{
|
|
2983
|
+
id: "angry",
|
|
2984
|
+
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
2985
|
+
needs: BROWS,
|
|
2986
|
+
parameters: [
|
|
2987
|
+
...browsY(-0.5),
|
|
2988
|
+
...browsTilt(0.8),
|
|
2989
|
+
{ parameter: P4.MouthForm, value: -0.9, blend: "add" }
|
|
2990
|
+
]
|
|
2991
|
+
},
|
|
2992
|
+
{
|
|
2993
|
+
id: "sad",
|
|
2994
|
+
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
2995
|
+
needs: BROWS,
|
|
2996
|
+
parameters: [
|
|
2997
|
+
...browsY(0.35),
|
|
2998
|
+
...browsTilt(-0.8),
|
|
2999
|
+
{ parameter: P4.MouthForm, value: -0.8, blend: "add" }
|
|
3000
|
+
]
|
|
3001
|
+
},
|
|
3002
|
+
{
|
|
3003
|
+
id: "surprised",
|
|
3004
|
+
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
3005
|
+
parameters: [
|
|
3006
|
+
...browsY(0.8),
|
|
3007
|
+
{ parameter: P4.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
3008
|
+
]
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
id: "shy",
|
|
3012
|
+
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
3013
|
+
needs: [P4.Cheek],
|
|
3014
|
+
parameters: [
|
|
3015
|
+
cheek(1),
|
|
3016
|
+
// Gaze down.
|
|
3017
|
+
{ parameter: P4.EyeballY, value: -0.65, blend: "add" },
|
|
3018
|
+
{ parameter: P4.MouthForm, value: 0.4, blend: "add" },
|
|
3019
|
+
...browsTilt(-0.25)
|
|
3020
|
+
]
|
|
3021
|
+
}
|
|
3022
|
+
];
|
|
3023
|
+
function defaultExpressions(declared) {
|
|
3024
|
+
return EXPRESSIONS.filter(
|
|
3025
|
+
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
3026
|
+
).map(({ needs: _needs, ...e }) => ({
|
|
3027
|
+
...e,
|
|
3028
|
+
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
3029
|
+
}));
|
|
3030
|
+
}
|
|
3031
|
+
var DEFAULT_MOTIONS = {
|
|
3032
|
+
Nod: [
|
|
3033
|
+
{
|
|
3034
|
+
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
3035
|
+
duration: 1,
|
|
3036
|
+
curves: [
|
|
3037
|
+
{
|
|
3038
|
+
parameter: P4.AngleY,
|
|
3039
|
+
keys: [
|
|
3040
|
+
[0, 0],
|
|
3041
|
+
[0.3, -18],
|
|
3042
|
+
[0.6, 4],
|
|
3043
|
+
[0.8, -1],
|
|
3044
|
+
[1, 0]
|
|
3045
|
+
]
|
|
3046
|
+
}
|
|
3047
|
+
]
|
|
3048
|
+
}
|
|
3049
|
+
],
|
|
3050
|
+
Shake: [
|
|
3051
|
+
{
|
|
3052
|
+
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
3053
|
+
duration: 1.2,
|
|
3054
|
+
// The first swing peaks at 0.2 s, which the default fade would still
|
|
3055
|
+
// be damping.
|
|
3056
|
+
fadeIn: 0.15,
|
|
3057
|
+
curves: [
|
|
3058
|
+
{
|
|
3059
|
+
parameter: P4.AngleX,
|
|
3060
|
+
keys: [
|
|
3061
|
+
[0, 0],
|
|
3062
|
+
[0.2, -18],
|
|
3063
|
+
[0.45, 18],
|
|
3064
|
+
[0.7, -16],
|
|
3065
|
+
[0.95, 10],
|
|
3066
|
+
[1.2, 0]
|
|
3067
|
+
]
|
|
3068
|
+
}
|
|
3069
|
+
]
|
|
3070
|
+
}
|
|
3071
|
+
],
|
|
3072
|
+
Tilt: [
|
|
3073
|
+
{
|
|
3074
|
+
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
3075
|
+
duration: 1.4,
|
|
3076
|
+
curves: [
|
|
3077
|
+
{
|
|
3078
|
+
parameter: P4.AngleZ,
|
|
3079
|
+
keys: [
|
|
3080
|
+
[0, 0],
|
|
3081
|
+
[0.35, 20],
|
|
3082
|
+
[1, 20],
|
|
3083
|
+
[1.4, 0]
|
|
3084
|
+
]
|
|
3085
|
+
}
|
|
3086
|
+
]
|
|
3087
|
+
}
|
|
3088
|
+
]
|
|
3089
|
+
};
|
|
3090
|
+
|
|
3091
3091
|
// src/auto-rig/checks.ts
|
|
3092
3092
|
var finite = (v) => typeof v === "number" && Number.isFinite(v);
|
|
3093
3093
|
var isObject = (v) => typeof v === "object" && v !== null;
|
|
@@ -5726,6 +5726,7 @@ export {
|
|
|
5726
5726
|
SetPhysicsRig,
|
|
5727
5727
|
TurnTargetError,
|
|
5728
5728
|
UV_INSET_PX,
|
|
5729
|
+
armGeometry,
|
|
5729
5730
|
captureBindingEndpoint,
|
|
5730
5731
|
computeGridOffsets,
|
|
5731
5732
|
createDefaultMatrixDeformer,
|