@ikijs/editor 0.14.0 → 0.16.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 CHANGED
@@ -60,7 +60,12 @@ leaves the document untouched.
60
60
  `mouth`, plus optional `iris_*`, `brow_*`, `lash_*`, `lash_lower_*`, `hair_front`, `hair_back`,
61
61
  …) into a rigged model that blinks, gazes, opens its mouth, turns its head over
62
62
  a torso that breathes, and emotes with its brows — including a
63
- hair-sway physics rig when a `hair_front` layer is present.
63
+ hair-sway physics rig when a `hair_front` layer is present. With a `blush_*`
64
+ layer it declares `ParamCheek`, which fades the blush from faint at rest to
65
+ as drawn. Every rigged model also declares the head motions Nod, Shake and
66
+ Tilt and up to six default expressions (smile, laugh, angry, sad, surprised,
67
+ shy; shy needs a blush, angry and sad need brows), each with a description a
68
+ host picks by (`AUTO-RIG.md`).
64
69
 
65
70
  The rig turns the head by parallax, not a reshaped face, with values of our
66
71
  own picked by eye (`auto-rig/profile.ts`, `AUTO-RIG.md`). The face plate
package/dist/index.d.mts CHANGED
@@ -185,7 +185,8 @@ declare class SetDeformerBindings implements EditCommand {
185
185
  /**
186
186
  * Reparent a deformer (matrix or warp) under a new parent, or promote it to
187
187
  * root (`newParentId === undefined`). Calls {@link validateDeformerReparent}
188
- * FIRST so invalid reparents (cycles, warp parent, unknown id) throw before any
188
+ * FIRST so invalid reparents (cycles, warp-under-warp, a pivot outside the new
189
+ * warp parent's grid, unknown id) throw before any
189
190
  * capture or mutation — a throwing apply leaves the model and undo stack
190
191
  * untouched.
191
192
  *
@@ -861,7 +862,9 @@ declare function parseLayerRoles(fileNames: string[]): {
861
862
  * plate, the hair and the blush moved by per-vertex keyforms of their own —
862
863
  * the plate as up to four islands of one drawing: a head that slides, a neck
863
864
  * that stays and two ears that lag. Blink, gaze, brows, mouth, breath and
864
- * hair sway are part warps and bindings under those.
865
+ * hair sway are part warps and bindings under those. The model also declares
866
+ * the default expressions and the Nod, Shake and Tilt motions
867
+ * (`animations.ts`).
865
868
  */
866
869
 
867
870
  declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
@@ -1179,8 +1182,10 @@ declare function uvRectFor(placement: AtlasPlacement, page: {
1179
1182
  /**
1180
1183
  * Validate that reparenting `deformerId` under `newParentId` keeps the deformer
1181
1184
  * hierarchy valid. Pass `newParentId === undefined` to move to root (always legal).
1182
- * Checks: existence, self-reference, undeclared parent, kind constraint (warp
1183
- * deformers cannot be parents), and cycle detection via the proposed edge.
1185
+ * Checks: existence, self-reference, undeclared parent, kind constraint (a warp
1186
+ * deformer cannot be the parent of another warp deformer), a matrix deformer's
1187
+ * pivot inside its new warp parent's rest grid, and cycle detection via the
1188
+ * proposed edge.
1184
1189
  */
1185
1190
  declare function validateDeformerReparent(deformers: IkiDeformer[], deformerId: string, newParentId: string | undefined): void;
1186
1191
  /**
package/dist/index.d.ts CHANGED
@@ -185,7 +185,8 @@ declare class SetDeformerBindings implements EditCommand {
185
185
  /**
186
186
  * Reparent a deformer (matrix or warp) under a new parent, or promote it to
187
187
  * root (`newParentId === undefined`). Calls {@link validateDeformerReparent}
188
- * FIRST so invalid reparents (cycles, warp parent, unknown id) throw before any
188
+ * FIRST so invalid reparents (cycles, warp-under-warp, a pivot outside the new
189
+ * warp parent's grid, unknown id) throw before any
189
190
  * capture or mutation — a throwing apply leaves the model and undo stack
190
191
  * untouched.
191
192
  *
@@ -861,7 +862,9 @@ declare function parseLayerRoles(fileNames: string[]): {
861
862
  * plate, the hair and the blush moved by per-vertex keyforms of their own —
862
863
  * the plate as up to four islands of one drawing: a head that slides, a neck
863
864
  * that stays and two ears that lag. Blink, gaze, brows, mouth, breath and
864
- * hair sway are part warps and bindings under those.
865
+ * hair sway are part warps and bindings under those. The model also declares
866
+ * the default expressions and the Nod, Shake and Tilt motions
867
+ * (`animations.ts`).
865
868
  */
866
869
 
867
870
  declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
@@ -1179,8 +1182,10 @@ declare function uvRectFor(placement: AtlasPlacement, page: {
1179
1182
  /**
1180
1183
  * Validate that reparenting `deformerId` under `newParentId` keeps the deformer
1181
1184
  * hierarchy valid. Pass `newParentId === undefined` to move to root (always legal).
1182
- * Checks: existence, self-reference, undeclared parent, kind constraint (warp
1183
- * deformers cannot be parents), and cycle detection via the proposed edge.
1185
+ * Checks: existence, self-reference, undeclared parent, kind constraint (a warp
1186
+ * deformer cannot be the parent of another warp deformer), a matrix deformer's
1187
+ * pivot inside its new warp parent's rest grid, and cycle detection via the
1188
+ * proposed edge.
1184
1189
  */
1185
1190
  declare function validateDeformerReparent(deformers: IkiDeformer[], deformerId: string, newParentId: string | undefined): void;
1186
1191
  /**
package/dist/index.js CHANGED
@@ -520,11 +520,24 @@ function validateDeformerReparent(deformers2, deformerId, newParentId) {
520
520
  `deformers."${deformerId}".parent "${newParentId}" is not a declared deformer`
521
521
  );
522
522
  }
523
- if (kindOf(parent) === "warp") {
523
+ if (kindOf(parent) === "warp" && kindOf(target) === "warp") {
524
524
  throw new Error(
525
- `deformers."${deformerId}".parent "${newParentId}" must be a matrix deformer (warp deformers cannot be parents)`
525
+ `deformers."${deformerId}".parent "${newParentId}" must be a matrix deformer (warp deformers cannot be nested under a warp deformer)`
526
526
  );
527
527
  }
528
+ if (parent.kind === "warp" && target.kind !== "warp") {
529
+ const { pivot } = target;
530
+ const { cols, rows, points } = parent.grid;
531
+ const xMin = points[0];
532
+ const xMax = points[2 * cols];
533
+ const yMax = points[1];
534
+ const yMin = points[rows * (cols + 1) * 2 + 1];
535
+ if (pivot.x < xMin || pivot.x > xMax || pivot.y < yMin || pivot.y > yMax) {
536
+ throw new Error(
537
+ `deformers."${deformerId}".pivot (${pivot.x}, ${pivot.y}) lies outside its warp parent "${newParentId}" rest grid x ${xMin}..${xMax}, y ${yMin}..${yMax}`
538
+ );
539
+ }
540
+ }
528
541
  const parentOf = /* @__PURE__ */ new Map();
529
542
  for (const d of deformers2) {
530
543
  if (d.parent !== void 0) parentOf.set(d.id, d.parent);
@@ -1983,7 +1996,8 @@ var PROFILE_VALUES = {
1983
1996
  mouthWiden: 1.2,
1984
1997
  brow: 0.15,
1985
1998
  breath: 0.03,
1986
- sway: 0.08
1999
+ sway: 0.08,
2000
+ blushRest: 0.4
1987
2001
  };
1988
2002
  function deriveProfile(v) {
1989
2003
  const farLead = v.lead * (1 - v.fore / 2);
@@ -2070,6 +2084,8 @@ function deriveProfile(v) {
2070
2084
  breathHead: v.breath * 2 / 3,
2071
2085
  /** Hair tip travel at full sway (±20), hh. */
2072
2086
  sway: v.sway,
2087
+ /** The blush's opacity at Cheek 0; at Cheek 1 it is as drawn. */
2088
+ blushRest: v.blushRest,
2073
2089
  /** The neck under the face reaches this far above the jaw, hh — what the
2074
2090
  * chin uncovers as it slides off it: half again the chin's full-turn
2075
2091
  * slide, to the next 0.05. */
@@ -2187,7 +2203,156 @@ function parseLayerRoles(fileNames) {
2187
2203
  }
2188
2204
 
2189
2205
  // src/auto-rig/generate.ts
2190
- var import_format5 = require("@ikijs/format");
2206
+ var import_format6 = require("@ikijs/format");
2207
+
2208
+ // src/auto-rig/animations.ts
2209
+ var import_format3 = require("@ikijs/format");
2210
+ function browsY(y) {
2211
+ return [
2212
+ { parameter: import_format3.StandardParameter.BrowLeftY, value: y, blend: "add" },
2213
+ { parameter: import_format3.StandardParameter.BrowRightY, value: y, blend: "add" }
2214
+ ];
2215
+ }
2216
+ function browsTilt(innerDown) {
2217
+ return [
2218
+ { parameter: import_format3.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
2219
+ { parameter: import_format3.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
2220
+ ];
2221
+ }
2222
+ function cheek(value) {
2223
+ return { parameter: import_format3.StandardParameter.Cheek, value, blend: "add" };
2224
+ }
2225
+ var BROWS = [import_format3.StandardParameter.BrowLeftY, import_format3.StandardParameter.BrowRightY, import_format3.StandardParameter.BrowLeftAngle, import_format3.StandardParameter.BrowRightAngle];
2226
+ var EXPRESSIONS = [
2227
+ {
2228
+ id: "smile",
2229
+ description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
2230
+ parameters: [
2231
+ { parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
2232
+ ...browsY(0.25),
2233
+ cheek(0.4)
2234
+ ]
2235
+ },
2236
+ {
2237
+ id: "laugh",
2238
+ description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
2239
+ parameters: [
2240
+ { parameter: import_format3.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
2241
+ { parameter: import_format3.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
2242
+ { parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
2243
+ { parameter: import_format3.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
2244
+ ...browsY(0.4),
2245
+ cheek(0.65)
2246
+ ]
2247
+ },
2248
+ {
2249
+ id: "angry",
2250
+ description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
2251
+ needs: BROWS,
2252
+ parameters: [
2253
+ ...browsY(-0.5),
2254
+ ...browsTilt(0.8),
2255
+ { parameter: import_format3.StandardParameter.MouthForm, value: -0.9, blend: "add" }
2256
+ ]
2257
+ },
2258
+ {
2259
+ id: "sad",
2260
+ description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
2261
+ needs: BROWS,
2262
+ parameters: [
2263
+ ...browsY(0.35),
2264
+ ...browsTilt(-0.8),
2265
+ { parameter: import_format3.StandardParameter.MouthForm, value: -0.8, blend: "add" }
2266
+ ]
2267
+ },
2268
+ {
2269
+ id: "surprised",
2270
+ description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
2271
+ parameters: [
2272
+ ...browsY(0.8),
2273
+ { parameter: import_format3.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
2274
+ ]
2275
+ },
2276
+ {
2277
+ id: "shy",
2278
+ description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
2279
+ needs: [import_format3.StandardParameter.Cheek],
2280
+ parameters: [
2281
+ cheek(1),
2282
+ // Gaze down.
2283
+ { parameter: import_format3.StandardParameter.EyeballY, value: -0.65, blend: "add" },
2284
+ { parameter: import_format3.StandardParameter.MouthForm, value: 0.4, blend: "add" },
2285
+ ...browsTilt(-0.25)
2286
+ ]
2287
+ }
2288
+ ];
2289
+ function defaultExpressions(declared) {
2290
+ return EXPRESSIONS.filter(
2291
+ (e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
2292
+ ).map(({ needs: _needs, ...e }) => ({
2293
+ ...e,
2294
+ parameters: e.parameters.filter((t) => declared.has(t.parameter))
2295
+ }));
2296
+ }
2297
+ var DEFAULT_MOTIONS = {
2298
+ Nod: [
2299
+ {
2300
+ description: "Nods yes: agreement, acknowledgement, understanding.",
2301
+ duration: 1,
2302
+ curves: [
2303
+ {
2304
+ parameter: import_format3.StandardParameter.AngleY,
2305
+ keys: [
2306
+ [0, 0],
2307
+ [0.3, -18],
2308
+ [0.6, 4],
2309
+ [0.8, -1],
2310
+ [1, 0]
2311
+ ]
2312
+ }
2313
+ ]
2314
+ }
2315
+ ],
2316
+ Shake: [
2317
+ {
2318
+ description: "Shakes the head no: disagreement, refusal, disbelief.",
2319
+ duration: 1.2,
2320
+ // The first swing peaks at 0.2 s, which the default fade would still
2321
+ // be damping.
2322
+ fadeIn: 0.15,
2323
+ curves: [
2324
+ {
2325
+ parameter: import_format3.StandardParameter.AngleX,
2326
+ keys: [
2327
+ [0, 0],
2328
+ [0.2, -18],
2329
+ [0.45, 18],
2330
+ [0.7, -16],
2331
+ [0.95, 10],
2332
+ [1.2, 0]
2333
+ ]
2334
+ }
2335
+ ]
2336
+ }
2337
+ ],
2338
+ Tilt: [
2339
+ {
2340
+ description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
2341
+ duration: 1.4,
2342
+ curves: [
2343
+ {
2344
+ parameter: import_format3.StandardParameter.AngleZ,
2345
+ keys: [
2346
+ [0, 0],
2347
+ [0.35, 20],
2348
+ [1, 20],
2349
+ [1.4, 0]
2350
+ ]
2351
+ }
2352
+ ]
2353
+ }
2354
+ ]
2355
+ };
2191
2356
 
2192
2357
  // src/auto-rig/layout.ts
2193
2358
  function boxOfLayer(layer) {
@@ -2482,7 +2647,7 @@ function checkStrandEdges(strand, irises, hair) {
2482
2647
  }
2483
2648
 
2484
2649
  // src/auto-rig/context.ts
2485
- var import_format3 = require("@ikijs/format");
2650
+ var import_format4 = require("@ikijs/format");
2486
2651
 
2487
2652
  // src/auto-rig/grid.ts
2488
2653
  var X_STOPS = [-30, 0, 30];
@@ -3698,7 +3863,7 @@ function renderedLander(turn, parts, grids, from = /* @__PURE__ */ new Map()) {
3698
3863
  const family = roleSpec(role).family;
3699
3864
  const part = parts.find((p) => p.id === role);
3700
3865
  const g = grids.get(family);
3701
- const warp = part?.warps?.find((w) => w.parameter === import_format3.StandardParameter.AngleX);
3866
+ const warp = part?.warps?.find((w) => w.parameter === import_format4.StandardParameter.AngleX);
3702
3867
  if (part === void 0 || part.mesh === void 0 || !g && !warp) {
3703
3868
  return x + field(role)(x, y, ax, 0)[0];
3704
3869
  }
@@ -4408,7 +4573,7 @@ function buildTurn(frame, landmarks, q) {
4408
4573
  }
4409
4574
 
4410
4575
  // src/auto-rig/drivers.ts
4411
- var import_format4 = require("@ikijs/format");
4576
+ var import_format5 = require("@ikijs/format");
4412
4577
  var SWAY_RANGE = 20;
4413
4578
  var SWAY_CURVE = 1.4;
4414
4579
  var HAIR_HANG = 0.35;
@@ -4486,13 +4651,13 @@ function gazeBindings(irisW, share = 1) {
4486
4651
  const gy = AMPLITUDE.gazeY * irisW * share;
4487
4652
  return [
4488
4653
  {
4489
- parameter: import_format4.StandardParameter.EyeballX,
4654
+ parameter: import_format5.StandardParameter.EyeballX,
4490
4655
  channel: "translateX",
4491
4656
  from: -round1(gx),
4492
4657
  to: round1(gx)
4493
4658
  },
4494
4659
  {
4495
- parameter: import_format4.StandardParameter.EyeballY,
4660
+ parameter: import_format5.StandardParameter.EyeballY,
4496
4661
  channel: "translateY",
4497
4662
  from: -round1(gy),
4498
4663
  to: round1(gy)
@@ -4506,8 +4671,8 @@ function browReach(hh) {
4506
4671
  return AMPLITUDE.brow * hh;
4507
4672
  }
4508
4673
  function browBindings(side, reach) {
4509
- const y = side === "L" ? import_format4.StandardParameter.BrowLeftY : import_format4.StandardParameter.BrowRightY;
4510
- const a = side === "L" ? import_format4.StandardParameter.BrowLeftAngle : import_format4.StandardParameter.BrowRightAngle;
4674
+ const y = side === "L" ? import_format5.StandardParameter.BrowLeftY : import_format5.StandardParameter.BrowRightY;
4675
+ const a = side === "L" ? import_format5.StandardParameter.BrowLeftAngle : import_format5.StandardParameter.BrowRightAngle;
4511
4676
  return [
4512
4677
  {
4513
4678
  parameter: y,
@@ -4523,7 +4688,7 @@ function mouthForm(mesh, box) {
4523
4688
  const a = 0.3 * bh(box);
4524
4689
  const c = cx(box);
4525
4690
  const half = bw(box) / 2;
4526
- return localWarp(import_format4.StandardParameter.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
4691
+ return localWarp(import_format5.StandardParameter.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
4527
4692
  if (v === 0) return [0, 0];
4528
4693
  const u = (x - c) / half;
4529
4694
  const widen = v > 0 ? 0.05 : 0.03;
@@ -4533,7 +4698,7 @@ function mouthForm(mesh, box) {
4533
4698
  function mouthOpenGrow(mesh, box) {
4534
4699
  const c = cx(box);
4535
4700
  return localWarp(
4536
- import_format4.StandardParameter.MouthOpen,
4701
+ import_format5.StandardParameter.MouthOpen,
4537
4702
  mesh,
4538
4703
  box,
4539
4704
  [0, 1],
@@ -4542,7 +4707,7 @@ function mouthOpenGrow(mesh, box) {
4542
4707
  }
4543
4708
  function mouthWiden(mesh, box) {
4544
4709
  const c = cx(box);
4545
- return localWarp(import_format4.StandardParameter.MouthOpen, mesh, box, [0, 1], ([x], v) => [
4710
+ return localWarp(import_format5.StandardParameter.MouthOpen, mesh, box, [0, 1], ([x], v) => [
4546
4711
  v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),
4547
4712
  0
4548
4713
  ]);
@@ -4560,7 +4725,7 @@ function hairSway(param, mesh, box, amp) {
4560
4725
  );
4561
4726
  }
4562
4727
  function tiltHang(mesh, box, pivot, weight) {
4563
- return localWarp(import_format4.StandardParameter.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
4728
+ return localWarp(import_format5.StandardParameter.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
4564
4729
  const g = weight(y, i);
4565
4730
  if (g === 0 || v === 0) return [0, 0];
4566
4731
  const a = -g * rollOf(v);
@@ -4713,16 +4878,19 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
4713
4878
  ...part.warps ?? []
4714
4879
  ];
4715
4880
  }
4881
+ const parameters = declareParameters(new Set(byRole.keys()));
4716
4882
  const model = {
4717
- version: import_format5.IKI_FORMAT_VERSION,
4883
+ version: import_format6.IKI_FORMAT_VERSION,
4718
4884
  name: "auto-rigged",
4719
4885
  canvas: { width: canvas.width, height: canvas.height },
4720
- parameters: declareParameters(new Set(byRole.keys())),
4886
+ parameters,
4721
4887
  parts,
4722
4888
  deformers: deformers(frame, grids, has("body") ? box("body") : void 0),
4723
- ...has("hair_front") ? { physics: hairPhysics() } : {}
4889
+ ...has("hair_front") ? { physics: hairPhysics() } : {},
4890
+ expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),
4891
+ motions: DEFAULT_MOTIONS
4724
4892
  };
4725
- const valid = (0, import_format5.parseIkiModel)(model);
4893
+ const valid = (0, import_format6.parseIkiModel)(model);
4726
4894
  if (hasNose && options.onTurnSolved) {
4727
4895
  options.onTurnSolved(
4728
4896
  turnReport(
@@ -4737,14 +4905,14 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
4737
4905
  function turnWarps(mesh, b, fieldOf) {
4738
4906
  return [
4739
4907
  localWarp(
4740
- import_format5.StandardParameter.AngleX,
4908
+ import_format6.StandardParameter.AngleX,
4741
4909
  mesh,
4742
4910
  b,
4743
4911
  X_STOPS,
4744
4912
  ([x, y], v, i) => v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0]
4745
4913
  ),
4746
4914
  localWarp(
4747
- import_format5.StandardParameter.AngleY,
4915
+ import_format6.StandardParameter.AngleY,
4748
4916
  mesh,
4749
4917
  b,
4750
4918
  Y_STOPS,
@@ -4792,7 +4960,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
4792
4960
  }
4793
4961
  if (mesh !== void 0) part.mesh = mesh;
4794
4962
  const side = spec.role.endsWith("_L") ? "L" : "R";
4795
- const eyeOpen = side === "L" ? import_format5.StandardParameter.EyeOpenLeft : import_format5.StandardParameter.EyeOpenRight;
4963
+ const eyeOpen = side === "L" ? import_format6.StandardParameter.EyeOpenLeft : import_format6.StandardParameter.EyeOpenRight;
4796
4964
  const hh = frame.hh;
4797
4965
  switch (spec.role) {
4798
4966
  case "face":
@@ -4801,7 +4969,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
4801
4969
  warps.push(
4802
4970
  tiltHang(mesh, b, pivot, (_y, i) => isNeck[i] ? 1 : 0),
4803
4971
  localWarp(
4804
- import_format5.StandardParameter.Breath,
4972
+ import_format6.StandardParameter.Breath,
4805
4973
  mesh,
4806
4974
  b,
4807
4975
  [0, 1],
@@ -4848,8 +5016,8 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
4848
5016
  if (byRole.has("mouth_open")) {
4849
5017
  warps.push(mouthWiden(mesh, b));
4850
5018
  bindings.push(
4851
- { parameter: import_format5.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 },
4852
- { parameter: import_format5.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 }
5019
+ { parameter: import_format6.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 },
5020
+ { parameter: import_format6.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 }
4853
5021
  );
4854
5022
  extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
4855
5023
  } else {
@@ -4859,19 +5027,19 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
4859
5027
  );
4860
5028
  bindings.push(
4861
5029
  {
4862
- parameter: import_format5.StandardParameter.MouthOpen,
5030
+ parameter: import_format6.StandardParameter.MouthOpen,
4863
5031
  channel: "scaleY",
4864
5032
  from: 0,
4865
5033
  to: roundTo(grow, 0.01)
4866
5034
  },
4867
5035
  {
4868
- parameter: import_format5.StandardParameter.MouthOpen,
5036
+ parameter: import_format6.StandardParameter.MouthOpen,
4869
5037
  channel: "scaleX",
4870
5038
  from: 0,
4871
5039
  to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01)
4872
5040
  },
4873
5041
  {
4874
- parameter: import_format5.StandardParameter.MouthOpen,
5042
+ parameter: import_format6.StandardParameter.MouthOpen,
4875
5043
  channel: "translateY",
4876
5044
  from: 0,
4877
5045
  to: -roundTo(grow * bh(b) / 2, 0.01)
@@ -4883,20 +5051,29 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
4883
5051
  case "mouth_open":
4884
5052
  warps.push(mouthForm(mesh, b), mouthOpenGrow(mesh, b));
4885
5053
  bindings.push({
4886
- parameter: import_format5.StandardParameter.MouthOpen,
5054
+ parameter: import_format6.StandardParameter.MouthOpen,
4887
5055
  channel: "opacity",
4888
5056
  from: 0,
4889
5057
  to: 1
4890
5058
  });
4891
5059
  extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
4892
5060
  break;
5061
+ case "blush_L":
5062
+ case "blush_R":
5063
+ bindings.push({
5064
+ parameter: import_format6.StandardParameter.Cheek,
5065
+ channel: "opacity",
5066
+ from: AMPLITUDE.blushRest,
5067
+ to: 1
5068
+ });
5069
+ break;
4893
5070
  case "hair_front":
4894
5071
  case "hair_back":
4895
5072
  if (byRole.has("hair_front")) {
4896
5073
  const amp = style.sway * AMPLITUDE.sway * hh;
4897
5074
  warps.push(
4898
- hairSway(import_format5.StandardParameter.HairSwayX, mesh, b, amp),
4899
- hairSway(import_format5.StandardParameter.HairSwayZ, mesh, b, amp)
5075
+ hairSway(import_format6.StandardParameter.HairSwayX, mesh, b, amp),
5076
+ hairSway(import_format6.StandardParameter.HairSwayZ, mesh, b, amp)
4900
5077
  );
4901
5078
  }
4902
5079
  warps.push(tiltHang(mesh, b, pivot, hairHangWeight(frame.chinY, b.y0)));
@@ -4977,7 +5154,7 @@ function deformers(frame, grids, body) {
4977
5154
  pivot: { x: roundTo(cx(body), 0.01), y: roundTo(body.y1, 0.01) },
4978
5155
  bindings: [
4979
5156
  {
4980
- parameter: import_format5.StandardParameter.Breath,
5157
+ parameter: import_format6.StandardParameter.Breath,
4981
5158
  channel: "translateY",
4982
5159
  from: 0,
4983
5160
  to: roundTo(AMPLITUDE.breathBody * frame.hh, 0.01)
@@ -4990,9 +5167,9 @@ function deformers(frame, grids, body) {
4990
5167
  pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },
4991
5168
  bindings: [
4992
5169
  // AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.
4993
- { parameter: import_format5.StandardParameter.AngleZ, channel: "rotate", from: ROLL_DEG, to: -ROLL_DEG },
5170
+ { parameter: import_format6.StandardParameter.AngleZ, channel: "rotate", from: ROLL_DEG, to: -ROLL_DEG },
4994
5171
  {
4995
- parameter: import_format5.StandardParameter.Breath,
5172
+ parameter: import_format6.StandardParameter.Breath,
4996
5173
  channel: "translateY",
4997
5174
  from: 0,
4998
5175
  to: roundTo(AMPLITUDE.breathHead * frame.hh, 0.01)
@@ -5010,8 +5187,8 @@ function deformers(frame, grids, body) {
5010
5187
  points: g.lattice.points
5011
5188
  },
5012
5189
  warp2d: {
5013
- parameter: import_format5.StandardParameter.AngleX,
5014
- parameterY: import_format5.StandardParameter.AngleY,
5190
+ parameter: import_format6.StandardParameter.AngleX,
5191
+ parameterY: import_format6.StandardParameter.AngleY,
5015
5192
  valuesX: X_STOPS,
5016
5193
  valuesY: Y_STOPS,
5017
5194
  keyforms2d: g.keyforms.map((offsets) => ({ offsets }))
@@ -5024,16 +5201,16 @@ function hairPhysics() {
5024
5201
  return [
5025
5202
  {
5026
5203
  id: "hairSway",
5027
- input: { parameter: import_format5.StandardParameter.AngleX, weight: 1 },
5028
- output: { parameter: import_format5.StandardParameter.HairSwayX, scale: 5 },
5204
+ input: { parameter: import_format6.StandardParameter.AngleX, weight: 1 },
5205
+ output: { parameter: import_format6.StandardParameter.HairSwayX, scale: 5 },
5029
5206
  mass: 1,
5030
5207
  stiffness: 30,
5031
5208
  damping: 3
5032
5209
  },
5033
5210
  {
5034
5211
  id: "hairTilt",
5035
- input: { parameter: import_format5.StandardParameter.AngleZ, weight: 1 },
5036
- output: { parameter: import_format5.StandardParameter.HairSwayZ, scale: 8 },
5212
+ input: { parameter: import_format6.StandardParameter.AngleZ, weight: 1 },
5213
+ output: { parameter: import_format6.StandardParameter.HairSwayZ, scale: 8 },
5037
5214
  mass: 1,
5038
5215
  stiffness: 25,
5039
5216
  damping: 2.5
@@ -5043,29 +5220,32 @@ function hairPhysics() {
5043
5220
  function declareParameters(roles) {
5044
5221
  const out = [];
5045
5222
  const add = (id, name, min, max, def) => out.push({ id, name, min, max, default: def });
5046
- add(import_format5.StandardParameter.AngleX, "Head Angle", -30, 30, 0);
5047
- add(import_format5.StandardParameter.AngleY, "Head Angle Y", -30, 30, 0);
5048
- add(import_format5.StandardParameter.AngleZ, "Head Angle Z", -30, 30, 0);
5049
- add(import_format5.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
5050
- add(import_format5.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
5223
+ add(import_format6.StandardParameter.AngleX, "Head Angle", -30, 30, 0);
5224
+ add(import_format6.StandardParameter.AngleY, "Head Angle Y", -30, 30, 0);
5225
+ add(import_format6.StandardParameter.AngleZ, "Head Angle Z", -30, 30, 0);
5226
+ add(import_format6.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
5227
+ add(import_format6.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
5051
5228
  if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {
5052
- add(import_format5.StandardParameter.EyeballX, "Gaze X", -1, 1, 0);
5053
- add(import_format5.StandardParameter.EyeballY, "Gaze Y", -1, 1, 0);
5229
+ add(import_format6.StandardParameter.EyeballX, "Gaze X", -1, 1, 0);
5230
+ add(import_format6.StandardParameter.EyeballY, "Gaze Y", -1, 1, 0);
5054
5231
  }
5055
- add(import_format5.StandardParameter.MouthOpen, "Mouth Open", 0, 1, 0);
5056
- add(import_format5.StandardParameter.MouthForm, "Mouth Form", -1, 1, 0);
5232
+ add(import_format6.StandardParameter.MouthOpen, "Mouth Open", 0, 1, 0);
5233
+ add(import_format6.StandardParameter.MouthForm, "Mouth Form", -1, 1, 0);
5057
5234
  if (roles.has("brow_L")) {
5058
- add(import_format5.StandardParameter.BrowLeftY, "Brow L Y", -1, 1, 0);
5059
- add(import_format5.StandardParameter.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
5235
+ add(import_format6.StandardParameter.BrowLeftY, "Brow L Y", -1, 1, 0);
5236
+ add(import_format6.StandardParameter.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
5060
5237
  }
5061
5238
  if (roles.has("brow_R")) {
5062
- add(import_format5.StandardParameter.BrowRightY, "Brow R Y", -1, 1, 0);
5063
- add(import_format5.StandardParameter.BrowRightAngle, "Brow R Angle", -1, 1, 0);
5239
+ add(import_format6.StandardParameter.BrowRightY, "Brow R Y", -1, 1, 0);
5240
+ add(import_format6.StandardParameter.BrowRightAngle, "Brow R Angle", -1, 1, 0);
5241
+ }
5242
+ if (roles.has("blush_L") || roles.has("blush_R")) {
5243
+ add(import_format6.StandardParameter.Cheek, "Cheek", 0, 1, 0);
5064
5244
  }
5065
- add(import_format5.StandardParameter.Breath, "Breath", 0, 1, 0);
5245
+ add(import_format6.StandardParameter.Breath, "Breath", 0, 1, 0);
5066
5246
  if (roles.has("hair_front")) {
5067
- add(import_format5.StandardParameter.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
5068
- add(import_format5.StandardParameter.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
5247
+ add(import_format6.StandardParameter.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
5248
+ add(import_format6.StandardParameter.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
5069
5249
  }
5070
5250
  return out;
5071
5251
  }