@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.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]);
|
|
@@ -2937,19 +2684,25 @@ function headOwnBreath(hasBody) {
|
|
|
2937
2684
|
var ELBOW_AT = 0.42;
|
|
2938
2685
|
var CAP_ROWS = [0.1, 0.3];
|
|
2939
2686
|
var CAP_SEGMENTS = 12;
|
|
2940
|
-
var
|
|
2687
|
+
var CAP_INSET = 3;
|
|
2688
|
+
var capInset = (i) => Math.round(CAP_INSET * Math.min(1, Math.min(i, CAP_SEGMENTS - i) / 2));
|
|
2689
|
+
var CAP_RIM = 0.25;
|
|
2690
|
+
var ARM_RANGE = [-8, 32];
|
|
2691
|
+
var ELBOW_RANGE = [-10, 90];
|
|
2941
2692
|
var ARM_PARAMS = {
|
|
2942
|
-
arm_L: { arm:
|
|
2943
|
-
arm_R: { arm:
|
|
2693
|
+
arm_L: { arm: P3.ArmLeft, elbow: P3.ElbowLeft },
|
|
2694
|
+
arm_R: { arm: P3.ArmRight, elbow: P3.ElbowRight }
|
|
2944
2695
|
};
|
|
2945
2696
|
var ARM_IDS = {
|
|
2946
2697
|
arm_L: {
|
|
2947
2698
|
forearm: "forearm_L",
|
|
2699
|
+
cap: "elbow_L",
|
|
2948
2700
|
armDeformer: "armDeformer_L",
|
|
2949
2701
|
forearmDeformer: "forearmDeformer_L"
|
|
2950
2702
|
},
|
|
2951
2703
|
arm_R: {
|
|
2952
2704
|
forearm: "forearm_R",
|
|
2705
|
+
cap: "elbow_R",
|
|
2953
2706
|
armDeformer: "armDeformer_R",
|
|
2954
2707
|
forearmDeformer: "forearmDeformer_R"
|
|
2955
2708
|
}
|
|
@@ -3002,11 +2755,30 @@ function armGeometry(layer, bodyAxisX) {
|
|
|
3002
2755
|
b.x1 - elbow.x,
|
|
3003
2756
|
b.y1 - elbow.y
|
|
3004
2757
|
);
|
|
2758
|
+
const inside = (x, y) => {
|
|
2759
|
+
const k = Math.floor(y) - bbox.y;
|
|
2760
|
+
if (k < 0 || k >= bbox.h) return false;
|
|
2761
|
+
const [rs, re] = span(k);
|
|
2762
|
+
return rs < x && x < re;
|
|
2763
|
+
};
|
|
2764
|
+
const capRays = Array.from({ length: CAP_SEGMENTS + 1 }, (_, i) => {
|
|
2765
|
+
const a = Math.PI * i / CAP_SEGMENTS;
|
|
2766
|
+
let t = 1;
|
|
2767
|
+
while (t <= capRadius + CAP_INSET && inside(
|
|
2768
|
+
elbow.x + canvasW / 2 + t * Math.cos(a),
|
|
2769
|
+
canvasH / 2 - elbow.y - t * Math.sin(a)
|
|
2770
|
+
)) {
|
|
2771
|
+
t++;
|
|
2772
|
+
}
|
|
2773
|
+
return Math.min(capRadius, Math.max(1, t - capInset(i)));
|
|
2774
|
+
});
|
|
3005
2775
|
return {
|
|
3006
2776
|
shoulder,
|
|
3007
2777
|
shoulderRadius: ru,
|
|
3008
2778
|
elbow,
|
|
3009
2779
|
capRadius,
|
|
2780
|
+
capRays,
|
|
2781
|
+
seamRun: [s - bbox.x, e - bbox.x],
|
|
3010
2782
|
side: shoulder.x > bodyAxisX ? 1 : -1
|
|
3011
2783
|
};
|
|
3012
2784
|
}
|
|
@@ -3021,73 +2793,358 @@ function armParts(role, layer, g, order) {
|
|
|
3021
2793
|
const lx = (x) => roundTo((x - cx(b)) / bw(b), 1e-5);
|
|
3022
2794
|
const ly = (y) => roundTo((y - cy(b)) / bh(b), 1e-5);
|
|
3023
2795
|
const seam = ly(g.elbow.y);
|
|
3024
|
-
const band = (
|
|
2796
|
+
const band = (top2, bottom) => [
|
|
3025
2797
|
-0.5,
|
|
3026
|
-
|
|
2798
|
+
top2,
|
|
3027
2799
|
0.5,
|
|
3028
|
-
|
|
2800
|
+
top2,
|
|
3029
2801
|
-0.5,
|
|
3030
2802
|
bottom,
|
|
3031
2803
|
0.5,
|
|
3032
2804
|
bottom
|
|
3033
2805
|
];
|
|
3034
2806
|
const quad = [2, 3, 0, 0, 3, 1];
|
|
3035
|
-
const
|
|
2807
|
+
const rays = g.capRays.length;
|
|
2808
|
+
const top = (rays - 1) / 2;
|
|
2809
|
+
const at = (i, r) => {
|
|
2810
|
+
const a = Math.PI * i / (rays - 1);
|
|
2811
|
+
return [lx(g.elbow.x + r * Math.cos(a)), ly(g.elbow.y + r * Math.sin(a))];
|
|
2812
|
+
};
|
|
2813
|
+
const width = (i) => Math.min(CAP_RIM * g.capRadius, g.capRays[i] / 2);
|
|
2814
|
+
const ringRays = Array.from({ length: rays }, (_, i) => i);
|
|
2815
|
+
ringRays.splice(top, 0, top);
|
|
2816
|
+
const vertices = [lx(g.elbow.x), seam];
|
|
2817
|
+
for (let i = 0; i < rays; i++) {
|
|
2818
|
+
vertices.push(...at(i, g.capRays[i] - width(i)));
|
|
2819
|
+
}
|
|
2820
|
+
const ringInner = vertices.length / 2;
|
|
2821
|
+
for (const i of ringRays) vertices.push(...at(i, g.capRays[i] - width(i)));
|
|
2822
|
+
const ringOuter = vertices.length / 2;
|
|
2823
|
+
for (const i of ringRays) vertices.push(...at(i, g.capRays[i]));
|
|
2824
|
+
const { uvs } = meshOf(vertices, []);
|
|
2825
|
+
const col = (c) => roundTo(Math.min(Math.max(c + 0.5, 0.5), bw(b) - 0.5) / bw(b), 1e-5);
|
|
2826
|
+
const v = roundTo(0.5 - seam, 1e-5);
|
|
2827
|
+
ringRays.forEach((i, j) => {
|
|
2828
|
+
const right = j <= top;
|
|
2829
|
+
const outer = right ? g.seamRun[1] : g.seamRun[0] - 1;
|
|
2830
|
+
const step = right ? -width(i) : width(i);
|
|
2831
|
+
uvs[(ringInner + j) * 2] = col(outer + step);
|
|
2832
|
+
uvs[(ringInner + j) * 2 + 1] = v;
|
|
2833
|
+
uvs[(ringOuter + j) * 2] = col(outer);
|
|
2834
|
+
uvs[(ringOuter + j) * 2 + 1] = v;
|
|
2835
|
+
});
|
|
3036
2836
|
const fan = [];
|
|
3037
|
-
for (let i = 0; i
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
);
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
const part = (id, deformer, at, mesh) => ({
|
|
2837
|
+
for (let i = 0; i < rays - 1; i++) fan.push(0, 1 + i, 2 + i);
|
|
2838
|
+
const ring = [];
|
|
2839
|
+
for (let j = 0; j < ringRays.length - 1; j++) {
|
|
2840
|
+
if (j === top) continue;
|
|
2841
|
+
const [p, q] = [ringInner + j, ringOuter + j];
|
|
2842
|
+
ring.push(p, q, q + 1, p, q + 1, p + 1);
|
|
2843
|
+
}
|
|
2844
|
+
const part = (id, deformer, z, mesh) => ({
|
|
3046
2845
|
id,
|
|
3047
2846
|
color: [1, 1, 1, 1],
|
|
3048
2847
|
width: bw(b),
|
|
3049
2848
|
height: bh(b),
|
|
3050
2849
|
transform: { x: cx(b), y: cy(b) },
|
|
3051
|
-
order:
|
|
2850
|
+
order: z,
|
|
3052
2851
|
deformer,
|
|
3053
2852
|
mesh
|
|
3054
2853
|
});
|
|
3055
2854
|
const ids = ARM_IDS[role];
|
|
3056
2855
|
return [
|
|
3057
|
-
part(
|
|
2856
|
+
part(ids.cap, ids.forearmDeformer, order, {
|
|
2857
|
+
vertices,
|
|
2858
|
+
uvs,
|
|
2859
|
+
indices: [...fan, ...ring]
|
|
2860
|
+
}),
|
|
2861
|
+
part(role, ids.armDeformer, order + 1, meshOf(band(0.5, seam), quad)),
|
|
3058
2862
|
part(
|
|
3059
2863
|
ids.forearm,
|
|
3060
2864
|
ids.forearmDeformer,
|
|
3061
|
-
order +
|
|
3062
|
-
meshOf(
|
|
2865
|
+
order + 2,
|
|
2866
|
+
meshOf(band(seam, -0.5), quad)
|
|
3063
2867
|
)
|
|
3064
2868
|
];
|
|
3065
2869
|
}
|
|
3066
2870
|
function armDeformers(role, g) {
|
|
3067
2871
|
const ids = ARM_IDS[role];
|
|
3068
2872
|
const params = ARM_PARAMS[role];
|
|
3069
|
-
const rotate = (parameter) => ({
|
|
2873
|
+
const rotate = (parameter, range, sign) => ({
|
|
3070
2874
|
parameter,
|
|
3071
2875
|
channel: "rotate",
|
|
3072
|
-
from:
|
|
3073
|
-
to:
|
|
2876
|
+
from: sign * range[0],
|
|
2877
|
+
to: sign * range[1]
|
|
3074
2878
|
});
|
|
3075
2879
|
return [
|
|
3076
2880
|
{
|
|
3077
2881
|
id: ids.armDeformer,
|
|
3078
2882
|
parent: BODY_WARP_ID,
|
|
3079
2883
|
pivot: { ...g.shoulder },
|
|
3080
|
-
bindings: [rotate(params.arm)]
|
|
2884
|
+
bindings: [rotate(params.arm, ARM_RANGE, g.side)]
|
|
3081
2885
|
},
|
|
3082
2886
|
{
|
|
3083
2887
|
id: ids.forearmDeformer,
|
|
3084
2888
|
parent: ids.armDeformer,
|
|
3085
2889
|
pivot: { ...g.elbow },
|
|
3086
|
-
bindings: [rotate(params.elbow)]
|
|
2890
|
+
bindings: [rotate(params.elbow, ELBOW_RANGE, -g.side)]
|
|
3087
2891
|
}
|
|
3088
2892
|
];
|
|
3089
2893
|
}
|
|
3090
2894
|
|
|
2895
|
+
// src/auto-rig/roles.ts
|
|
2896
|
+
var ROLE_TABLE = [
|
|
2897
|
+
{ role: "hair_back", family: "hair_back" },
|
|
2898
|
+
{ role: "body", family: "body" },
|
|
2899
|
+
{ role: "arm_L", family: "arm", parts: ["elbow_L", "arm_L", "forearm_L"] },
|
|
2900
|
+
{ role: "arm_R", family: "arm", parts: ["elbow_R", "arm_R", "forearm_R"] },
|
|
2901
|
+
{ role: "face", family: "face", required: true },
|
|
2902
|
+
{ role: "blush_L", family: "face" },
|
|
2903
|
+
{ role: "blush_R", family: "face" },
|
|
2904
|
+
{ role: "nose", family: "nose" },
|
|
2905
|
+
{ role: "mouth", family: "mouth", required: true },
|
|
2906
|
+
{ role: "mouth_open", family: "mouth" },
|
|
2907
|
+
{ role: "eye_L", family: "eye_L", required: true },
|
|
2908
|
+
{ role: "eye_R", family: "eye_R", required: true },
|
|
2909
|
+
{ role: "iris_L", family: "eye_L" },
|
|
2910
|
+
{ role: "iris_R", family: "eye_R" },
|
|
2911
|
+
{ role: "pupil_L", family: "eye_L" },
|
|
2912
|
+
{ role: "pupil_R", family: "eye_R" },
|
|
2913
|
+
{ role: "highlight_L", family: "eye_L" },
|
|
2914
|
+
{ role: "highlight_R", family: "eye_R" },
|
|
2915
|
+
{ role: "lash_lower_L", family: "eye_L" },
|
|
2916
|
+
{ role: "lash_lower_R", family: "eye_R" },
|
|
2917
|
+
{ role: "lash_L", family: "eye_L" },
|
|
2918
|
+
{ role: "lash_R", family: "eye_R" },
|
|
2919
|
+
{ role: "brow_L", family: "brow_L" },
|
|
2920
|
+
{ role: "brow_R", family: "brow_R" },
|
|
2921
|
+
{ role: "hair_front", family: "hair_front" }
|
|
2922
|
+
];
|
|
2923
|
+
var REQUIRED_ROLES = ROLE_TABLE.filter(
|
|
2924
|
+
(r) => r.required
|
|
2925
|
+
).map((r) => r.role);
|
|
2926
|
+
var SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));
|
|
2927
|
+
function roleSpec(role) {
|
|
2928
|
+
const spec = SPEC_BY_ROLE.get(role);
|
|
2929
|
+
if (spec === void 0) throw new Error(`auto-rig: unknown role "${role}"`);
|
|
2930
|
+
return spec;
|
|
2931
|
+
}
|
|
2932
|
+
function partIdsOfRole(role) {
|
|
2933
|
+
return roleSpec(role).parts ?? [role];
|
|
2934
|
+
}
|
|
2935
|
+
var ROLE_BY_PART = new Map(
|
|
2936
|
+
ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role]))
|
|
2937
|
+
);
|
|
2938
|
+
function roleOfPart(partId) {
|
|
2939
|
+
return ROLE_BY_PART.get(partId) ?? partId;
|
|
2940
|
+
}
|
|
2941
|
+
var ALIASES = {
|
|
2942
|
+
eyebrow_L: "brow_L",
|
|
2943
|
+
eyebrow_R: "brow_R",
|
|
2944
|
+
eye_white_L: "eye_L",
|
|
2945
|
+
eye_white_R: "eye_R"
|
|
2946
|
+
};
|
|
2947
|
+
function roleOf(fileName) {
|
|
2948
|
+
const role = fileName.replace(/\.[^.]+$/, "").toLowerCase().replace(/[-\s]+/g, "_").replace(/_([lr])$/, (_, s) => `_${s.toUpperCase()}`);
|
|
2949
|
+
return ALIASES[role] ?? role;
|
|
2950
|
+
}
|
|
2951
|
+
function checkArmsHaveBody(roles) {
|
|
2952
|
+
const has = new Set(roles);
|
|
2953
|
+
if (has.has("body")) return;
|
|
2954
|
+
const arm = ROLE_TABLE.find((r) => r.family === "arm" && has.has(r.role));
|
|
2955
|
+
if (arm !== void 0) {
|
|
2956
|
+
throw new Error(
|
|
2957
|
+
`auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`
|
|
2958
|
+
);
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
function parseLayerRoles(fileNames) {
|
|
2962
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2963
|
+
const out = [];
|
|
2964
|
+
for (const fileName of fileNames) {
|
|
2965
|
+
const role = roleOf(fileName);
|
|
2966
|
+
if (!SPEC_BY_ROLE.has(role)) {
|
|
2967
|
+
throw new Error(
|
|
2968
|
+
`auto-rig: "${fileName}" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(", ")})`
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
const prior = seen.get(role);
|
|
2972
|
+
if (prior !== void 0) {
|
|
2973
|
+
throw new Error(
|
|
2974
|
+
`auto-rig: role "${role}" is named twice ("${prior}" and "${fileName}")`
|
|
2975
|
+
);
|
|
2976
|
+
}
|
|
2977
|
+
seen.set(role, fileName);
|
|
2978
|
+
out.push({ role, fileName });
|
|
2979
|
+
}
|
|
2980
|
+
const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));
|
|
2981
|
+
if (missing.length > 0) {
|
|
2982
|
+
throw new Error(
|
|
2983
|
+
`auto-rig: missing required role${missing.length > 1 ? "s" : ""} ${missing.join(", ")}`
|
|
2984
|
+
);
|
|
2985
|
+
}
|
|
2986
|
+
checkArmsHaveBody(seen.keys());
|
|
2987
|
+
return out;
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
// src/auto-rig/generate.ts
|
|
2991
|
+
import {
|
|
2992
|
+
IKI_FORMAT_VERSION as IKI_FORMAT_VERSION2,
|
|
2993
|
+
StandardParameter as P6,
|
|
2994
|
+
parseIkiModel as parseIkiModel3
|
|
2995
|
+
} from "@ikijs/format";
|
|
2996
|
+
|
|
2997
|
+
// src/auto-rig/animations.ts
|
|
2998
|
+
import {
|
|
2999
|
+
StandardParameter as P4
|
|
3000
|
+
} from "@ikijs/format";
|
|
3001
|
+
function browsY(y) {
|
|
3002
|
+
return [
|
|
3003
|
+
{ parameter: P4.BrowLeftY, value: y, blend: "add" },
|
|
3004
|
+
{ parameter: P4.BrowRightY, value: y, blend: "add" }
|
|
3005
|
+
];
|
|
3006
|
+
}
|
|
3007
|
+
function browsTilt(innerDown) {
|
|
3008
|
+
return [
|
|
3009
|
+
{ parameter: P4.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
3010
|
+
{ parameter: P4.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
3011
|
+
];
|
|
3012
|
+
}
|
|
3013
|
+
function cheek(value) {
|
|
3014
|
+
return { parameter: P4.Cheek, value, blend: "add" };
|
|
3015
|
+
}
|
|
3016
|
+
var BROWS = [P4.BrowLeftY, P4.BrowRightY, P4.BrowLeftAngle, P4.BrowRightAngle];
|
|
3017
|
+
var EXPRESSIONS = [
|
|
3018
|
+
{
|
|
3019
|
+
id: "smile",
|
|
3020
|
+
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
3021
|
+
parameters: [
|
|
3022
|
+
{ parameter: P4.MouthForm, value: 1, blend: "add" },
|
|
3023
|
+
...browsY(0.25),
|
|
3024
|
+
cheek(0.4)
|
|
3025
|
+
]
|
|
3026
|
+
},
|
|
3027
|
+
{
|
|
3028
|
+
id: "laugh",
|
|
3029
|
+
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
3030
|
+
parameters: [
|
|
3031
|
+
{ parameter: P4.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
3032
|
+
{ parameter: P4.EyeOpenRight, value: 0, blend: "multiply" },
|
|
3033
|
+
{ parameter: P4.MouthForm, value: 1, blend: "add" },
|
|
3034
|
+
{ parameter: P4.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
3035
|
+
...browsY(0.4),
|
|
3036
|
+
cheek(0.65)
|
|
3037
|
+
]
|
|
3038
|
+
},
|
|
3039
|
+
{
|
|
3040
|
+
id: "angry",
|
|
3041
|
+
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
3042
|
+
needs: BROWS,
|
|
3043
|
+
parameters: [
|
|
3044
|
+
...browsY(-0.5),
|
|
3045
|
+
...browsTilt(0.8),
|
|
3046
|
+
{ parameter: P4.MouthForm, value: -0.9, blend: "add" }
|
|
3047
|
+
]
|
|
3048
|
+
},
|
|
3049
|
+
{
|
|
3050
|
+
id: "sad",
|
|
3051
|
+
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
3052
|
+
needs: BROWS,
|
|
3053
|
+
parameters: [
|
|
3054
|
+
...browsY(0.35),
|
|
3055
|
+
...browsTilt(-0.8),
|
|
3056
|
+
{ parameter: P4.MouthForm, value: -0.8, blend: "add" }
|
|
3057
|
+
]
|
|
3058
|
+
},
|
|
3059
|
+
{
|
|
3060
|
+
id: "surprised",
|
|
3061
|
+
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
3062
|
+
parameters: [
|
|
3063
|
+
...browsY(0.8),
|
|
3064
|
+
{ parameter: P4.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
3065
|
+
]
|
|
3066
|
+
},
|
|
3067
|
+
{
|
|
3068
|
+
id: "shy",
|
|
3069
|
+
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
3070
|
+
needs: [P4.Cheek],
|
|
3071
|
+
parameters: [
|
|
3072
|
+
cheek(1),
|
|
3073
|
+
// Gaze down.
|
|
3074
|
+
{ parameter: P4.EyeballY, value: -0.65, blend: "add" },
|
|
3075
|
+
{ parameter: P4.MouthForm, value: 0.4, blend: "add" },
|
|
3076
|
+
...browsTilt(-0.25)
|
|
3077
|
+
]
|
|
3078
|
+
}
|
|
3079
|
+
];
|
|
3080
|
+
function defaultExpressions(declared) {
|
|
3081
|
+
return EXPRESSIONS.filter(
|
|
3082
|
+
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
3083
|
+
).map(({ needs: _needs, ...e }) => ({
|
|
3084
|
+
...e,
|
|
3085
|
+
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
3086
|
+
}));
|
|
3087
|
+
}
|
|
3088
|
+
var DEFAULT_MOTIONS = {
|
|
3089
|
+
Nod: [
|
|
3090
|
+
{
|
|
3091
|
+
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
3092
|
+
duration: 1,
|
|
3093
|
+
curves: [
|
|
3094
|
+
{
|
|
3095
|
+
parameter: P4.AngleY,
|
|
3096
|
+
keys: [
|
|
3097
|
+
[0, 0],
|
|
3098
|
+
[0.3, -18],
|
|
3099
|
+
[0.6, 4],
|
|
3100
|
+
[0.8, -1],
|
|
3101
|
+
[1, 0]
|
|
3102
|
+
]
|
|
3103
|
+
}
|
|
3104
|
+
]
|
|
3105
|
+
}
|
|
3106
|
+
],
|
|
3107
|
+
Shake: [
|
|
3108
|
+
{
|
|
3109
|
+
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
3110
|
+
duration: 1.2,
|
|
3111
|
+
// The first swing peaks at 0.2 s, which the default fade would still
|
|
3112
|
+
// be damping.
|
|
3113
|
+
fadeIn: 0.15,
|
|
3114
|
+
curves: [
|
|
3115
|
+
{
|
|
3116
|
+
parameter: P4.AngleX,
|
|
3117
|
+
keys: [
|
|
3118
|
+
[0, 0],
|
|
3119
|
+
[0.2, -18],
|
|
3120
|
+
[0.45, 18],
|
|
3121
|
+
[0.7, -16],
|
|
3122
|
+
[0.95, 10],
|
|
3123
|
+
[1.2, 0]
|
|
3124
|
+
]
|
|
3125
|
+
}
|
|
3126
|
+
]
|
|
3127
|
+
}
|
|
3128
|
+
],
|
|
3129
|
+
Tilt: [
|
|
3130
|
+
{
|
|
3131
|
+
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
3132
|
+
duration: 1.4,
|
|
3133
|
+
curves: [
|
|
3134
|
+
{
|
|
3135
|
+
parameter: P4.AngleZ,
|
|
3136
|
+
keys: [
|
|
3137
|
+
[0, 0],
|
|
3138
|
+
[0.35, 20],
|
|
3139
|
+
[1, 20],
|
|
3140
|
+
[1.4, 0]
|
|
3141
|
+
]
|
|
3142
|
+
}
|
|
3143
|
+
]
|
|
3144
|
+
}
|
|
3145
|
+
]
|
|
3146
|
+
};
|
|
3147
|
+
|
|
3091
3148
|
// src/auto-rig/checks.ts
|
|
3092
3149
|
var finite = (v) => typeof v === "number" && Number.isFinite(v);
|
|
3093
3150
|
var isObject = (v) => typeof v === "object" && v !== null;
|
|
@@ -5659,13 +5716,14 @@ function declareParameters(roles) {
|
|
|
5659
5716
|
add(P6.BodyAngleZ, "Body Angle Z", -10, 10, 0);
|
|
5660
5717
|
}
|
|
5661
5718
|
const [armMin, armMax] = ARM_RANGE;
|
|
5719
|
+
const [elbowMin, elbowMax] = ELBOW_RANGE;
|
|
5662
5720
|
if (roles.has("arm_L")) {
|
|
5663
5721
|
add(P6.ArmLeft, "Arm L", armMin, armMax, 0);
|
|
5664
|
-
add(P6.ElbowLeft, "Elbow L",
|
|
5722
|
+
add(P6.ElbowLeft, "Elbow L", elbowMin, elbowMax, 0);
|
|
5665
5723
|
}
|
|
5666
5724
|
if (roles.has("arm_R")) {
|
|
5667
5725
|
add(P6.ArmRight, "Arm R", armMin, armMax, 0);
|
|
5668
|
-
add(P6.ElbowRight, "Elbow R",
|
|
5726
|
+
add(P6.ElbowRight, "Elbow R", elbowMin, elbowMax, 0);
|
|
5669
5727
|
}
|
|
5670
5728
|
add(P6.EyeOpenLeft, "Eye L", 0, 1, 1);
|
|
5671
5729
|
add(P6.EyeOpenRight, "Eye R", 0, 1, 1);
|
|
@@ -5726,6 +5784,7 @@ export {
|
|
|
5726
5784
|
SetPhysicsRig,
|
|
5727
5785
|
TurnTargetError,
|
|
5728
5786
|
UV_INSET_PX,
|
|
5787
|
+
armGeometry,
|
|
5729
5788
|
captureBindingEndpoint,
|
|
5730
5789
|
computeGridOffsets,
|
|
5731
5790
|
createDefaultMatrixDeformer,
|