@ikijs/editor 0.13.0 → 0.15.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 +7 -2
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +229 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +229 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -57,10 +57,15 @@ leaves the document untouched.
|
|
|
57
57
|
## Auto-rig
|
|
58
58
|
|
|
59
59
|
`generateIkiFromLayerSet` turns role-named layers (`face`, `eye_L`, `eye_R`,
|
|
60
|
-
`mouth`, plus optional `iris_*`, `brow_*`, `lash_*`, `hair_front`, `hair_back`,
|
|
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
|
@@ -861,7 +861,9 @@ declare function parseLayerRoles(fileNames: string[]): {
|
|
|
861
861
|
* plate, the hair and the blush moved by per-vertex keyforms of their own —
|
|
862
862
|
* the plate as up to four islands of one drawing: a head that slides, a neck
|
|
863
863
|
* that stays and two ears that lag. Blink, gaze, brows, mouth, breath and
|
|
864
|
-
* hair sway are part warps and bindings under those.
|
|
864
|
+
* hair sway are part warps and bindings under those. The model also declares
|
|
865
|
+
* the default expressions and the Nod, Shake and Tilt motions
|
|
866
|
+
* (`animations.ts`).
|
|
865
867
|
*/
|
|
866
868
|
|
|
867
869
|
declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
|
package/dist/index.d.ts
CHANGED
|
@@ -861,7 +861,9 @@ declare function parseLayerRoles(fileNames: string[]): {
|
|
|
861
861
|
* plate, the hair and the blush moved by per-vertex keyforms of their own —
|
|
862
862
|
* the plate as up to four islands of one drawing: a head that slides, a neck
|
|
863
863
|
* that stays and two ears that lag. Blink, gaze, brows, mouth, breath and
|
|
864
|
-
* hair sway are part warps and bindings under those.
|
|
864
|
+
* hair sway are part warps and bindings under those. The model also declares
|
|
865
|
+
* the default expressions and the Nod, Shake and Tilt motions
|
|
866
|
+
* (`animations.ts`).
|
|
865
867
|
*/
|
|
866
868
|
|
|
867
869
|
declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
|
package/dist/index.js
CHANGED
|
@@ -1983,7 +1983,8 @@ var PROFILE_VALUES = {
|
|
|
1983
1983
|
mouthWiden: 1.2,
|
|
1984
1984
|
brow: 0.15,
|
|
1985
1985
|
breath: 0.03,
|
|
1986
|
-
sway: 0.08
|
|
1986
|
+
sway: 0.08,
|
|
1987
|
+
blushRest: 0.4
|
|
1987
1988
|
};
|
|
1988
1989
|
function deriveProfile(v) {
|
|
1989
1990
|
const farLead = v.lead * (1 - v.fore / 2);
|
|
@@ -2070,6 +2071,8 @@ function deriveProfile(v) {
|
|
|
2070
2071
|
breathHead: v.breath * 2 / 3,
|
|
2071
2072
|
/** Hair tip travel at full sway (±20), hh. */
|
|
2072
2073
|
sway: v.sway,
|
|
2074
|
+
/** The blush's opacity at Cheek 0; at Cheek 1 it is as drawn. */
|
|
2075
|
+
blushRest: v.blushRest,
|
|
2073
2076
|
/** The neck under the face reaches this far above the jaw, hh — what the
|
|
2074
2077
|
* chin uncovers as it slides off it: half again the chin's full-turn
|
|
2075
2078
|
* slide, to the next 0.05. */
|
|
@@ -2131,6 +2134,8 @@ var ROLE_TABLE = [
|
|
|
2131
2134
|
{ role: "pupil_R", family: "eye_R" },
|
|
2132
2135
|
{ role: "highlight_L", family: "eye_L" },
|
|
2133
2136
|
{ role: "highlight_R", family: "eye_R" },
|
|
2137
|
+
{ role: "lash_lower_L", family: "eye_L" },
|
|
2138
|
+
{ role: "lash_lower_R", family: "eye_R" },
|
|
2134
2139
|
{ role: "lash_L", family: "eye_L" },
|
|
2135
2140
|
{ role: "lash_R", family: "eye_R" },
|
|
2136
2141
|
{ role: "brow_L", family: "brow_L" },
|
|
@@ -2185,7 +2190,156 @@ function parseLayerRoles(fileNames) {
|
|
|
2185
2190
|
}
|
|
2186
2191
|
|
|
2187
2192
|
// src/auto-rig/generate.ts
|
|
2188
|
-
var
|
|
2193
|
+
var import_format6 = require("@ikijs/format");
|
|
2194
|
+
|
|
2195
|
+
// src/auto-rig/animations.ts
|
|
2196
|
+
var import_format3 = require("@ikijs/format");
|
|
2197
|
+
function browsY(y) {
|
|
2198
|
+
return [
|
|
2199
|
+
{ parameter: import_format3.StandardParameter.BrowLeftY, value: y, blend: "add" },
|
|
2200
|
+
{ parameter: import_format3.StandardParameter.BrowRightY, value: y, blend: "add" }
|
|
2201
|
+
];
|
|
2202
|
+
}
|
|
2203
|
+
function browsTilt(innerDown) {
|
|
2204
|
+
return [
|
|
2205
|
+
{ parameter: import_format3.StandardParameter.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
2206
|
+
{ parameter: import_format3.StandardParameter.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
2207
|
+
];
|
|
2208
|
+
}
|
|
2209
|
+
function cheek(value) {
|
|
2210
|
+
return { parameter: import_format3.StandardParameter.Cheek, value, blend: "add" };
|
|
2211
|
+
}
|
|
2212
|
+
var BROWS = [import_format3.StandardParameter.BrowLeftY, import_format3.StandardParameter.BrowRightY, import_format3.StandardParameter.BrowLeftAngle, import_format3.StandardParameter.BrowRightAngle];
|
|
2213
|
+
var EXPRESSIONS = [
|
|
2214
|
+
{
|
|
2215
|
+
id: "smile",
|
|
2216
|
+
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
2217
|
+
parameters: [
|
|
2218
|
+
{ parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
2219
|
+
...browsY(0.25),
|
|
2220
|
+
cheek(0.4)
|
|
2221
|
+
]
|
|
2222
|
+
},
|
|
2223
|
+
{
|
|
2224
|
+
id: "laugh",
|
|
2225
|
+
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
2226
|
+
parameters: [
|
|
2227
|
+
{ parameter: import_format3.StandardParameter.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
2228
|
+
{ parameter: import_format3.StandardParameter.EyeOpenRight, value: 0, blend: "multiply" },
|
|
2229
|
+
{ parameter: import_format3.StandardParameter.MouthForm, value: 1, blend: "add" },
|
|
2230
|
+
{ parameter: import_format3.StandardParameter.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
2231
|
+
...browsY(0.4),
|
|
2232
|
+
cheek(0.65)
|
|
2233
|
+
]
|
|
2234
|
+
},
|
|
2235
|
+
{
|
|
2236
|
+
id: "angry",
|
|
2237
|
+
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
2238
|
+
needs: BROWS,
|
|
2239
|
+
parameters: [
|
|
2240
|
+
...browsY(-0.5),
|
|
2241
|
+
...browsTilt(0.8),
|
|
2242
|
+
{ parameter: import_format3.StandardParameter.MouthForm, value: -0.9, blend: "add" }
|
|
2243
|
+
]
|
|
2244
|
+
},
|
|
2245
|
+
{
|
|
2246
|
+
id: "sad",
|
|
2247
|
+
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
2248
|
+
needs: BROWS,
|
|
2249
|
+
parameters: [
|
|
2250
|
+
...browsY(0.35),
|
|
2251
|
+
...browsTilt(-0.8),
|
|
2252
|
+
{ parameter: import_format3.StandardParameter.MouthForm, value: -0.8, blend: "add" }
|
|
2253
|
+
]
|
|
2254
|
+
},
|
|
2255
|
+
{
|
|
2256
|
+
id: "surprised",
|
|
2257
|
+
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
2258
|
+
parameters: [
|
|
2259
|
+
...browsY(0.8),
|
|
2260
|
+
{ parameter: import_format3.StandardParameter.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
2261
|
+
]
|
|
2262
|
+
},
|
|
2263
|
+
{
|
|
2264
|
+
id: "shy",
|
|
2265
|
+
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
2266
|
+
needs: [import_format3.StandardParameter.Cheek],
|
|
2267
|
+
parameters: [
|
|
2268
|
+
cheek(1),
|
|
2269
|
+
// Gaze down.
|
|
2270
|
+
{ parameter: import_format3.StandardParameter.EyeballY, value: -0.65, blend: "add" },
|
|
2271
|
+
{ parameter: import_format3.StandardParameter.MouthForm, value: 0.4, blend: "add" },
|
|
2272
|
+
...browsTilt(-0.25)
|
|
2273
|
+
]
|
|
2274
|
+
}
|
|
2275
|
+
];
|
|
2276
|
+
function defaultExpressions(declared) {
|
|
2277
|
+
return EXPRESSIONS.filter(
|
|
2278
|
+
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
2279
|
+
).map(({ needs: _needs, ...e }) => ({
|
|
2280
|
+
...e,
|
|
2281
|
+
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
2282
|
+
}));
|
|
2283
|
+
}
|
|
2284
|
+
var DEFAULT_MOTIONS = {
|
|
2285
|
+
Nod: [
|
|
2286
|
+
{
|
|
2287
|
+
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
2288
|
+
duration: 1,
|
|
2289
|
+
curves: [
|
|
2290
|
+
{
|
|
2291
|
+
parameter: import_format3.StandardParameter.AngleY,
|
|
2292
|
+
keys: [
|
|
2293
|
+
[0, 0],
|
|
2294
|
+
[0.3, -18],
|
|
2295
|
+
[0.6, 4],
|
|
2296
|
+
[0.8, -1],
|
|
2297
|
+
[1, 0]
|
|
2298
|
+
]
|
|
2299
|
+
}
|
|
2300
|
+
]
|
|
2301
|
+
}
|
|
2302
|
+
],
|
|
2303
|
+
Shake: [
|
|
2304
|
+
{
|
|
2305
|
+
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
2306
|
+
duration: 1.2,
|
|
2307
|
+
// The first swing peaks at 0.2 s, which the default fade would still
|
|
2308
|
+
// be damping.
|
|
2309
|
+
fadeIn: 0.15,
|
|
2310
|
+
curves: [
|
|
2311
|
+
{
|
|
2312
|
+
parameter: import_format3.StandardParameter.AngleX,
|
|
2313
|
+
keys: [
|
|
2314
|
+
[0, 0],
|
|
2315
|
+
[0.2, -18],
|
|
2316
|
+
[0.45, 18],
|
|
2317
|
+
[0.7, -16],
|
|
2318
|
+
[0.95, 10],
|
|
2319
|
+
[1.2, 0]
|
|
2320
|
+
]
|
|
2321
|
+
}
|
|
2322
|
+
]
|
|
2323
|
+
}
|
|
2324
|
+
],
|
|
2325
|
+
Tilt: [
|
|
2326
|
+
{
|
|
2327
|
+
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
2328
|
+
duration: 1.4,
|
|
2329
|
+
curves: [
|
|
2330
|
+
{
|
|
2331
|
+
parameter: import_format3.StandardParameter.AngleZ,
|
|
2332
|
+
keys: [
|
|
2333
|
+
[0, 0],
|
|
2334
|
+
[0.35, 20],
|
|
2335
|
+
[1, 20],
|
|
2336
|
+
[1.4, 0]
|
|
2337
|
+
]
|
|
2338
|
+
}
|
|
2339
|
+
]
|
|
2340
|
+
}
|
|
2341
|
+
]
|
|
2342
|
+
};
|
|
2189
2343
|
|
|
2190
2344
|
// src/auto-rig/layout.ts
|
|
2191
2345
|
function boxOfLayer(layer) {
|
|
@@ -2480,7 +2634,7 @@ function checkStrandEdges(strand, irises, hair) {
|
|
|
2480
2634
|
}
|
|
2481
2635
|
|
|
2482
2636
|
// src/auto-rig/context.ts
|
|
2483
|
-
var
|
|
2637
|
+
var import_format4 = require("@ikijs/format");
|
|
2484
2638
|
|
|
2485
2639
|
// src/auto-rig/grid.ts
|
|
2486
2640
|
var X_STOPS = [-30, 0, 30];
|
|
@@ -3696,7 +3850,7 @@ function renderedLander(turn, parts, grids, from = /* @__PURE__ */ new Map()) {
|
|
|
3696
3850
|
const family = roleSpec(role).family;
|
|
3697
3851
|
const part = parts.find((p) => p.id === role);
|
|
3698
3852
|
const g = grids.get(family);
|
|
3699
|
-
const warp = part?.warps?.find((w) => w.parameter ===
|
|
3853
|
+
const warp = part?.warps?.find((w) => w.parameter === import_format4.StandardParameter.AngleX);
|
|
3700
3854
|
if (part === void 0 || part.mesh === void 0 || !g && !warp) {
|
|
3701
3855
|
return x + field(role)(x, y, ax, 0)[0];
|
|
3702
3856
|
}
|
|
@@ -4406,7 +4560,7 @@ function buildTurn(frame, landmarks, q) {
|
|
|
4406
4560
|
}
|
|
4407
4561
|
|
|
4408
4562
|
// src/auto-rig/drivers.ts
|
|
4409
|
-
var
|
|
4563
|
+
var import_format5 = require("@ikijs/format");
|
|
4410
4564
|
var SWAY_RANGE = 20;
|
|
4411
4565
|
var SWAY_CURVE = 1.4;
|
|
4412
4566
|
var HAIR_HANG = 0.35;
|
|
@@ -4458,12 +4612,12 @@ function motionReach(warps, mesh, box, extra = [0, 0]) {
|
|
|
4458
4612
|
}
|
|
4459
4613
|
return out;
|
|
4460
4614
|
}
|
|
4461
|
-
function blinkFold(param, mesh,
|
|
4615
|
+
function blinkFold(param, mesh, box, travel, eye = box) {
|
|
4462
4616
|
const yc = eye.y1 - travel * bh(eye);
|
|
4463
4617
|
return localWarp(
|
|
4464
4618
|
param,
|
|
4465
4619
|
mesh,
|
|
4466
|
-
|
|
4620
|
+
box,
|
|
4467
4621
|
[0, 1],
|
|
4468
4622
|
([, y], v) => v === 1 ? [0, 0] : [0, yc - y]
|
|
4469
4623
|
);
|
|
@@ -4484,13 +4638,13 @@ function gazeBindings(irisW, share = 1) {
|
|
|
4484
4638
|
const gy = AMPLITUDE.gazeY * irisW * share;
|
|
4485
4639
|
return [
|
|
4486
4640
|
{
|
|
4487
|
-
parameter:
|
|
4641
|
+
parameter: import_format5.StandardParameter.EyeballX,
|
|
4488
4642
|
channel: "translateX",
|
|
4489
4643
|
from: -round1(gx),
|
|
4490
4644
|
to: round1(gx)
|
|
4491
4645
|
},
|
|
4492
4646
|
{
|
|
4493
|
-
parameter:
|
|
4647
|
+
parameter: import_format5.StandardParameter.EyeballY,
|
|
4494
4648
|
channel: "translateY",
|
|
4495
4649
|
from: -round1(gy),
|
|
4496
4650
|
to: round1(gy)
|
|
@@ -4504,8 +4658,8 @@ function browReach(hh) {
|
|
|
4504
4658
|
return AMPLITUDE.brow * hh;
|
|
4505
4659
|
}
|
|
4506
4660
|
function browBindings(side, reach) {
|
|
4507
|
-
const y = side === "L" ?
|
|
4508
|
-
const a = side === "L" ?
|
|
4661
|
+
const y = side === "L" ? import_format5.StandardParameter.BrowLeftY : import_format5.StandardParameter.BrowRightY;
|
|
4662
|
+
const a = side === "L" ? import_format5.StandardParameter.BrowLeftAngle : import_format5.StandardParameter.BrowRightAngle;
|
|
4509
4663
|
return [
|
|
4510
4664
|
{
|
|
4511
4665
|
parameter: y,
|
|
@@ -4521,7 +4675,7 @@ function mouthForm(mesh, box) {
|
|
|
4521
4675
|
const a = 0.3 * bh(box);
|
|
4522
4676
|
const c = cx(box);
|
|
4523
4677
|
const half = bw(box) / 2;
|
|
4524
|
-
return localWarp(
|
|
4678
|
+
return localWarp(import_format5.StandardParameter.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
|
|
4525
4679
|
if (v === 0) return [0, 0];
|
|
4526
4680
|
const u = (x - c) / half;
|
|
4527
4681
|
const widen = v > 0 ? 0.05 : 0.03;
|
|
@@ -4531,7 +4685,7 @@ function mouthForm(mesh, box) {
|
|
|
4531
4685
|
function mouthOpenGrow(mesh, box) {
|
|
4532
4686
|
const c = cx(box);
|
|
4533
4687
|
return localWarp(
|
|
4534
|
-
|
|
4688
|
+
import_format5.StandardParameter.MouthOpen,
|
|
4535
4689
|
mesh,
|
|
4536
4690
|
box,
|
|
4537
4691
|
[0, 1],
|
|
@@ -4540,7 +4694,7 @@ function mouthOpenGrow(mesh, box) {
|
|
|
4540
4694
|
}
|
|
4541
4695
|
function mouthWiden(mesh, box) {
|
|
4542
4696
|
const c = cx(box);
|
|
4543
|
-
return localWarp(
|
|
4697
|
+
return localWarp(import_format5.StandardParameter.MouthOpen, mesh, box, [0, 1], ([x], v) => [
|
|
4544
4698
|
v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),
|
|
4545
4699
|
0
|
|
4546
4700
|
]);
|
|
@@ -4558,7 +4712,7 @@ function hairSway(param, mesh, box, amp) {
|
|
|
4558
4712
|
);
|
|
4559
4713
|
}
|
|
4560
4714
|
function tiltHang(mesh, box, pivot, weight) {
|
|
4561
|
-
return localWarp(
|
|
4715
|
+
return localWarp(import_format5.StandardParameter.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
|
|
4562
4716
|
const g = weight(y, i);
|
|
4563
4717
|
if (g === 0 || v === 0) return [0, 0];
|
|
4564
4718
|
const a = -g * rollOf(v);
|
|
@@ -4711,16 +4865,19 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
|
|
|
4711
4865
|
...part.warps ?? []
|
|
4712
4866
|
];
|
|
4713
4867
|
}
|
|
4868
|
+
const parameters = declareParameters(new Set(byRole.keys()));
|
|
4714
4869
|
const model = {
|
|
4715
|
-
version:
|
|
4870
|
+
version: import_format6.IKI_FORMAT_VERSION,
|
|
4716
4871
|
name: "auto-rigged",
|
|
4717
4872
|
canvas: { width: canvas.width, height: canvas.height },
|
|
4718
|
-
parameters
|
|
4873
|
+
parameters,
|
|
4719
4874
|
parts,
|
|
4720
4875
|
deformers: deformers(frame, grids, has("body") ? box("body") : void 0),
|
|
4721
|
-
...has("hair_front") ? { physics: hairPhysics() } : {}
|
|
4876
|
+
...has("hair_front") ? { physics: hairPhysics() } : {},
|
|
4877
|
+
expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),
|
|
4878
|
+
motions: DEFAULT_MOTIONS
|
|
4722
4879
|
};
|
|
4723
|
-
const valid = (0,
|
|
4880
|
+
const valid = (0, import_format6.parseIkiModel)(model);
|
|
4724
4881
|
if (hasNose && options.onTurnSolved) {
|
|
4725
4882
|
options.onTurnSolved(
|
|
4726
4883
|
turnReport(
|
|
@@ -4735,14 +4892,14 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
|
|
|
4735
4892
|
function turnWarps(mesh, b, fieldOf) {
|
|
4736
4893
|
return [
|
|
4737
4894
|
localWarp(
|
|
4738
|
-
|
|
4895
|
+
import_format6.StandardParameter.AngleX,
|
|
4739
4896
|
mesh,
|
|
4740
4897
|
b,
|
|
4741
4898
|
X_STOPS,
|
|
4742
4899
|
([x, y], v, i) => v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0]
|
|
4743
4900
|
),
|
|
4744
4901
|
localWarp(
|
|
4745
|
-
|
|
4902
|
+
import_format6.StandardParameter.AngleY,
|
|
4746
4903
|
mesh,
|
|
4747
4904
|
b,
|
|
4748
4905
|
Y_STOPS,
|
|
@@ -4790,7 +4947,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4790
4947
|
}
|
|
4791
4948
|
if (mesh !== void 0) part.mesh = mesh;
|
|
4792
4949
|
const side = spec.role.endsWith("_L") ? "L" : "R";
|
|
4793
|
-
const eyeOpen = side === "L" ?
|
|
4950
|
+
const eyeOpen = side === "L" ? import_format6.StandardParameter.EyeOpenLeft : import_format6.StandardParameter.EyeOpenRight;
|
|
4794
4951
|
const hh = frame.hh;
|
|
4795
4952
|
switch (spec.role) {
|
|
4796
4953
|
case "face":
|
|
@@ -4799,7 +4956,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4799
4956
|
warps.push(
|
|
4800
4957
|
tiltHang(mesh, b, pivot, (_y, i) => isNeck[i] ? 1 : 0),
|
|
4801
4958
|
localWarp(
|
|
4802
|
-
|
|
4959
|
+
import_format6.StandardParameter.Breath,
|
|
4803
4960
|
mesh,
|
|
4804
4961
|
b,
|
|
4805
4962
|
[0, 1],
|
|
@@ -4812,6 +4969,10 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4812
4969
|
case "eye_R":
|
|
4813
4970
|
warps.push(blinkFold(eyeOpen, mesh, b, style.blink));
|
|
4814
4971
|
break;
|
|
4972
|
+
case "lash_lower_L":
|
|
4973
|
+
case "lash_lower_R":
|
|
4974
|
+
warps.push(blinkFold(eyeOpen, mesh, b, style.blink, box(`eye_${side}`)));
|
|
4975
|
+
break;
|
|
4815
4976
|
case "lash_L":
|
|
4816
4977
|
case "lash_R":
|
|
4817
4978
|
warps.push(lashFold(eyeOpen, mesh, b, box(`eye_${side}`), style.blink));
|
|
@@ -4842,8 +5003,8 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4842
5003
|
if (byRole.has("mouth_open")) {
|
|
4843
5004
|
warps.push(mouthWiden(mesh, b));
|
|
4844
5005
|
bindings.push(
|
|
4845
|
-
{ parameter:
|
|
4846
|
-
{ parameter:
|
|
5006
|
+
{ parameter: import_format6.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 },
|
|
5007
|
+
{ parameter: import_format6.StandardParameter.MouthOpen, channel: "opacity", from: 1, to: 0 }
|
|
4847
5008
|
);
|
|
4848
5009
|
extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
|
|
4849
5010
|
} else {
|
|
@@ -4853,19 +5014,19 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4853
5014
|
);
|
|
4854
5015
|
bindings.push(
|
|
4855
5016
|
{
|
|
4856
|
-
parameter:
|
|
5017
|
+
parameter: import_format6.StandardParameter.MouthOpen,
|
|
4857
5018
|
channel: "scaleY",
|
|
4858
5019
|
from: 0,
|
|
4859
5020
|
to: roundTo(grow, 0.01)
|
|
4860
5021
|
},
|
|
4861
5022
|
{
|
|
4862
|
-
parameter:
|
|
5023
|
+
parameter: import_format6.StandardParameter.MouthOpen,
|
|
4863
5024
|
channel: "scaleX",
|
|
4864
5025
|
from: 0,
|
|
4865
5026
|
to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01)
|
|
4866
5027
|
},
|
|
4867
5028
|
{
|
|
4868
|
-
parameter:
|
|
5029
|
+
parameter: import_format6.StandardParameter.MouthOpen,
|
|
4869
5030
|
channel: "translateY",
|
|
4870
5031
|
from: 0,
|
|
4871
5032
|
to: -roundTo(grow * bh(b) / 2, 0.01)
|
|
@@ -4877,20 +5038,29 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4877
5038
|
case "mouth_open":
|
|
4878
5039
|
warps.push(mouthForm(mesh, b), mouthOpenGrow(mesh, b));
|
|
4879
5040
|
bindings.push({
|
|
4880
|
-
parameter:
|
|
5041
|
+
parameter: import_format6.StandardParameter.MouthOpen,
|
|
4881
5042
|
channel: "opacity",
|
|
4882
5043
|
from: 0,
|
|
4883
5044
|
to: 1
|
|
4884
5045
|
});
|
|
4885
5046
|
extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
|
|
4886
5047
|
break;
|
|
5048
|
+
case "blush_L":
|
|
5049
|
+
case "blush_R":
|
|
5050
|
+
bindings.push({
|
|
5051
|
+
parameter: import_format6.StandardParameter.Cheek,
|
|
5052
|
+
channel: "opacity",
|
|
5053
|
+
from: AMPLITUDE.blushRest,
|
|
5054
|
+
to: 1
|
|
5055
|
+
});
|
|
5056
|
+
break;
|
|
4887
5057
|
case "hair_front":
|
|
4888
5058
|
case "hair_back":
|
|
4889
5059
|
if (byRole.has("hair_front")) {
|
|
4890
5060
|
const amp = style.sway * AMPLITUDE.sway * hh;
|
|
4891
5061
|
warps.push(
|
|
4892
|
-
hairSway(
|
|
4893
|
-
hairSway(
|
|
5062
|
+
hairSway(import_format6.StandardParameter.HairSwayX, mesh, b, amp),
|
|
5063
|
+
hairSway(import_format6.StandardParameter.HairSwayZ, mesh, b, amp)
|
|
4894
5064
|
);
|
|
4895
5065
|
}
|
|
4896
5066
|
warps.push(tiltHang(mesh, b, pivot, hairHangWeight(frame.chinY, b.y0)));
|
|
@@ -4971,7 +5141,7 @@ function deformers(frame, grids, body) {
|
|
|
4971
5141
|
pivot: { x: roundTo(cx(body), 0.01), y: roundTo(body.y1, 0.01) },
|
|
4972
5142
|
bindings: [
|
|
4973
5143
|
{
|
|
4974
|
-
parameter:
|
|
5144
|
+
parameter: import_format6.StandardParameter.Breath,
|
|
4975
5145
|
channel: "translateY",
|
|
4976
5146
|
from: 0,
|
|
4977
5147
|
to: roundTo(AMPLITUDE.breathBody * frame.hh, 0.01)
|
|
@@ -4984,9 +5154,9 @@ function deformers(frame, grids, body) {
|
|
|
4984
5154
|
pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },
|
|
4985
5155
|
bindings: [
|
|
4986
5156
|
// AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.
|
|
4987
|
-
{ parameter:
|
|
5157
|
+
{ parameter: import_format6.StandardParameter.AngleZ, channel: "rotate", from: ROLL_DEG, to: -ROLL_DEG },
|
|
4988
5158
|
{
|
|
4989
|
-
parameter:
|
|
5159
|
+
parameter: import_format6.StandardParameter.Breath,
|
|
4990
5160
|
channel: "translateY",
|
|
4991
5161
|
from: 0,
|
|
4992
5162
|
to: roundTo(AMPLITUDE.breathHead * frame.hh, 0.01)
|
|
@@ -5004,8 +5174,8 @@ function deformers(frame, grids, body) {
|
|
|
5004
5174
|
points: g.lattice.points
|
|
5005
5175
|
},
|
|
5006
5176
|
warp2d: {
|
|
5007
|
-
parameter:
|
|
5008
|
-
parameterY:
|
|
5177
|
+
parameter: import_format6.StandardParameter.AngleX,
|
|
5178
|
+
parameterY: import_format6.StandardParameter.AngleY,
|
|
5009
5179
|
valuesX: X_STOPS,
|
|
5010
5180
|
valuesY: Y_STOPS,
|
|
5011
5181
|
keyforms2d: g.keyforms.map((offsets) => ({ offsets }))
|
|
@@ -5018,16 +5188,16 @@ function hairPhysics() {
|
|
|
5018
5188
|
return [
|
|
5019
5189
|
{
|
|
5020
5190
|
id: "hairSway",
|
|
5021
|
-
input: { parameter:
|
|
5022
|
-
output: { parameter:
|
|
5191
|
+
input: { parameter: import_format6.StandardParameter.AngleX, weight: 1 },
|
|
5192
|
+
output: { parameter: import_format6.StandardParameter.HairSwayX, scale: 5 },
|
|
5023
5193
|
mass: 1,
|
|
5024
5194
|
stiffness: 30,
|
|
5025
5195
|
damping: 3
|
|
5026
5196
|
},
|
|
5027
5197
|
{
|
|
5028
5198
|
id: "hairTilt",
|
|
5029
|
-
input: { parameter:
|
|
5030
|
-
output: { parameter:
|
|
5199
|
+
input: { parameter: import_format6.StandardParameter.AngleZ, weight: 1 },
|
|
5200
|
+
output: { parameter: import_format6.StandardParameter.HairSwayZ, scale: 8 },
|
|
5031
5201
|
mass: 1,
|
|
5032
5202
|
stiffness: 25,
|
|
5033
5203
|
damping: 2.5
|
|
@@ -5037,29 +5207,32 @@ function hairPhysics() {
|
|
|
5037
5207
|
function declareParameters(roles) {
|
|
5038
5208
|
const out = [];
|
|
5039
5209
|
const add = (id, name, min, max, def) => out.push({ id, name, min, max, default: def });
|
|
5040
|
-
add(
|
|
5041
|
-
add(
|
|
5042
|
-
add(
|
|
5043
|
-
add(
|
|
5044
|
-
add(
|
|
5210
|
+
add(import_format6.StandardParameter.AngleX, "Head Angle", -30, 30, 0);
|
|
5211
|
+
add(import_format6.StandardParameter.AngleY, "Head Angle Y", -30, 30, 0);
|
|
5212
|
+
add(import_format6.StandardParameter.AngleZ, "Head Angle Z", -30, 30, 0);
|
|
5213
|
+
add(import_format6.StandardParameter.EyeOpenLeft, "Eye L", 0, 1, 1);
|
|
5214
|
+
add(import_format6.StandardParameter.EyeOpenRight, "Eye R", 0, 1, 1);
|
|
5045
5215
|
if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {
|
|
5046
|
-
add(
|
|
5047
|
-
add(
|
|
5216
|
+
add(import_format6.StandardParameter.EyeballX, "Gaze X", -1, 1, 0);
|
|
5217
|
+
add(import_format6.StandardParameter.EyeballY, "Gaze Y", -1, 1, 0);
|
|
5048
5218
|
}
|
|
5049
|
-
add(
|
|
5050
|
-
add(
|
|
5219
|
+
add(import_format6.StandardParameter.MouthOpen, "Mouth Open", 0, 1, 0);
|
|
5220
|
+
add(import_format6.StandardParameter.MouthForm, "Mouth Form", -1, 1, 0);
|
|
5051
5221
|
if (roles.has("brow_L")) {
|
|
5052
|
-
add(
|
|
5053
|
-
add(
|
|
5222
|
+
add(import_format6.StandardParameter.BrowLeftY, "Brow L Y", -1, 1, 0);
|
|
5223
|
+
add(import_format6.StandardParameter.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
|
|
5054
5224
|
}
|
|
5055
5225
|
if (roles.has("brow_R")) {
|
|
5056
|
-
add(
|
|
5057
|
-
add(
|
|
5226
|
+
add(import_format6.StandardParameter.BrowRightY, "Brow R Y", -1, 1, 0);
|
|
5227
|
+
add(import_format6.StandardParameter.BrowRightAngle, "Brow R Angle", -1, 1, 0);
|
|
5228
|
+
}
|
|
5229
|
+
if (roles.has("blush_L") || roles.has("blush_R")) {
|
|
5230
|
+
add(import_format6.StandardParameter.Cheek, "Cheek", 0, 1, 0);
|
|
5058
5231
|
}
|
|
5059
|
-
add(
|
|
5232
|
+
add(import_format6.StandardParameter.Breath, "Breath", 0, 1, 0);
|
|
5060
5233
|
if (roles.has("hair_front")) {
|
|
5061
|
-
add(
|
|
5062
|
-
add(
|
|
5234
|
+
add(import_format6.StandardParameter.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
|
|
5235
|
+
add(import_format6.StandardParameter.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
|
|
5063
5236
|
}
|
|
5064
5237
|
return out;
|
|
5065
5238
|
}
|