@ikijs/editor 0.17.0 → 0.19.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 +16 -16
- package/dist/index.d.mts +89 -3
- package/dist/index.d.ts +89 -3
- package/dist/index.js +351 -291
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +356 -297
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ __export(index_exports, {
|
|
|
52
52
|
SetPhysicsRig: () => SetPhysicsRig,
|
|
53
53
|
TurnTargetError: () => TurnTargetError,
|
|
54
54
|
UV_INSET_PX: () => UV_INSET_PX,
|
|
55
|
+
armGeometry: () => armGeometry,
|
|
55
56
|
captureBindingEndpoint: () => captureBindingEndpoint,
|
|
56
57
|
computeGridOffsets: () => computeGridOffsets,
|
|
57
58
|
createDefaultMatrixDeformer: () => createDefaultMatrixDeformer,
|
|
@@ -2180,258 +2181,11 @@ var DEFAULT_TURN_TARGETS = Object.freeze({
|
|
|
2180
2181
|
silhouetteRatio: 1
|
|
2181
2182
|
});
|
|
2182
2183
|
|
|
2183
|
-
// src/auto-rig/roles.ts
|
|
2184
|
-
var ROLE_TABLE = [
|
|
2185
|
-
{ role: "hair_back", family: "hair_back" },
|
|
2186
|
-
{ role: "body", family: "body" },
|
|
2187
|
-
{ role: "arm_L", family: "arm", parts: ["arm_L", "forearm_L"] },
|
|
2188
|
-
{ role: "arm_R", family: "arm", parts: ["arm_R", "forearm_R"] },
|
|
2189
|
-
{ role: "face", family: "face", required: true },
|
|
2190
|
-
{ role: "blush_L", family: "face" },
|
|
2191
|
-
{ role: "blush_R", family: "face" },
|
|
2192
|
-
{ role: "nose", family: "nose" },
|
|
2193
|
-
{ role: "mouth", family: "mouth", required: true },
|
|
2194
|
-
{ role: "mouth_open", family: "mouth" },
|
|
2195
|
-
{ role: "eye_L", family: "eye_L", required: true },
|
|
2196
|
-
{ role: "eye_R", family: "eye_R", required: true },
|
|
2197
|
-
{ role: "iris_L", family: "eye_L" },
|
|
2198
|
-
{ role: "iris_R", family: "eye_R" },
|
|
2199
|
-
{ role: "pupil_L", family: "eye_L" },
|
|
2200
|
-
{ role: "pupil_R", family: "eye_R" },
|
|
2201
|
-
{ role: "highlight_L", family: "eye_L" },
|
|
2202
|
-
{ role: "highlight_R", family: "eye_R" },
|
|
2203
|
-
{ role: "lash_lower_L", family: "eye_L" },
|
|
2204
|
-
{ role: "lash_lower_R", family: "eye_R" },
|
|
2205
|
-
{ role: "lash_L", family: "eye_L" },
|
|
2206
|
-
{ role: "lash_R", family: "eye_R" },
|
|
2207
|
-
{ role: "brow_L", family: "brow_L" },
|
|
2208
|
-
{ role: "brow_R", family: "brow_R" },
|
|
2209
|
-
{ role: "hair_front", family: "hair_front" }
|
|
2210
|
-
];
|
|
2211
|
-
var REQUIRED_ROLES = ROLE_TABLE.filter(
|
|
2212
|
-
(r) => r.required
|
|
2213
|
-
).map((r) => r.role);
|
|
2214
|
-
var SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));
|
|
2215
|
-
function roleSpec(role) {
|
|
2216
|
-
const spec = SPEC_BY_ROLE.get(role);
|
|
2217
|
-
if (spec === void 0) throw new Error(`auto-rig: unknown role "${role}"`);
|
|
2218
|
-
return spec;
|
|
2219
|
-
}
|
|
2220
|
-
function partIdsOfRole(role) {
|
|
2221
|
-
return roleSpec(role).parts ?? [role];
|
|
2222
|
-
}
|
|
2223
|
-
var ROLE_BY_PART = new Map(
|
|
2224
|
-
ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role]))
|
|
2225
|
-
);
|
|
2226
|
-
function roleOfPart(partId) {
|
|
2227
|
-
return ROLE_BY_PART.get(partId) ?? partId;
|
|
2228
|
-
}
|
|
2229
|
-
var ALIASES = {
|
|
2230
|
-
eyebrow_L: "brow_L",
|
|
2231
|
-
eyebrow_R: "brow_R",
|
|
2232
|
-
eye_white_L: "eye_L",
|
|
2233
|
-
eye_white_R: "eye_R"
|
|
2234
|
-
};
|
|
2235
|
-
function roleOf(fileName) {
|
|
2236
|
-
const role = fileName.replace(/\.[^.]+$/, "").toLowerCase().replace(/[-\s]+/g, "_").replace(/_([lr])$/, (_, s) => `_${s.toUpperCase()}`);
|
|
2237
|
-
return ALIASES[role] ?? role;
|
|
2238
|
-
}
|
|
2239
|
-
function checkArmsHaveBody(roles) {
|
|
2240
|
-
const has = new Set(roles);
|
|
2241
|
-
if (has.has("body")) return;
|
|
2242
|
-
const arm = ROLE_TABLE.find((r) => r.family === "arm" && has.has(r.role));
|
|
2243
|
-
if (arm !== void 0) {
|
|
2244
|
-
throw new Error(
|
|
2245
|
-
`auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`
|
|
2246
|
-
);
|
|
2247
|
-
}
|
|
2248
|
-
}
|
|
2249
|
-
function parseLayerRoles(fileNames) {
|
|
2250
|
-
const seen = /* @__PURE__ */ new Map();
|
|
2251
|
-
const out = [];
|
|
2252
|
-
for (const fileName of fileNames) {
|
|
2253
|
-
const role = roleOf(fileName);
|
|
2254
|
-
if (!SPEC_BY_ROLE.has(role)) {
|
|
2255
|
-
throw new Error(
|
|
2256
|
-
`auto-rig: "${fileName}" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(", ")})`
|
|
2257
|
-
);
|
|
2258
|
-
}
|
|
2259
|
-
const prior = seen.get(role);
|
|
2260
|
-
if (prior !== void 0) {
|
|
2261
|
-
throw new Error(
|
|
2262
|
-
`auto-rig: role "${role}" is named twice ("${prior}" and "${fileName}")`
|
|
2263
|
-
);
|
|
2264
|
-
}
|
|
2265
|
-
seen.set(role, fileName);
|
|
2266
|
-
out.push({ role, fileName });
|
|
2267
|
-
}
|
|
2268
|
-
const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));
|
|
2269
|
-
if (missing.length > 0) {
|
|
2270
|
-
throw new Error(
|
|
2271
|
-
`auto-rig: missing required role${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`
|
|
2272
|
-
);
|
|
2273
|
-
}
|
|
2274
|
-
checkArmsHaveBody(seen.keys());
|
|
2275
|
-
return out;
|
|
2276
|
-
}
|
|
2277
|
-
|
|
2278
|
-
// src/auto-rig/generate.ts
|
|
2279
|
-
var import_format8 = require("@ikijs/format");
|
|
2280
|
-
|
|
2281
|
-
// src/auto-rig/animations.ts
|
|
2282
|
-
var import_format3 = require("@ikijs/format");
|
|
2283
|
-
function browsY(y) {
|
|
2284
|
-
return [
|
|
2285
|
-
{ parameter: import_format3.StandardParameter.BrowLeftY, value: y, blend: "add" },
|
|
2286
|
-
{ parameter: import_format3.StandardParameter.BrowRightY, value: y, blend: "add" }
|
|
2287
|
-
];
|
|
2288
|
-
}
|
|
2289
|
-
function browsTilt(innerDown) {
|
|
2290
|
-
return [
|
|
2291
|
-
{ parameter: import_format3.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
2292
|
-
{ parameter: import_format3.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
2293
|
-
];
|
|
2294
|
-
}
|
|
2295
|
-
function cheek(value) {
|
|
2296
|
-
return { parameter: import_format3.StandardParameter.Cheek, value, blend: "add" };
|
|
2297
|
-
}
|
|
2298
|
-
var BROWS = [import_format3.StandardParameter.BrowLeftY, import_format3.StandardParameter.BrowRightY, import_format3.StandardParameter.BrowLeftAngle, import_format3.StandardParameter.BrowRightAngle];
|
|
2299
|
-
var EXPRESSIONS = [
|
|
2300
|
-
{
|
|
2301
|
-
id: "smile",
|
|
2302
|
-
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
2303
|
-
parameters: [
|
|
2304
|
-
{ parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
2305
|
-
...browsY(0.25),
|
|
2306
|
-
cheek(0.4)
|
|
2307
|
-
]
|
|
2308
|
-
},
|
|
2309
|
-
{
|
|
2310
|
-
id: "laugh",
|
|
2311
|
-
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
2312
|
-
parameters: [
|
|
2313
|
-
{ parameter: import_format3.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
2314
|
-
{ parameter: import_format3.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
|
|
2315
|
-
{ parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
2316
|
-
{ parameter: import_format3.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
2317
|
-
...browsY(0.4),
|
|
2318
|
-
cheek(0.65)
|
|
2319
|
-
]
|
|
2320
|
-
},
|
|
2321
|
-
{
|
|
2322
|
-
id: "angry",
|
|
2323
|
-
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
2324
|
-
needs: BROWS,
|
|
2325
|
-
parameters: [
|
|
2326
|
-
...browsY(-0.5),
|
|
2327
|
-
...browsTilt(0.8),
|
|
2328
|
-
{ parameter: import_format3.StandardParameter.MouthForm, value: -0.9, blend: "add" }
|
|
2329
|
-
]
|
|
2330
|
-
},
|
|
2331
|
-
{
|
|
2332
|
-
id: "sad",
|
|
2333
|
-
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
2334
|
-
needs: BROWS,
|
|
2335
|
-
parameters: [
|
|
2336
|
-
...browsY(0.35),
|
|
2337
|
-
...browsTilt(-0.8),
|
|
2338
|
-
{ parameter: import_format3.StandardParameter.MouthForm, value: -0.8, blend: "add" }
|
|
2339
|
-
]
|
|
2340
|
-
},
|
|
2341
|
-
{
|
|
2342
|
-
id: "surprised",
|
|
2343
|
-
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
2344
|
-
parameters: [
|
|
2345
|
-
...browsY(0.8),
|
|
2346
|
-
{ parameter: import_format3.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
2347
|
-
]
|
|
2348
|
-
},
|
|
2349
|
-
{
|
|
2350
|
-
id: "shy",
|
|
2351
|
-
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
2352
|
-
needs: [import_format3.StandardParameter.Cheek],
|
|
2353
|
-
parameters: [
|
|
2354
|
-
cheek(1),
|
|
2355
|
-
// Gaze down.
|
|
2356
|
-
{ parameter: import_format3.StandardParameter.EyeballY, value: -0.65, blend: "add" },
|
|
2357
|
-
{ parameter: import_format3.StandardParameter.MouthForm, value: 0.4, blend: "add" },
|
|
2358
|
-
...browsTilt(-0.25)
|
|
2359
|
-
]
|
|
2360
|
-
}
|
|
2361
|
-
];
|
|
2362
|
-
function defaultExpressions(declared) {
|
|
2363
|
-
return EXPRESSIONS.filter(
|
|
2364
|
-
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
2365
|
-
).map(({ needs: _needs, ...e }) => ({
|
|
2366
|
-
...e,
|
|
2367
|
-
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
2368
|
-
}));
|
|
2369
|
-
}
|
|
2370
|
-
var DEFAULT_MOTIONS = {
|
|
2371
|
-
Nod: [
|
|
2372
|
-
{
|
|
2373
|
-
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
2374
|
-
duration: 1,
|
|
2375
|
-
curves: [
|
|
2376
|
-
{
|
|
2377
|
-
parameter: import_format3.StandardParameter.AngleY,
|
|
2378
|
-
keys: [
|
|
2379
|
-
[0, 0],
|
|
2380
|
-
[0.3, -18],
|
|
2381
|
-
[0.6, 4],
|
|
2382
|
-
[0.8, -1],
|
|
2383
|
-
[1, 0]
|
|
2384
|
-
]
|
|
2385
|
-
}
|
|
2386
|
-
]
|
|
2387
|
-
}
|
|
2388
|
-
],
|
|
2389
|
-
Shake: [
|
|
2390
|
-
{
|
|
2391
|
-
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
2392
|
-
duration: 1.2,
|
|
2393
|
-
// The first swing peaks at 0.2 s, which the default fade would still
|
|
2394
|
-
// be damping.
|
|
2395
|
-
fadeIn: 0.15,
|
|
2396
|
-
curves: [
|
|
2397
|
-
{
|
|
2398
|
-
parameter: import_format3.StandardParameter.AngleX,
|
|
2399
|
-
keys: [
|
|
2400
|
-
[0, 0],
|
|
2401
|
-
[0.2, -18],
|
|
2402
|
-
[0.45, 18],
|
|
2403
|
-
[0.7, -16],
|
|
2404
|
-
[0.95, 10],
|
|
2405
|
-
[1.2, 0]
|
|
2406
|
-
]
|
|
2407
|
-
}
|
|
2408
|
-
]
|
|
2409
|
-
}
|
|
2410
|
-
],
|
|
2411
|
-
Tilt: [
|
|
2412
|
-
{
|
|
2413
|
-
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
2414
|
-
duration: 1.4,
|
|
2415
|
-
curves: [
|
|
2416
|
-
{
|
|
2417
|
-
parameter: import_format3.StandardParameter.AngleZ,
|
|
2418
|
-
keys: [
|
|
2419
|
-
[0, 0],
|
|
2420
|
-
[0.35, 20],
|
|
2421
|
-
[1, 20],
|
|
2422
|
-
[1.4, 0]
|
|
2423
|
-
]
|
|
2424
|
-
}
|
|
2425
|
-
]
|
|
2426
|
-
}
|
|
2427
|
-
]
|
|
2428
|
-
};
|
|
2429
|
-
|
|
2430
2184
|
// src/auto-rig/arms.ts
|
|
2431
|
-
var
|
|
2185
|
+
var import_format5 = require("@ikijs/format");
|
|
2432
2186
|
|
|
2433
2187
|
// src/auto-rig/body.ts
|
|
2434
|
-
var
|
|
2188
|
+
var import_format4 = require("@ikijs/format");
|
|
2435
2189
|
|
|
2436
2190
|
// src/auto-rig/layout.ts
|
|
2437
2191
|
function boxOfLayer(layer) {
|
|
@@ -2507,7 +2261,7 @@ function meshPoints(mesh, box) {
|
|
|
2507
2261
|
}
|
|
2508
2262
|
|
|
2509
2263
|
// src/auto-rig/drivers.ts
|
|
2510
|
-
var
|
|
2264
|
+
var import_format3 = require("@ikijs/format");
|
|
2511
2265
|
var SWAY_RANGE = 20;
|
|
2512
2266
|
var SWAY_CURVE = 1.4;
|
|
2513
2267
|
var HAIR_HANG = 0.35;
|
|
@@ -2585,13 +2339,13 @@ function gazeBindings(irisW, share = 1) {
|
|
|
2585
2339
|
const gy = AMPLITUDE.gazeY * irisW * share;
|
|
2586
2340
|
return [
|
|
2587
2341
|
{
|
|
2588
|
-
parameter:
|
|
2342
|
+
parameter: import_format3.StandardParameter.EyeballX,
|
|
2589
2343
|
channel: "translateX",
|
|
2590
2344
|
from: -round1(gx),
|
|
2591
2345
|
to: round1(gx)
|
|
2592
2346
|
},
|
|
2593
2347
|
{
|
|
2594
|
-
parameter:
|
|
2348
|
+
parameter: import_format3.StandardParameter.EyeballY,
|
|
2595
2349
|
channel: "translateY",
|
|
2596
2350
|
from: -round1(gy),
|
|
2597
2351
|
to: round1(gy)
|
|
@@ -2605,8 +2359,8 @@ function browReach(hh) {
|
|
|
2605
2359
|
return AMPLITUDE.brow * hh;
|
|
2606
2360
|
}
|
|
2607
2361
|
function browBindings(side, reach) {
|
|
2608
|
-
const y = side === "L" ?
|
|
2609
|
-
const a = side === "L" ?
|
|
2362
|
+
const y = side === "L" ? import_format3.StandardParameter.BrowLeftY : import_format3.StandardParameter.BrowRightY;
|
|
2363
|
+
const a = side === "L" ? import_format3.StandardParameter.BrowLeftAngle : import_format3.StandardParameter.BrowRightAngle;
|
|
2610
2364
|
return [
|
|
2611
2365
|
{
|
|
2612
2366
|
parameter: y,
|
|
@@ -2622,7 +2376,7 @@ function mouthForm(mesh, box) {
|
|
|
2622
2376
|
const a = 0.3 * bh(box);
|
|
2623
2377
|
const c = cx(box);
|
|
2624
2378
|
const half = bw(box) / 2;
|
|
2625
|
-
return localWarp(
|
|
2379
|
+
return localWarp(import_format3.StandardParameter.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
|
|
2626
2380
|
if (v === 0) return [0, 0];
|
|
2627
2381
|
const u = (x - c) / half;
|
|
2628
2382
|
const widen = v > 0 ? 0.05 : 0.03;
|
|
@@ -2632,7 +2386,7 @@ function mouthForm(mesh, box) {
|
|
|
2632
2386
|
function mouthOpenGrow(mesh, box) {
|
|
2633
2387
|
const c = cx(box);
|
|
2634
2388
|
return localWarp(
|
|
2635
|
-
|
|
2389
|
+
import_format3.StandardParameter.MouthOpen,
|
|
2636
2390
|
mesh,
|
|
2637
2391
|
box,
|
|
2638
2392
|
[0, 1],
|
|
@@ -2641,7 +2395,7 @@ function mouthOpenGrow(mesh, box) {
|
|
|
2641
2395
|
}
|
|
2642
2396
|
function mouthWiden(mesh, box) {
|
|
2643
2397
|
const c = cx(box);
|
|
2644
|
-
return localWarp(
|
|
2398
|
+
return localWarp(import_format3.StandardParameter.MouthOpen, mesh, box, [0, 1], ([x], v) => [
|
|
2645
2399
|
v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),
|
|
2646
2400
|
0
|
|
2647
2401
|
]);
|
|
@@ -2659,7 +2413,7 @@ function hairSway(param, mesh, box, amp) {
|
|
|
2659
2413
|
);
|
|
2660
2414
|
}
|
|
2661
2415
|
function tiltHang(mesh, box, pivot, weight, deg = ROLL_DEG) {
|
|
2662
|
-
return localWarp(
|
|
2416
|
+
return localWarp(import_format3.StandardParameter.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
|
|
2663
2417
|
const g = weight(y, i);
|
|
2664
2418
|
if (g === 0 || v === 0) return [0, 0];
|
|
2665
2419
|
const a = -g * rollOf(v, deg);
|
|
@@ -2908,16 +2662,16 @@ function buildBodyWarp({
|
|
|
2908
2662
|
points: ys.flatMap((y) => xs.flatMap((x) => [x, y]))
|
|
2909
2663
|
},
|
|
2910
2664
|
warps: [
|
|
2911
|
-
warp(
|
|
2912
|
-
warp(
|
|
2665
|
+
warp(import_format4.StandardParameter.BodyAngleX, BODY_STOPS, (x, _y, t) => [turn(x, t), 0]),
|
|
2666
|
+
warp(import_format4.StandardParameter.BodyAngleY, BODY_STOPS, (_x, _y, t) => [0, t * BODY.bow * hh]),
|
|
2913
2667
|
warp(
|
|
2914
|
-
|
|
2668
|
+
import_format4.StandardParameter.BodyAngleZ,
|
|
2915
2669
|
BODY_STOPS,
|
|
2916
2670
|
(x, y, t) => roll(x, y, -t * BODY.rollDeg)
|
|
2917
2671
|
),
|
|
2918
|
-
warp(
|
|
2919
|
-
warp(
|
|
2920
|
-
warp(
|
|
2672
|
+
warp(import_format4.StandardParameter.AngleX, X_STOPS, (x, _y, t) => [BODY.followX * turn(x, t), 0]),
|
|
2673
|
+
warp(import_format4.StandardParameter.AngleZ, Z_STOPS, (x, y, t) => roll(x, y, -t * BODY.followRoll)),
|
|
2674
|
+
warp(import_format4.StandardParameter.Breath, [0, 1], (_x, _y, t) => [0, t * AMPLITUDE.breathBody * hh])
|
|
2921
2675
|
]
|
|
2922
2676
|
};
|
|
2923
2677
|
refuseFold(body, deformer, anchor, [chin, ...pivots]);
|
|
@@ -3000,19 +2754,25 @@ function headOwnBreath(hasBody) {
|
|
|
3000
2754
|
var ELBOW_AT = 0.42;
|
|
3001
2755
|
var CAP_ROWS = [0.1, 0.3];
|
|
3002
2756
|
var CAP_SEGMENTS = 12;
|
|
3003
|
-
var
|
|
2757
|
+
var CAP_INSET = 3;
|
|
2758
|
+
var capInset = (i) => Math.round(CAP_INSET * Math.min(1, Math.min(i, CAP_SEGMENTS - i) / 2));
|
|
2759
|
+
var CAP_RIM = 0.25;
|
|
2760
|
+
var ARM_RANGE = [-8, 32];
|
|
2761
|
+
var ELBOW_RANGE = [-10, 90];
|
|
3004
2762
|
var ARM_PARAMS = {
|
|
3005
|
-
arm_L: { arm:
|
|
3006
|
-
arm_R: { arm:
|
|
2763
|
+
arm_L: { arm: import_format5.StandardParameter.ArmLeft, elbow: import_format5.StandardParameter.ElbowLeft },
|
|
2764
|
+
arm_R: { arm: import_format5.StandardParameter.ArmRight, elbow: import_format5.StandardParameter.ElbowRight }
|
|
3007
2765
|
};
|
|
3008
2766
|
var ARM_IDS = {
|
|
3009
2767
|
arm_L: {
|
|
3010
2768
|
forearm: "forearm_L",
|
|
2769
|
+
cap: "elbow_L",
|
|
3011
2770
|
armDeformer: "armDeformer_L",
|
|
3012
2771
|
forearmDeformer: "forearmDeformer_L"
|
|
3013
2772
|
},
|
|
3014
2773
|
arm_R: {
|
|
3015
2774
|
forearm: "forearm_R",
|
|
2775
|
+
cap: "elbow_R",
|
|
3016
2776
|
armDeformer: "armDeformer_R",
|
|
3017
2777
|
forearmDeformer: "forearmDeformer_R"
|
|
3018
2778
|
}
|
|
@@ -3065,11 +2825,30 @@ function armGeometry(layer, bodyAxisX) {
|
|
|
3065
2825
|
b.x1 - elbow.x,
|
|
3066
2826
|
b.y1 - elbow.y
|
|
3067
2827
|
);
|
|
2828
|
+
const inside = (x, y) => {
|
|
2829
|
+
const k = Math.floor(y) - bbox.y;
|
|
2830
|
+
if (k < 0 || k >= bbox.h) return false;
|
|
2831
|
+
const [rs, re] = span(k);
|
|
2832
|
+
return rs < x && x < re;
|
|
2833
|
+
};
|
|
2834
|
+
const capRays = Array.from({ length: CAP_SEGMENTS + 1 }, (_, i) => {
|
|
2835
|
+
const a = Math.PI * i / CAP_SEGMENTS;
|
|
2836
|
+
let t = 1;
|
|
2837
|
+
while (t <= capRadius + CAP_INSET && inside(
|
|
2838
|
+
elbow.x + canvasW / 2 + t * Math.cos(a),
|
|
2839
|
+
canvasH / 2 - elbow.y - t * Math.sin(a)
|
|
2840
|
+
)) {
|
|
2841
|
+
t++;
|
|
2842
|
+
}
|
|
2843
|
+
return Math.min(capRadius, Math.max(1, t - capInset(i)));
|
|
2844
|
+
});
|
|
3068
2845
|
return {
|
|
3069
2846
|
shoulder,
|
|
3070
2847
|
shoulderRadius: ru,
|
|
3071
2848
|
elbow,
|
|
3072
2849
|
capRadius,
|
|
2850
|
+
capRays,
|
|
2851
|
+
seamRun: [s - bbox.x, e - bbox.x],
|
|
3073
2852
|
side: shoulder.x > bodyAxisX ? 1 : -1
|
|
3074
2853
|
};
|
|
3075
2854
|
}
|
|
@@ -3084,72 +2863,351 @@ function armParts(role, layer, g, order) {
|
|
|
3084
2863
|
const lx = (x) => roundTo((x - cx(b)) / bw(b), 1e-5);
|
|
3085
2864
|
const ly = (y) => roundTo((y - cy(b)) / bh(b), 1e-5);
|
|
3086
2865
|
const seam = ly(g.elbow.y);
|
|
3087
|
-
const band = (
|
|
2866
|
+
const band = (top2, bottom) => [
|
|
3088
2867
|
-0.5,
|
|
3089
|
-
|
|
2868
|
+
top2,
|
|
3090
2869
|
0.5,
|
|
3091
|
-
|
|
2870
|
+
top2,
|
|
3092
2871
|
-0.5,
|
|
3093
2872
|
bottom,
|
|
3094
2873
|
0.5,
|
|
3095
2874
|
bottom
|
|
3096
2875
|
];
|
|
3097
2876
|
const quad = [2, 3, 0, 0, 3, 1];
|
|
3098
|
-
const
|
|
2877
|
+
const rays = g.capRays.length;
|
|
2878
|
+
const top = (rays - 1) / 2;
|
|
2879
|
+
const at = (i, r) => {
|
|
2880
|
+
const a = Math.PI * i / (rays - 1);
|
|
2881
|
+
return [lx(g.elbow.x + r * Math.cos(a)), ly(g.elbow.y + r * Math.sin(a))];
|
|
2882
|
+
};
|
|
2883
|
+
const width = (i) => Math.min(CAP_RIM * g.capRadius, g.capRays[i] / 2);
|
|
2884
|
+
const ringRays = Array.from({ length: rays }, (_, i) => i);
|
|
2885
|
+
ringRays.splice(top, 0, top);
|
|
2886
|
+
const vertices = [lx(g.elbow.x), seam];
|
|
2887
|
+
for (let i = 0; i < rays; i++) {
|
|
2888
|
+
vertices.push(...at(i, g.capRays[i] - width(i)));
|
|
2889
|
+
}
|
|
2890
|
+
const ringInner = vertices.length / 2;
|
|
2891
|
+
for (const i of ringRays) vertices.push(...at(i, g.capRays[i] - width(i)));
|
|
2892
|
+
const ringOuter = vertices.length / 2;
|
|
2893
|
+
for (const i of ringRays) vertices.push(...at(i, g.capRays[i]));
|
|
2894
|
+
const { uvs } = meshOf(vertices, []);
|
|
2895
|
+
const col = (c) => roundTo(Math.min(Math.max(c + 0.5, 0.5), bw(b) - 0.5) / bw(b), 1e-5);
|
|
2896
|
+
const v = roundTo(0.5 - seam, 1e-5);
|
|
2897
|
+
ringRays.forEach((i, j) => {
|
|
2898
|
+
const right = j <= top;
|
|
2899
|
+
const outer = right ? g.seamRun[1] : g.seamRun[0] - 1;
|
|
2900
|
+
const step = right ? -width(i) : width(i);
|
|
2901
|
+
uvs[(ringInner + j) * 2] = col(outer + step);
|
|
2902
|
+
uvs[(ringInner + j) * 2 + 1] = v;
|
|
2903
|
+
uvs[(ringOuter + j) * 2] = col(outer);
|
|
2904
|
+
uvs[(ringOuter + j) * 2 + 1] = v;
|
|
2905
|
+
});
|
|
3099
2906
|
const fan = [];
|
|
3100
|
-
for (let i = 0; i
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
);
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
const part = (id, deformer, at, mesh) => ({
|
|
2907
|
+
for (let i = 0; i < rays - 1; i++) fan.push(0, 1 + i, 2 + i);
|
|
2908
|
+
const ring = [];
|
|
2909
|
+
for (let j = 0; j < ringRays.length - 1; j++) {
|
|
2910
|
+
if (j === top) continue;
|
|
2911
|
+
const [p, q] = [ringInner + j, ringOuter + j];
|
|
2912
|
+
ring.push(p, q, q + 1, p, q + 1, p + 1);
|
|
2913
|
+
}
|
|
2914
|
+
const part = (id, deformer, z, mesh) => ({
|
|
3109
2915
|
id,
|
|
3110
2916
|
color: [1, 1, 1, 1],
|
|
3111
2917
|
width: bw(b),
|
|
3112
2918
|
height: bh(b),
|
|
3113
2919
|
transform: { x: cx(b), y: cy(b) },
|
|
3114
|
-
order:
|
|
2920
|
+
order: z,
|
|
3115
2921
|
deformer,
|
|
3116
2922
|
mesh
|
|
3117
2923
|
});
|
|
3118
2924
|
const ids = ARM_IDS[role];
|
|
3119
2925
|
return [
|
|
3120
|
-
part(
|
|
2926
|
+
part(ids.cap, ids.forearmDeformer, order, {
|
|
2927
|
+
vertices,
|
|
2928
|
+
uvs,
|
|
2929
|
+
indices: [...fan, ...ring]
|
|
2930
|
+
}),
|
|
2931
|
+
part(role, ids.armDeformer, order + 1, meshOf(band(0.5, seam), quad)),
|
|
3121
2932
|
part(
|
|
3122
2933
|
ids.forearm,
|
|
3123
2934
|
ids.forearmDeformer,
|
|
3124
|
-
order +
|
|
3125
|
-
meshOf(
|
|
2935
|
+
order + 2,
|
|
2936
|
+
meshOf(band(seam, -0.5), quad)
|
|
3126
2937
|
)
|
|
3127
2938
|
];
|
|
3128
2939
|
}
|
|
3129
2940
|
function armDeformers(role, g) {
|
|
3130
2941
|
const ids = ARM_IDS[role];
|
|
3131
2942
|
const params = ARM_PARAMS[role];
|
|
3132
|
-
const rotate = (parameter) => ({
|
|
2943
|
+
const rotate = (parameter, range, sign) => ({
|
|
3133
2944
|
parameter,
|
|
3134
2945
|
channel: "rotate",
|
|
3135
|
-
from:
|
|
3136
|
-
to:
|
|
2946
|
+
from: sign * range[0],
|
|
2947
|
+
to: sign * range[1]
|
|
3137
2948
|
});
|
|
3138
2949
|
return [
|
|
3139
2950
|
{
|
|
3140
2951
|
id: ids.armDeformer,
|
|
3141
2952
|
parent: BODY_WARP_ID,
|
|
3142
2953
|
pivot: { ...g.shoulder },
|
|
3143
|
-
bindings: [rotate(params.arm)]
|
|
2954
|
+
bindings: [rotate(params.arm, ARM_RANGE, g.side)]
|
|
3144
2955
|
},
|
|
3145
2956
|
{
|
|
3146
2957
|
id: ids.forearmDeformer,
|
|
3147
2958
|
parent: ids.armDeformer,
|
|
3148
2959
|
pivot: { ...g.elbow },
|
|
3149
|
-
bindings: [rotate(params.elbow)]
|
|
2960
|
+
bindings: [rotate(params.elbow, ELBOW_RANGE, -g.side)]
|
|
2961
|
+
}
|
|
2962
|
+
];
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
// src/auto-rig/roles.ts
|
|
2966
|
+
var ROLE_TABLE = [
|
|
2967
|
+
{ role: "hair_back", family: "hair_back" },
|
|
2968
|
+
{ role: "body", family: "body" },
|
|
2969
|
+
{ role: "arm_L", family: "arm", parts: ["elbow_L", "arm_L", "forearm_L"] },
|
|
2970
|
+
{ role: "arm_R", family: "arm", parts: ["elbow_R", "arm_R", "forearm_R"] },
|
|
2971
|
+
{ role: "face", family: "face", required: true },
|
|
2972
|
+
{ role: "blush_L", family: "face" },
|
|
2973
|
+
{ role: "blush_R", family: "face" },
|
|
2974
|
+
{ role: "nose", family: "nose" },
|
|
2975
|
+
{ role: "mouth", family: "mouth", required: true },
|
|
2976
|
+
{ role: "mouth_open", family: "mouth" },
|
|
2977
|
+
{ role: "eye_L", family: "eye_L", required: true },
|
|
2978
|
+
{ role: "eye_R", family: "eye_R", required: true },
|
|
2979
|
+
{ role: "iris_L", family: "eye_L" },
|
|
2980
|
+
{ role: "iris_R", family: "eye_R" },
|
|
2981
|
+
{ role: "pupil_L", family: "eye_L" },
|
|
2982
|
+
{ role: "pupil_R", family: "eye_R" },
|
|
2983
|
+
{ role: "highlight_L", family: "eye_L" },
|
|
2984
|
+
{ role: "highlight_R", family: "eye_R" },
|
|
2985
|
+
{ role: "lash_lower_L", family: "eye_L" },
|
|
2986
|
+
{ role: "lash_lower_R", family: "eye_R" },
|
|
2987
|
+
{ role: "lash_L", family: "eye_L" },
|
|
2988
|
+
{ role: "lash_R", family: "eye_R" },
|
|
2989
|
+
{ role: "brow_L", family: "brow_L" },
|
|
2990
|
+
{ role: "brow_R", family: "brow_R" },
|
|
2991
|
+
{ role: "hair_front", family: "hair_front" }
|
|
2992
|
+
];
|
|
2993
|
+
var REQUIRED_ROLES = ROLE_TABLE.filter(
|
|
2994
|
+
(r) => r.required
|
|
2995
|
+
).map((r) => r.role);
|
|
2996
|
+
var SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));
|
|
2997
|
+
function roleSpec(role) {
|
|
2998
|
+
const spec = SPEC_BY_ROLE.get(role);
|
|
2999
|
+
if (spec === void 0) throw new Error(`auto-rig: unknown role "${role}"`);
|
|
3000
|
+
return spec;
|
|
3001
|
+
}
|
|
3002
|
+
function partIdsOfRole(role) {
|
|
3003
|
+
return roleSpec(role).parts ?? [role];
|
|
3004
|
+
}
|
|
3005
|
+
var ROLE_BY_PART = new Map(
|
|
3006
|
+
ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role]))
|
|
3007
|
+
);
|
|
3008
|
+
function roleOfPart(partId) {
|
|
3009
|
+
return ROLE_BY_PART.get(partId) ?? partId;
|
|
3010
|
+
}
|
|
3011
|
+
var ALIASES = {
|
|
3012
|
+
eyebrow_L: "brow_L",
|
|
3013
|
+
eyebrow_R: "brow_R",
|
|
3014
|
+
eye_white_L: "eye_L",
|
|
3015
|
+
eye_white_R: "eye_R"
|
|
3016
|
+
};
|
|
3017
|
+
function roleOf(fileName) {
|
|
3018
|
+
const role = fileName.replace(/\.[^.]+$/, "").toLowerCase().replace(/[-\s]+/g, "_").replace(/_([lr])$/, (_, s) => `_${s.toUpperCase()}`);
|
|
3019
|
+
return ALIASES[role] ?? role;
|
|
3020
|
+
}
|
|
3021
|
+
function checkArmsHaveBody(roles) {
|
|
3022
|
+
const has = new Set(roles);
|
|
3023
|
+
if (has.has("body")) return;
|
|
3024
|
+
const arm = ROLE_TABLE.find((r) => r.family === "arm" && has.has(r.role));
|
|
3025
|
+
if (arm !== void 0) {
|
|
3026
|
+
throw new Error(
|
|
3027
|
+
`auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
function parseLayerRoles(fileNames) {
|
|
3032
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3033
|
+
const out = [];
|
|
3034
|
+
for (const fileName of fileNames) {
|
|
3035
|
+
const role = roleOf(fileName);
|
|
3036
|
+
if (!SPEC_BY_ROLE.has(role)) {
|
|
3037
|
+
throw new Error(
|
|
3038
|
+
`auto-rig: "${fileName}" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(", ")})`
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
const prior = seen.get(role);
|
|
3042
|
+
if (prior !== void 0) {
|
|
3043
|
+
throw new Error(
|
|
3044
|
+
`auto-rig: role "${role}" is named twice ("${prior}" and "${fileName}")`
|
|
3045
|
+
);
|
|
3150
3046
|
}
|
|
3047
|
+
seen.set(role, fileName);
|
|
3048
|
+
out.push({ role, fileName });
|
|
3049
|
+
}
|
|
3050
|
+
const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));
|
|
3051
|
+
if (missing.length > 0) {
|
|
3052
|
+
throw new Error(
|
|
3053
|
+
`auto-rig: missing required role${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`
|
|
3054
|
+
);
|
|
3055
|
+
}
|
|
3056
|
+
checkArmsHaveBody(seen.keys());
|
|
3057
|
+
return out;
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
// src/auto-rig/generate.ts
|
|
3061
|
+
var import_format8 = require("@ikijs/format");
|
|
3062
|
+
|
|
3063
|
+
// src/auto-rig/animations.ts
|
|
3064
|
+
var import_format6 = require("@ikijs/format");
|
|
3065
|
+
function browsY(y) {
|
|
3066
|
+
return [
|
|
3067
|
+
{ parameter: import_format6.StandardParameter.BrowLeftY, value: y, blend: "add" },
|
|
3068
|
+
{ parameter: import_format6.StandardParameter.BrowRightY, value: y, blend: "add" }
|
|
3151
3069
|
];
|
|
3152
3070
|
}
|
|
3071
|
+
function browsTilt(innerDown) {
|
|
3072
|
+
return [
|
|
3073
|
+
{ parameter: import_format6.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
3074
|
+
{ parameter: import_format6.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
3075
|
+
];
|
|
3076
|
+
}
|
|
3077
|
+
function cheek(value) {
|
|
3078
|
+
return { parameter: import_format6.StandardParameter.Cheek, value, blend: "add" };
|
|
3079
|
+
}
|
|
3080
|
+
var BROWS = [import_format6.StandardParameter.BrowLeftY, import_format6.StandardParameter.BrowRightY, import_format6.StandardParameter.BrowLeftAngle, import_format6.StandardParameter.BrowRightAngle];
|
|
3081
|
+
var EXPRESSIONS = [
|
|
3082
|
+
{
|
|
3083
|
+
id: "smile",
|
|
3084
|
+
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
3085
|
+
parameters: [
|
|
3086
|
+
{ parameter: import_format6.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
3087
|
+
...browsY(0.25),
|
|
3088
|
+
cheek(0.4)
|
|
3089
|
+
]
|
|
3090
|
+
},
|
|
3091
|
+
{
|
|
3092
|
+
id: "laugh",
|
|
3093
|
+
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
3094
|
+
parameters: [
|
|
3095
|
+
{ parameter: import_format6.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
3096
|
+
{ parameter: import_format6.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
|
|
3097
|
+
{ parameter: import_format6.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
3098
|
+
{ parameter: import_format6.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
3099
|
+
...browsY(0.4),
|
|
3100
|
+
cheek(0.65)
|
|
3101
|
+
]
|
|
3102
|
+
},
|
|
3103
|
+
{
|
|
3104
|
+
id: "angry",
|
|
3105
|
+
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
3106
|
+
needs: BROWS,
|
|
3107
|
+
parameters: [
|
|
3108
|
+
...browsY(-0.5),
|
|
3109
|
+
...browsTilt(0.8),
|
|
3110
|
+
{ parameter: import_format6.StandardParameter.MouthForm, value: -0.9, blend: "add" }
|
|
3111
|
+
]
|
|
3112
|
+
},
|
|
3113
|
+
{
|
|
3114
|
+
id: "sad",
|
|
3115
|
+
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
3116
|
+
needs: BROWS,
|
|
3117
|
+
parameters: [
|
|
3118
|
+
...browsY(0.35),
|
|
3119
|
+
...browsTilt(-0.8),
|
|
3120
|
+
{ parameter: import_format6.StandardParameter.MouthForm, value: -0.8, blend: "add" }
|
|
3121
|
+
]
|
|
3122
|
+
},
|
|
3123
|
+
{
|
|
3124
|
+
id: "surprised",
|
|
3125
|
+
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
3126
|
+
parameters: [
|
|
3127
|
+
...browsY(0.8),
|
|
3128
|
+
{ parameter: import_format6.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
3129
|
+
]
|
|
3130
|
+
},
|
|
3131
|
+
{
|
|
3132
|
+
id: "shy",
|
|
3133
|
+
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
3134
|
+
needs: [import_format6.StandardParameter.Cheek],
|
|
3135
|
+
parameters: [
|
|
3136
|
+
cheek(1),
|
|
3137
|
+
// Gaze down.
|
|
3138
|
+
{ parameter: import_format6.StandardParameter.EyeballY, value: -0.65, blend: "add" },
|
|
3139
|
+
{ parameter: import_format6.StandardParameter.MouthForm, value: 0.4, blend: "add" },
|
|
3140
|
+
...browsTilt(-0.25)
|
|
3141
|
+
]
|
|
3142
|
+
}
|
|
3143
|
+
];
|
|
3144
|
+
function defaultExpressions(declared) {
|
|
3145
|
+
return EXPRESSIONS.filter(
|
|
3146
|
+
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
3147
|
+
).map(({ needs: _needs, ...e }) => ({
|
|
3148
|
+
...e,
|
|
3149
|
+
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
3150
|
+
}));
|
|
3151
|
+
}
|
|
3152
|
+
var DEFAULT_MOTIONS = {
|
|
3153
|
+
Nod: [
|
|
3154
|
+
{
|
|
3155
|
+
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
3156
|
+
duration: 1,
|
|
3157
|
+
curves: [
|
|
3158
|
+
{
|
|
3159
|
+
parameter: import_format6.StandardParameter.AngleY,
|
|
3160
|
+
keys: [
|
|
3161
|
+
[0, 0],
|
|
3162
|
+
[0.3, -18],
|
|
3163
|
+
[0.6, 4],
|
|
3164
|
+
[0.8, -1],
|
|
3165
|
+
[1, 0]
|
|
3166
|
+
]
|
|
3167
|
+
}
|
|
3168
|
+
]
|
|
3169
|
+
}
|
|
3170
|
+
],
|
|
3171
|
+
Shake: [
|
|
3172
|
+
{
|
|
3173
|
+
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
3174
|
+
duration: 1.2,
|
|
3175
|
+
// The first swing peaks at 0.2 s, which the default fade would still
|
|
3176
|
+
// be damping.
|
|
3177
|
+
fadeIn: 0.15,
|
|
3178
|
+
curves: [
|
|
3179
|
+
{
|
|
3180
|
+
parameter: import_format6.StandardParameter.AngleX,
|
|
3181
|
+
keys: [
|
|
3182
|
+
[0, 0],
|
|
3183
|
+
[0.2, -18],
|
|
3184
|
+
[0.45, 18],
|
|
3185
|
+
[0.7, -16],
|
|
3186
|
+
[0.95, 10],
|
|
3187
|
+
[1.2, 0]
|
|
3188
|
+
]
|
|
3189
|
+
}
|
|
3190
|
+
]
|
|
3191
|
+
}
|
|
3192
|
+
],
|
|
3193
|
+
Tilt: [
|
|
3194
|
+
{
|
|
3195
|
+
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
3196
|
+
duration: 1.4,
|
|
3197
|
+
curves: [
|
|
3198
|
+
{
|
|
3199
|
+
parameter: import_format6.StandardParameter.AngleZ,
|
|
3200
|
+
keys: [
|
|
3201
|
+
[0, 0],
|
|
3202
|
+
[0.35, 20],
|
|
3203
|
+
[1, 20],
|
|
3204
|
+
[1.4, 0]
|
|
3205
|
+
]
|
|
3206
|
+
}
|
|
3207
|
+
]
|
|
3208
|
+
}
|
|
3209
|
+
]
|
|
3210
|
+
};
|
|
3153
3211
|
|
|
3154
3212
|
// src/auto-rig/checks.ts
|
|
3155
3213
|
var finite = (v) => typeof v === "number" && Number.isFinite(v);
|
|
@@ -5722,13 +5780,14 @@ function declareParameters(roles) {
|
|
|
5722
5780
|
add(import_format8.StandardParameter.BodyAngleZ, "Body Angle Z", -10, 10, 0);
|
|
5723
5781
|
}
|
|
5724
5782
|
const [armMin, armMax] = ARM_RANGE;
|
|
5783
|
+
const [elbowMin, elbowMax] = ELBOW_RANGE;
|
|
5725
5784
|
if (roles.has("arm_L")) {
|
|
5726
5785
|
add(import_format8.StandardParameter.ArmLeft, "Arm L", armMin, armMax, 0);
|
|
5727
|
-
add(import_format8.StandardParameter.ElbowLeft, "Elbow L",
|
|
5786
|
+
add(import_format8.StandardParameter.ElbowLeft, "Elbow L", elbowMin, elbowMax, 0);
|
|
5728
5787
|
}
|
|
5729
5788
|
if (roles.has("arm_R")) {
|
|
5730
5789
|
add(import_format8.StandardParameter.ArmRight, "Arm R", armMin, armMax, 0);
|
|
5731
|
-
add(import_format8.StandardParameter.ElbowRight, "Elbow R",
|
|
5790
|
+
add(import_format8.StandardParameter.ElbowRight, "Elbow R", elbowMin, elbowMax, 0);
|
|
5732
5791
|
}
|
|
5733
5792
|
add(import_format8.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
|
|
5734
5793
|
add(import_format8.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
|
|
@@ -5790,6 +5849,7 @@ function declareParameters(roles) {
|
|
|
5790
5849
|
SetPhysicsRig,
|
|
5791
5850
|
TurnTargetError,
|
|
5792
5851
|
UV_INSET_PX,
|
|
5852
|
+
armGeometry,
|
|
5793
5853
|
captureBindingEndpoint,
|
|
5794
5854
|
computeGridOffsets,
|
|
5795
5855
|
createDefaultMatrixDeformer,
|