@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/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 P4
2110
+ StandardParameter as P3
2364
2111
  } from "@ikijs/format";
2365
2112
 
2366
2113
  // src/auto-rig/body.ts
2367
2114
  import {
2368
- StandardParameter as P3
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 P2
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: P2.EyeballX,
2272
+ parameter: P.EyeballX,
2526
2273
  channel: "translateX",
2527
2274
  from: -round1(gx),
2528
2275
  to: round1(gx)
2529
2276
  },
2530
2277
  {
2531
- parameter: P2.EyeballY,
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" ? P2.BrowLeftY : P2.BrowRightY;
2546
- const a = side === "L" ? P2.BrowLeftAngle : P2.BrowRightAngle;
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(P2.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
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
- P2.MouthOpen,
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(P2.MouthOpen, mesh, box, [0, 1], ([x], v) => [
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(P2.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
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(P3.BodyAngleX, BODY_STOPS, (x, _y, t) => [turn(x, t), 0]),
2849
- warp(P3.BodyAngleY, BODY_STOPS, (_x, _y, t) => [0, t * BODY.bow * hh]),
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
- P3.BodyAngleZ,
2598
+ P2.BodyAngleZ,
2852
2599
  BODY_STOPS,
2853
2600
  (x, y, t) => roll(x, y, -t * BODY.rollDeg)
2854
2601
  ),
2855
- warp(P3.AngleX, X_STOPS, (x, _y, t) => [BODY.followX * turn(x, t), 0]),
2856
- warp(P3.AngleZ, Z_STOPS, (x, y, t) => roll(x, y, -t * BODY.followRoll)),
2857
- warp(P3.Breath, [0, 1], (_x, _y, t) => [0, t * AMPLITUDE.breathBody * hh])
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: P4.ArmLeft, elbow: P4.ElbowLeft },
2943
- arm_R: { arm: P4.ArmRight, elbow: P4.ElbowRight }
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,