@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/dist/index.mjs
CHANGED
|
@@ -1910,7 +1910,8 @@ var PROFILE_VALUES = {
|
|
|
1910
1910
|
mouthWiden: 1.2,
|
|
1911
1911
|
brow: 0.15,
|
|
1912
1912
|
breath: 0.03,
|
|
1913
|
-
sway: 0.08
|
|
1913
|
+
sway: 0.08,
|
|
1914
|
+
blushRest: 0.4
|
|
1914
1915
|
};
|
|
1915
1916
|
function deriveProfile(v) {
|
|
1916
1917
|
const farLead = v.lead * (1 - v.fore / 2);
|
|
@@ -1997,6 +1998,8 @@ function deriveProfile(v) {
|
|
|
1997
1998
|
breathHead: v.breath * 2 / 3,
|
|
1998
1999
|
/** Hair tip travel at full sway (±20), hh. */
|
|
1999
2000
|
sway: v.sway,
|
|
2001
|
+
/** The blush's opacity at Cheek 0; at Cheek 1 it is as drawn. */
|
|
2002
|
+
blushRest: v.blushRest,
|
|
2000
2003
|
/** The neck under the face reaches this far above the jaw, hh — what the
|
|
2001
2004
|
* chin uncovers as it slides off it: half again the chin's full-turn
|
|
2002
2005
|
* slide, to the next 0.05. */
|
|
@@ -2058,6 +2061,8 @@ var ROLE_TABLE = [
|
|
|
2058
2061
|
{ role: "pupil_R", family: "eye_R" },
|
|
2059
2062
|
{ role: "highlight_L", family: "eye_L" },
|
|
2060
2063
|
{ role: "highlight_R", family: "eye_R" },
|
|
2064
|
+
{ role: "lash_lower_L", family: "eye_L" },
|
|
2065
|
+
{ role: "lash_lower_R", family: "eye_R" },
|
|
2061
2066
|
{ role: "lash_L", family: "eye_L" },
|
|
2062
2067
|
{ role: "lash_R", family: "eye_R" },
|
|
2063
2068
|
{ role: "brow_L", family: "brow_L" },
|
|
@@ -2114,10 +2119,161 @@ function parseLayerRoles(fileNames) {
|
|
|
2114
2119
|
// src/auto-rig/generate.ts
|
|
2115
2120
|
import {
|
|
2116
2121
|
IKI_FORMAT_VERSION as IKI_FORMAT_VERSION2,
|
|
2117
|
-
StandardParameter as
|
|
2122
|
+
StandardParameter as P4,
|
|
2118
2123
|
parseIkiModel as parseIkiModel3
|
|
2119
2124
|
} from "@ikijs/format";
|
|
2120
2125
|
|
|
2126
|
+
// src/auto-rig/animations.ts
|
|
2127
|
+
import {
|
|
2128
|
+
StandardParameter as P
|
|
2129
|
+
} from "@ikijs/format";
|
|
2130
|
+
function browsY(y) {
|
|
2131
|
+
return [
|
|
2132
|
+
{ parameter: P.BrowLeftY, value: y, blend: "add" },
|
|
2133
|
+
{ parameter: P.BrowRightY, value: y, blend: "add" }
|
|
2134
|
+
];
|
|
2135
|
+
}
|
|
2136
|
+
function browsTilt(innerDown) {
|
|
2137
|
+
return [
|
|
2138
|
+
{ parameter: P.BrowLeftAngle, value: innerDown, blend: "add" },
|
|
2139
|
+
{ parameter: P.BrowRightAngle, value: -innerDown, blend: "add" }
|
|
2140
|
+
];
|
|
2141
|
+
}
|
|
2142
|
+
function cheek(value) {
|
|
2143
|
+
return { parameter: P.Cheek, value, blend: "add" };
|
|
2144
|
+
}
|
|
2145
|
+
var BROWS = [P.BrowLeftY, P.BrowRightY, P.BrowLeftAngle, P.BrowRightAngle];
|
|
2146
|
+
var EXPRESSIONS = [
|
|
2147
|
+
{
|
|
2148
|
+
id: "smile",
|
|
2149
|
+
description: "Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.",
|
|
2150
|
+
parameters: [
|
|
2151
|
+
{ parameter: P.MouthForm, value: 1, blend: "add" },
|
|
2152
|
+
...browsY(0.25),
|
|
2153
|
+
cheek(0.4)
|
|
2154
|
+
]
|
|
2155
|
+
},
|
|
2156
|
+
{
|
|
2157
|
+
id: "laugh",
|
|
2158
|
+
description: "Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.",
|
|
2159
|
+
parameters: [
|
|
2160
|
+
{ parameter: P.EyeOpenLeft, value: 0, blend: "multiply" },
|
|
2161
|
+
{ parameter: P.EyeOpenRight, value: 0, blend: "multiply" },
|
|
2162
|
+
{ parameter: P.MouthForm, value: 1, blend: "add" },
|
|
2163
|
+
{ parameter: P.MouthOpen, value: 0.8, blend: "overwrite" },
|
|
2164
|
+
...browsY(0.4),
|
|
2165
|
+
cheek(0.65)
|
|
2166
|
+
]
|
|
2167
|
+
},
|
|
2168
|
+
{
|
|
2169
|
+
id: "angry",
|
|
2170
|
+
description: "Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.",
|
|
2171
|
+
needs: BROWS,
|
|
2172
|
+
parameters: [
|
|
2173
|
+
...browsY(-0.5),
|
|
2174
|
+
...browsTilt(0.8),
|
|
2175
|
+
{ parameter: P.MouthForm, value: -0.9, blend: "add" }
|
|
2176
|
+
]
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
id: "sad",
|
|
2180
|
+
description: "Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.",
|
|
2181
|
+
needs: BROWS,
|
|
2182
|
+
parameters: [
|
|
2183
|
+
...browsY(0.35),
|
|
2184
|
+
...browsTilt(-0.8),
|
|
2185
|
+
{ parameter: P.MouthForm, value: -0.8, blend: "add" }
|
|
2186
|
+
]
|
|
2187
|
+
},
|
|
2188
|
+
{
|
|
2189
|
+
id: "surprised",
|
|
2190
|
+
description: "Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.",
|
|
2191
|
+
parameters: [
|
|
2192
|
+
...browsY(0.8),
|
|
2193
|
+
{ parameter: P.MouthOpen, value: 0.9, blend: "overwrite" }
|
|
2194
|
+
]
|
|
2195
|
+
},
|
|
2196
|
+
{
|
|
2197
|
+
id: "shy",
|
|
2198
|
+
description: "Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.",
|
|
2199
|
+
needs: [P.Cheek],
|
|
2200
|
+
parameters: [
|
|
2201
|
+
cheek(1),
|
|
2202
|
+
// Gaze down.
|
|
2203
|
+
{ parameter: P.EyeballY, value: -0.65, blend: "add" },
|
|
2204
|
+
{ parameter: P.MouthForm, value: 0.4, blend: "add" },
|
|
2205
|
+
...browsTilt(-0.25)
|
|
2206
|
+
]
|
|
2207
|
+
}
|
|
2208
|
+
];
|
|
2209
|
+
function defaultExpressions(declared) {
|
|
2210
|
+
return EXPRESSIONS.filter(
|
|
2211
|
+
(e) => e.needs === void 0 || e.needs.some((id) => declared.has(id))
|
|
2212
|
+
).map(({ needs: _needs, ...e }) => ({
|
|
2213
|
+
...e,
|
|
2214
|
+
parameters: e.parameters.filter((t) => declared.has(t.parameter))
|
|
2215
|
+
}));
|
|
2216
|
+
}
|
|
2217
|
+
var DEFAULT_MOTIONS = {
|
|
2218
|
+
Nod: [
|
|
2219
|
+
{
|
|
2220
|
+
description: "Nods yes: agreement, acknowledgement, understanding.",
|
|
2221
|
+
duration: 1,
|
|
2222
|
+
curves: [
|
|
2223
|
+
{
|
|
2224
|
+
parameter: P.AngleY,
|
|
2225
|
+
keys: [
|
|
2226
|
+
[0, 0],
|
|
2227
|
+
[0.3, -18],
|
|
2228
|
+
[0.6, 4],
|
|
2229
|
+
[0.8, -1],
|
|
2230
|
+
[1, 0]
|
|
2231
|
+
]
|
|
2232
|
+
}
|
|
2233
|
+
]
|
|
2234
|
+
}
|
|
2235
|
+
],
|
|
2236
|
+
Shake: [
|
|
2237
|
+
{
|
|
2238
|
+
description: "Shakes the head no: disagreement, refusal, disbelief.",
|
|
2239
|
+
duration: 1.2,
|
|
2240
|
+
// The first swing peaks at 0.2 s, which the default fade would still
|
|
2241
|
+
// be damping.
|
|
2242
|
+
fadeIn: 0.15,
|
|
2243
|
+
curves: [
|
|
2244
|
+
{
|
|
2245
|
+
parameter: P.AngleX,
|
|
2246
|
+
keys: [
|
|
2247
|
+
[0, 0],
|
|
2248
|
+
[0.2, -18],
|
|
2249
|
+
[0.45, 18],
|
|
2250
|
+
[0.7, -16],
|
|
2251
|
+
[0.95, 10],
|
|
2252
|
+
[1.2, 0]
|
|
2253
|
+
]
|
|
2254
|
+
}
|
|
2255
|
+
]
|
|
2256
|
+
}
|
|
2257
|
+
],
|
|
2258
|
+
Tilt: [
|
|
2259
|
+
{
|
|
2260
|
+
description: "Tilts the head to one side and back: curiosity, puzzlement, a question.",
|
|
2261
|
+
duration: 1.4,
|
|
2262
|
+
curves: [
|
|
2263
|
+
{
|
|
2264
|
+
parameter: P.AngleZ,
|
|
2265
|
+
keys: [
|
|
2266
|
+
[0, 0],
|
|
2267
|
+
[0.35, 20],
|
|
2268
|
+
[1, 20],
|
|
2269
|
+
[1.4, 0]
|
|
2270
|
+
]
|
|
2271
|
+
}
|
|
2272
|
+
]
|
|
2273
|
+
}
|
|
2274
|
+
]
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2121
2277
|
// src/auto-rig/layout.ts
|
|
2122
2278
|
function boxOfLayer(layer) {
|
|
2123
2279
|
return boxOfPixels(layer.bbox, layer.canvasW, layer.canvasH);
|
|
@@ -2411,7 +2567,7 @@ function checkStrandEdges(strand, irises, hair) {
|
|
|
2411
2567
|
}
|
|
2412
2568
|
|
|
2413
2569
|
// src/auto-rig/context.ts
|
|
2414
|
-
import { StandardParameter as
|
|
2570
|
+
import { StandardParameter as P2 } from "@ikijs/format";
|
|
2415
2571
|
|
|
2416
2572
|
// src/auto-rig/grid.ts
|
|
2417
2573
|
var X_STOPS = [-30, 0, 30];
|
|
@@ -3627,7 +3783,7 @@ function renderedLander(turn, parts, grids, from = /* @__PURE__ */ new Map()) {
|
|
|
3627
3783
|
const family = roleSpec(role).family;
|
|
3628
3784
|
const part = parts.find((p) => p.id === role);
|
|
3629
3785
|
const g = grids.get(family);
|
|
3630
|
-
const warp = part?.warps?.find((w) => w.parameter ===
|
|
3786
|
+
const warp = part?.warps?.find((w) => w.parameter === P2.AngleX);
|
|
3631
3787
|
if (part === void 0 || part.mesh === void 0 || !g && !warp) {
|
|
3632
3788
|
return x + field(role)(x, y, ax, 0)[0];
|
|
3633
3789
|
}
|
|
@@ -4338,7 +4494,7 @@ function buildTurn(frame, landmarks, q) {
|
|
|
4338
4494
|
|
|
4339
4495
|
// src/auto-rig/drivers.ts
|
|
4340
4496
|
import {
|
|
4341
|
-
StandardParameter as
|
|
4497
|
+
StandardParameter as P3
|
|
4342
4498
|
} from "@ikijs/format";
|
|
4343
4499
|
var SWAY_RANGE = 20;
|
|
4344
4500
|
var SWAY_CURVE = 1.4;
|
|
@@ -4391,12 +4547,12 @@ function motionReach(warps, mesh, box, extra = [0, 0]) {
|
|
|
4391
4547
|
}
|
|
4392
4548
|
return out;
|
|
4393
4549
|
}
|
|
4394
|
-
function blinkFold(param, mesh,
|
|
4550
|
+
function blinkFold(param, mesh, box, travel, eye = box) {
|
|
4395
4551
|
const yc = eye.y1 - travel * bh(eye);
|
|
4396
4552
|
return localWarp(
|
|
4397
4553
|
param,
|
|
4398
4554
|
mesh,
|
|
4399
|
-
|
|
4555
|
+
box,
|
|
4400
4556
|
[0, 1],
|
|
4401
4557
|
([, y], v) => v === 1 ? [0, 0] : [0, yc - y]
|
|
4402
4558
|
);
|
|
@@ -4417,13 +4573,13 @@ function gazeBindings(irisW, share = 1) {
|
|
|
4417
4573
|
const gy = AMPLITUDE.gazeY * irisW * share;
|
|
4418
4574
|
return [
|
|
4419
4575
|
{
|
|
4420
|
-
parameter:
|
|
4576
|
+
parameter: P3.EyeballX,
|
|
4421
4577
|
channel: "translateX",
|
|
4422
4578
|
from: -round1(gx),
|
|
4423
4579
|
to: round1(gx)
|
|
4424
4580
|
},
|
|
4425
4581
|
{
|
|
4426
|
-
parameter:
|
|
4582
|
+
parameter: P3.EyeballY,
|
|
4427
4583
|
channel: "translateY",
|
|
4428
4584
|
from: -round1(gy),
|
|
4429
4585
|
to: round1(gy)
|
|
@@ -4437,8 +4593,8 @@ function browReach(hh) {
|
|
|
4437
4593
|
return AMPLITUDE.brow * hh;
|
|
4438
4594
|
}
|
|
4439
4595
|
function browBindings(side, reach) {
|
|
4440
|
-
const y = side === "L" ?
|
|
4441
|
-
const a = side === "L" ?
|
|
4596
|
+
const y = side === "L" ? P3.BrowLeftY : P3.BrowRightY;
|
|
4597
|
+
const a = side === "L" ? P3.BrowLeftAngle : P3.BrowRightAngle;
|
|
4442
4598
|
return [
|
|
4443
4599
|
{
|
|
4444
4600
|
parameter: y,
|
|
@@ -4454,7 +4610,7 @@ function mouthForm(mesh, box) {
|
|
|
4454
4610
|
const a = 0.3 * bh(box);
|
|
4455
4611
|
const c = cx(box);
|
|
4456
4612
|
const half = bw(box) / 2;
|
|
4457
|
-
return localWarp(
|
|
4613
|
+
return localWarp(P3.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {
|
|
4458
4614
|
if (v === 0) return [0, 0];
|
|
4459
4615
|
const u = (x - c) / half;
|
|
4460
4616
|
const widen = v > 0 ? 0.05 : 0.03;
|
|
@@ -4464,7 +4620,7 @@ function mouthForm(mesh, box) {
|
|
|
4464
4620
|
function mouthOpenGrow(mesh, box) {
|
|
4465
4621
|
const c = cx(box);
|
|
4466
4622
|
return localWarp(
|
|
4467
|
-
|
|
4623
|
+
P3.MouthOpen,
|
|
4468
4624
|
mesh,
|
|
4469
4625
|
box,
|
|
4470
4626
|
[0, 1],
|
|
@@ -4473,7 +4629,7 @@ function mouthOpenGrow(mesh, box) {
|
|
|
4473
4629
|
}
|
|
4474
4630
|
function mouthWiden(mesh, box) {
|
|
4475
4631
|
const c = cx(box);
|
|
4476
|
-
return localWarp(
|
|
4632
|
+
return localWarp(P3.MouthOpen, mesh, box, [0, 1], ([x], v) => [
|
|
4477
4633
|
v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),
|
|
4478
4634
|
0
|
|
4479
4635
|
]);
|
|
@@ -4491,7 +4647,7 @@ function hairSway(param, mesh, box, amp) {
|
|
|
4491
4647
|
);
|
|
4492
4648
|
}
|
|
4493
4649
|
function tiltHang(mesh, box, pivot, weight) {
|
|
4494
|
-
return localWarp(
|
|
4650
|
+
return localWarp(P3.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {
|
|
4495
4651
|
const g = weight(y, i);
|
|
4496
4652
|
if (g === 0 || v === 0) return [0, 0];
|
|
4497
4653
|
const a = -g * rollOf(v);
|
|
@@ -4644,14 +4800,17 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
|
|
|
4644
4800
|
...part.warps ?? []
|
|
4645
4801
|
];
|
|
4646
4802
|
}
|
|
4803
|
+
const parameters = declareParameters(new Set(byRole.keys()));
|
|
4647
4804
|
const model = {
|
|
4648
4805
|
version: IKI_FORMAT_VERSION2,
|
|
4649
4806
|
name: "auto-rigged",
|
|
4650
4807
|
canvas: { width: canvas.width, height: canvas.height },
|
|
4651
|
-
parameters
|
|
4808
|
+
parameters,
|
|
4652
4809
|
parts,
|
|
4653
4810
|
deformers: deformers(frame, grids, has("body") ? box("body") : void 0),
|
|
4654
|
-
...has("hair_front") ? { physics: hairPhysics() } : {}
|
|
4811
|
+
...has("hair_front") ? { physics: hairPhysics() } : {},
|
|
4812
|
+
expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),
|
|
4813
|
+
motions: DEFAULT_MOTIONS
|
|
4655
4814
|
};
|
|
4656
4815
|
const valid = parseIkiModel3(model);
|
|
4657
4816
|
if (hasNose && options.onTurnSolved) {
|
|
@@ -4668,14 +4827,14 @@ function generateIkiFromLayerSet(layers, canvas, options = {}) {
|
|
|
4668
4827
|
function turnWarps(mesh, b, fieldOf) {
|
|
4669
4828
|
return [
|
|
4670
4829
|
localWarp(
|
|
4671
|
-
|
|
4830
|
+
P4.AngleX,
|
|
4672
4831
|
mesh,
|
|
4673
4832
|
b,
|
|
4674
4833
|
X_STOPS,
|
|
4675
4834
|
([x, y], v, i) => v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0]
|
|
4676
4835
|
),
|
|
4677
4836
|
localWarp(
|
|
4678
|
-
|
|
4837
|
+
P4.AngleY,
|
|
4679
4838
|
mesh,
|
|
4680
4839
|
b,
|
|
4681
4840
|
Y_STOPS,
|
|
@@ -4723,7 +4882,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4723
4882
|
}
|
|
4724
4883
|
if (mesh !== void 0) part.mesh = mesh;
|
|
4725
4884
|
const side = spec.role.endsWith("_L") ? "L" : "R";
|
|
4726
|
-
const eyeOpen = side === "L" ?
|
|
4885
|
+
const eyeOpen = side === "L" ? P4.EyeOpenLeft : P4.EyeOpenRight;
|
|
4727
4886
|
const hh = frame.hh;
|
|
4728
4887
|
switch (spec.role) {
|
|
4729
4888
|
case "face":
|
|
@@ -4732,7 +4891,7 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4732
4891
|
warps.push(
|
|
4733
4892
|
tiltHang(mesh, b, pivot, (_y, i) => isNeck[i] ? 1 : 0),
|
|
4734
4893
|
localWarp(
|
|
4735
|
-
|
|
4894
|
+
P4.Breath,
|
|
4736
4895
|
mesh,
|
|
4737
4896
|
b,
|
|
4738
4897
|
[0, 1],
|
|
@@ -4745,6 +4904,10 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4745
4904
|
case "eye_R":
|
|
4746
4905
|
warps.push(blinkFold(eyeOpen, mesh, b, style.blink));
|
|
4747
4906
|
break;
|
|
4907
|
+
case "lash_lower_L":
|
|
4908
|
+
case "lash_lower_R":
|
|
4909
|
+
warps.push(blinkFold(eyeOpen, mesh, b, style.blink, box(`eye_${side}`)));
|
|
4910
|
+
break;
|
|
4748
4911
|
case "lash_L":
|
|
4749
4912
|
case "lash_R":
|
|
4750
4913
|
warps.push(lashFold(eyeOpen, mesh, b, box(`eye_${side}`), style.blink));
|
|
@@ -4775,8 +4938,8 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4775
4938
|
if (byRole.has("mouth_open")) {
|
|
4776
4939
|
warps.push(mouthWiden(mesh, b));
|
|
4777
4940
|
bindings.push(
|
|
4778
|
-
{ parameter:
|
|
4779
|
-
{ parameter:
|
|
4941
|
+
{ parameter: P4.MouthOpen, channel: "opacity", from: 1, to: 0 },
|
|
4942
|
+
{ parameter: P4.MouthOpen, channel: "opacity", from: 1, to: 0 }
|
|
4780
4943
|
);
|
|
4781
4944
|
extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
|
|
4782
4945
|
} else {
|
|
@@ -4786,19 +4949,19 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4786
4949
|
);
|
|
4787
4950
|
bindings.push(
|
|
4788
4951
|
{
|
|
4789
|
-
parameter:
|
|
4952
|
+
parameter: P4.MouthOpen,
|
|
4790
4953
|
channel: "scaleY",
|
|
4791
4954
|
from: 0,
|
|
4792
4955
|
to: roundTo(grow, 0.01)
|
|
4793
4956
|
},
|
|
4794
4957
|
{
|
|
4795
|
-
parameter:
|
|
4958
|
+
parameter: P4.MouthOpen,
|
|
4796
4959
|
channel: "scaleX",
|
|
4797
4960
|
from: 0,
|
|
4798
4961
|
to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01)
|
|
4799
4962
|
},
|
|
4800
4963
|
{
|
|
4801
|
-
parameter:
|
|
4964
|
+
parameter: P4.MouthOpen,
|
|
4802
4965
|
channel: "translateY",
|
|
4803
4966
|
from: 0,
|
|
4804
4967
|
to: -roundTo(grow * bh(b) / 2, 0.01)
|
|
@@ -4810,20 +4973,29 @@ function buildPart(spec, b, order, frame, byRole, style, frontGrid) {
|
|
|
4810
4973
|
case "mouth_open":
|
|
4811
4974
|
warps.push(mouthForm(mesh, b), mouthOpenGrow(mesh, b));
|
|
4812
4975
|
bindings.push({
|
|
4813
|
-
parameter:
|
|
4976
|
+
parameter: P4.MouthOpen,
|
|
4814
4977
|
channel: "opacity",
|
|
4815
4978
|
from: 0,
|
|
4816
4979
|
to: 1
|
|
4817
4980
|
});
|
|
4818
4981
|
extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];
|
|
4819
4982
|
break;
|
|
4983
|
+
case "blush_L":
|
|
4984
|
+
case "blush_R":
|
|
4985
|
+
bindings.push({
|
|
4986
|
+
parameter: P4.Cheek,
|
|
4987
|
+
channel: "opacity",
|
|
4988
|
+
from: AMPLITUDE.blushRest,
|
|
4989
|
+
to: 1
|
|
4990
|
+
});
|
|
4991
|
+
break;
|
|
4820
4992
|
case "hair_front":
|
|
4821
4993
|
case "hair_back":
|
|
4822
4994
|
if (byRole.has("hair_front")) {
|
|
4823
4995
|
const amp = style.sway * AMPLITUDE.sway * hh;
|
|
4824
4996
|
warps.push(
|
|
4825
|
-
hairSway(
|
|
4826
|
-
hairSway(
|
|
4997
|
+
hairSway(P4.HairSwayX, mesh, b, amp),
|
|
4998
|
+
hairSway(P4.HairSwayZ, mesh, b, amp)
|
|
4827
4999
|
);
|
|
4828
5000
|
}
|
|
4829
5001
|
warps.push(tiltHang(mesh, b, pivot, hairHangWeight(frame.chinY, b.y0)));
|
|
@@ -4904,7 +5076,7 @@ function deformers(frame, grids, body) {
|
|
|
4904
5076
|
pivot: { x: roundTo(cx(body), 0.01), y: roundTo(body.y1, 0.01) },
|
|
4905
5077
|
bindings: [
|
|
4906
5078
|
{
|
|
4907
|
-
parameter:
|
|
5079
|
+
parameter: P4.Breath,
|
|
4908
5080
|
channel: "translateY",
|
|
4909
5081
|
from: 0,
|
|
4910
5082
|
to: roundTo(AMPLITUDE.breathBody * frame.hh, 0.01)
|
|
@@ -4917,9 +5089,9 @@ function deformers(frame, grids, body) {
|
|
|
4917
5089
|
pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },
|
|
4918
5090
|
bindings: [
|
|
4919
5091
|
// AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.
|
|
4920
|
-
{ parameter:
|
|
5092
|
+
{ parameter: P4.AngleZ, channel: "rotate", from: ROLL_DEG, to: -ROLL_DEG },
|
|
4921
5093
|
{
|
|
4922
|
-
parameter:
|
|
5094
|
+
parameter: P4.Breath,
|
|
4923
5095
|
channel: "translateY",
|
|
4924
5096
|
from: 0,
|
|
4925
5097
|
to: roundTo(AMPLITUDE.breathHead * frame.hh, 0.01)
|
|
@@ -4937,8 +5109,8 @@ function deformers(frame, grids, body) {
|
|
|
4937
5109
|
points: g.lattice.points
|
|
4938
5110
|
},
|
|
4939
5111
|
warp2d: {
|
|
4940
|
-
parameter:
|
|
4941
|
-
parameterY:
|
|
5112
|
+
parameter: P4.AngleX,
|
|
5113
|
+
parameterY: P4.AngleY,
|
|
4942
5114
|
valuesX: X_STOPS,
|
|
4943
5115
|
valuesY: Y_STOPS,
|
|
4944
5116
|
keyforms2d: g.keyforms.map((offsets) => ({ offsets }))
|
|
@@ -4951,16 +5123,16 @@ function hairPhysics() {
|
|
|
4951
5123
|
return [
|
|
4952
5124
|
{
|
|
4953
5125
|
id: "hairSway",
|
|
4954
|
-
input: { parameter:
|
|
4955
|
-
output: { parameter:
|
|
5126
|
+
input: { parameter: P4.AngleX, weight: 1 },
|
|
5127
|
+
output: { parameter: P4.HairSwayX, scale: 5 },
|
|
4956
5128
|
mass: 1,
|
|
4957
5129
|
stiffness: 30,
|
|
4958
5130
|
damping: 3
|
|
4959
5131
|
},
|
|
4960
5132
|
{
|
|
4961
5133
|
id: "hairTilt",
|
|
4962
|
-
input: { parameter:
|
|
4963
|
-
output: { parameter:
|
|
5134
|
+
input: { parameter: P4.AngleZ, weight: 1 },
|
|
5135
|
+
output: { parameter: P4.HairSwayZ, scale: 8 },
|
|
4964
5136
|
mass: 1,
|
|
4965
5137
|
stiffness: 25,
|
|
4966
5138
|
damping: 2.5
|
|
@@ -4970,29 +5142,32 @@ function hairPhysics() {
|
|
|
4970
5142
|
function declareParameters(roles) {
|
|
4971
5143
|
const out = [];
|
|
4972
5144
|
const add = (id, name, min, max, def) => out.push({ id, name, min, max, default: def });
|
|
4973
|
-
add(
|
|
4974
|
-
add(
|
|
4975
|
-
add(
|
|
4976
|
-
add(
|
|
4977
|
-
add(
|
|
5145
|
+
add(P4.AngleX, "Head Angle", -30, 30, 0);
|
|
5146
|
+
add(P4.AngleY, "Head Angle Y", -30, 30, 0);
|
|
5147
|
+
add(P4.AngleZ, "Head Angle Z", -30, 30, 0);
|
|
5148
|
+
add(P4.EyeOpenLeft, "Eye L", 0, 1, 1);
|
|
5149
|
+
add(P4.EyeOpenRight, "Eye R", 0, 1, 1);
|
|
4978
5150
|
if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {
|
|
4979
|
-
add(
|
|
4980
|
-
add(
|
|
5151
|
+
add(P4.EyeballX, "Gaze X", -1, 1, 0);
|
|
5152
|
+
add(P4.EyeballY, "Gaze Y", -1, 1, 0);
|
|
4981
5153
|
}
|
|
4982
|
-
add(
|
|
4983
|
-
add(
|
|
5154
|
+
add(P4.MouthOpen, "Mouth Open", 0, 1, 0);
|
|
5155
|
+
add(P4.MouthForm, "Mouth Form", -1, 1, 0);
|
|
4984
5156
|
if (roles.has("brow_L")) {
|
|
4985
|
-
add(
|
|
4986
|
-
add(
|
|
5157
|
+
add(P4.BrowLeftY, "Brow L Y", -1, 1, 0);
|
|
5158
|
+
add(P4.BrowLeftAngle, "Brow L Angle", -1, 1, 0);
|
|
4987
5159
|
}
|
|
4988
5160
|
if (roles.has("brow_R")) {
|
|
4989
|
-
add(
|
|
4990
|
-
add(
|
|
5161
|
+
add(P4.BrowRightY, "Brow R Y", -1, 1, 0);
|
|
5162
|
+
add(P4.BrowRightAngle, "Brow R Angle", -1, 1, 0);
|
|
5163
|
+
}
|
|
5164
|
+
if (roles.has("blush_L") || roles.has("blush_R")) {
|
|
5165
|
+
add(P4.Cheek, "Cheek", 0, 1, 0);
|
|
4991
5166
|
}
|
|
4992
|
-
add(
|
|
5167
|
+
add(P4.Breath, "Breath", 0, 1, 0);
|
|
4993
5168
|
if (roles.has("hair_front")) {
|
|
4994
|
-
add(
|
|
4995
|
-
add(
|
|
5169
|
+
add(P4.HairSwayX, "Hair Sway X", -SWAY_RANGE, SWAY_RANGE, 0);
|
|
5170
|
+
add(P4.HairSwayZ, "Hair Sway Z", -SWAY_RANGE, SWAY_RANGE, 0);
|
|
4996
5171
|
}
|
|
4997
5172
|
return out;
|
|
4998
5173
|
}
|