@lovelace_lol/loom3 1.0.40 → 1.0.42
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 +3 -3
- package/dist/index.cjs +498 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +125 -6
- package/dist/index.d.ts +125 -6
- package/dist/index.js +487 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,223 @@ function getCompositeAxisBinding(nodeKey, axisConfig, direction, getValue, auToB
|
|
|
60
60
|
return null;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// src/mappings/visemeSystem.ts
|
|
64
|
+
function hasOwn(value, key) {
|
|
65
|
+
return Boolean(value && Object.prototype.hasOwnProperty.call(value, key));
|
|
66
|
+
}
|
|
67
|
+
function toSlotId(label, index) {
|
|
68
|
+
const normalized = label.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
69
|
+
return normalized || `viseme-${index}`;
|
|
70
|
+
}
|
|
71
|
+
function bindingTargets(binding) {
|
|
72
|
+
if (!binding) return [];
|
|
73
|
+
const targets = binding.targets?.map((target) => target.morph).filter((morph) => morph !== "");
|
|
74
|
+
if (targets && targets.length > 0) return targets;
|
|
75
|
+
return binding.morph !== void 0 && binding.morph !== "" ? [binding.morph] : [];
|
|
76
|
+
}
|
|
77
|
+
function getProfileVisemeSlots(profile) {
|
|
78
|
+
if (profile.visemeSlots && profile.visemeSlots.length > 0) {
|
|
79
|
+
return [...profile.visemeSlots].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
80
|
+
}
|
|
81
|
+
return (profile.visemeKeys || []).map((key, index) => {
|
|
82
|
+
const label = typeof key === "string" && key ? key : `Viseme ${index}`;
|
|
83
|
+
return {
|
|
84
|
+
id: toSlotId(label, index),
|
|
85
|
+
label,
|
|
86
|
+
order: index,
|
|
87
|
+
defaultJawAmount: profile.visemeJawAmounts?.[index]
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function getVisemeSlotIndex(profile, slotId) {
|
|
92
|
+
return getProfileVisemeSlots(profile).findIndex((slot) => slot.id === slotId);
|
|
93
|
+
}
|
|
94
|
+
function compileVisemeKeys(profile) {
|
|
95
|
+
const slots = getProfileVisemeSlots(profile);
|
|
96
|
+
if (!profile.visemeBindings) return [...profile.visemeKeys || []];
|
|
97
|
+
return slots.map((slot, index) => {
|
|
98
|
+
const target = bindingTargets(profile.visemeBindings?.[slot.id])[0];
|
|
99
|
+
return target ?? profile.visemeKeys?.[index] ?? "";
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function getVisemeJawAmounts(profile) {
|
|
103
|
+
const slots = getProfileVisemeSlots(profile);
|
|
104
|
+
if (slots.length === 0) return profile.visemeJawAmounts ? [...profile.visemeJawAmounts] : void 0;
|
|
105
|
+
return slots.map((slot, index) => slot.defaultJawAmount ?? profile.visemeJawAmounts?.[index] ?? 0);
|
|
106
|
+
}
|
|
107
|
+
function resolveVisemeMeshCategory(profile) {
|
|
108
|
+
const morphToMesh = profile.morphToMesh || {};
|
|
109
|
+
if (profile.visemeMeshCategory) return profile.visemeMeshCategory;
|
|
110
|
+
if (hasOwn(morphToMesh, "viseme")) return "viseme";
|
|
111
|
+
return "face";
|
|
112
|
+
}
|
|
113
|
+
function getMeshNamesForVisemeProfile(profile) {
|
|
114
|
+
const morphToMesh = profile.morphToMesh || {};
|
|
115
|
+
const category = resolveVisemeMeshCategory(profile);
|
|
116
|
+
if (hasOwn(morphToMesh, category)) {
|
|
117
|
+
return Array.isArray(morphToMesh[category]) ? [...morphToMesh[category]] : [];
|
|
118
|
+
}
|
|
119
|
+
return profile.visemeMeshCategory ? [] : [...morphToMesh.face || []];
|
|
120
|
+
}
|
|
121
|
+
function getMeshNamesForAUProfile(profile, auId) {
|
|
122
|
+
const morphToMesh = profile.morphToMesh || {};
|
|
123
|
+
const facePart = profile.auInfo?.[String(auId)]?.facePart;
|
|
124
|
+
const category = facePart ? profile.auFacePartToMeshCategory?.[facePart] : void 0;
|
|
125
|
+
if (category) return Array.isArray(morphToMesh[category]) ? [...morphToMesh[category]] : [];
|
|
126
|
+
return [...morphToMesh.face || []];
|
|
127
|
+
}
|
|
128
|
+
function compileMatcher(pattern) {
|
|
129
|
+
try {
|
|
130
|
+
return new RegExp(pattern, "i");
|
|
131
|
+
} catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function classifyVisemeMorph(morphName, profile) {
|
|
136
|
+
const slots = getProfileVisemeSlots(profile);
|
|
137
|
+
const matches = [];
|
|
138
|
+
for (const slot of slots) {
|
|
139
|
+
const explicitTargets = bindingTargets(profile.visemeBindings?.[slot.id]);
|
|
140
|
+
if (explicitTargets.some((target) => String(target).toLowerCase() === morphName.toLowerCase())) {
|
|
141
|
+
matches.push({
|
|
142
|
+
slotId: slot.id,
|
|
143
|
+
label: slot.label,
|
|
144
|
+
confidence: 1,
|
|
145
|
+
reason: "explicit"
|
|
146
|
+
});
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
for (const pattern of slot.matchers || []) {
|
|
150
|
+
const matcher = compileMatcher(pattern);
|
|
151
|
+
if (matcher?.test(morphName)) {
|
|
152
|
+
matches.push({
|
|
153
|
+
slotId: slot.id,
|
|
154
|
+
label: slot.label,
|
|
155
|
+
confidence: 0.75,
|
|
156
|
+
reason: "regex",
|
|
157
|
+
pattern
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return matches;
|
|
163
|
+
}
|
|
164
|
+
function buildMappingEditorModel(profile, morphNames = []) {
|
|
165
|
+
const sections = /* @__PURE__ */ new Map();
|
|
166
|
+
const configuredSections = profile.mappingSections || [];
|
|
167
|
+
const configuredById = new Map(configuredSections.map((section) => [section.id, section]));
|
|
168
|
+
let nextOrder = configuredSections.length;
|
|
169
|
+
for (const section of configuredSections) {
|
|
170
|
+
sections.set(section.id, { ...section });
|
|
171
|
+
}
|
|
172
|
+
const getOrder = (id, fallback) => {
|
|
173
|
+
const configured = configuredById.get(id);
|
|
174
|
+
if (configured) return configured.order;
|
|
175
|
+
if (fallback !== void 0) return fallback;
|
|
176
|
+
const order = nextOrder;
|
|
177
|
+
nextOrder += 1;
|
|
178
|
+
return order;
|
|
179
|
+
};
|
|
180
|
+
const auSectionOrders = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const [auId, info] of Object.entries(profile.auInfo || {})) {
|
|
182
|
+
const label = info.facePart || "Unmapped";
|
|
183
|
+
auSectionOrders.set(label, Math.min(auSectionOrders.get(label) ?? Number.MAX_SAFE_INTEGER, Number(auId)));
|
|
184
|
+
}
|
|
185
|
+
if (configuredSections.length === 0 && auSectionOrders.size > 0) {
|
|
186
|
+
nextOrder = Math.max(...auSectionOrders.values()) + 1;
|
|
187
|
+
}
|
|
188
|
+
for (const info of Object.values(profile.auInfo || {})) {
|
|
189
|
+
const label = info.facePart || "Unmapped";
|
|
190
|
+
const configured = configuredById.get(label);
|
|
191
|
+
const meshCategory = profile.auFacePartToMeshCategory?.[label] || "face";
|
|
192
|
+
sections.set(label, {
|
|
193
|
+
...configured,
|
|
194
|
+
id: label,
|
|
195
|
+
label: configured?.label || label,
|
|
196
|
+
kind: "au",
|
|
197
|
+
order: getOrder(label, auSectionOrders.get(label)),
|
|
198
|
+
meshCategory: configured?.meshCategory || meshCategory,
|
|
199
|
+
facePart: label
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const configuredVisemes = configuredById.get("Visemes");
|
|
203
|
+
sections.set("Visemes", {
|
|
204
|
+
...configuredVisemes,
|
|
205
|
+
id: "Visemes",
|
|
206
|
+
label: configuredVisemes?.label || "Visemes",
|
|
207
|
+
kind: "viseme",
|
|
208
|
+
order: getOrder("Visemes"),
|
|
209
|
+
meshCategory: configuredVisemes?.meshCategory || resolveVisemeMeshCategory(profile)
|
|
210
|
+
});
|
|
211
|
+
if (hasOwn(profile.morphToMesh, "hair")) {
|
|
212
|
+
const configuredHair = configuredById.get("Hair");
|
|
213
|
+
sections.set("Hair", {
|
|
214
|
+
...configuredHair,
|
|
215
|
+
id: "Hair",
|
|
216
|
+
label: configuredHair?.label || "Hair",
|
|
217
|
+
kind: "hair",
|
|
218
|
+
order: getOrder("Hair"),
|
|
219
|
+
meshCategory: configuredHair?.meshCategory || "hair"
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const configuredUnmapped = configuredById.get("Unmapped");
|
|
223
|
+
sections.set("Unmapped", {
|
|
224
|
+
...configuredUnmapped,
|
|
225
|
+
id: "Unmapped",
|
|
226
|
+
label: configuredUnmapped?.label || "Unmapped",
|
|
227
|
+
kind: "unmapped",
|
|
228
|
+
order: getOrder("Unmapped"),
|
|
229
|
+
meshCategory: configuredUnmapped?.meshCategory || "face"
|
|
230
|
+
});
|
|
231
|
+
const candidates = morphNames.map((morph) => {
|
|
232
|
+
const matches = classifyVisemeMorph(morph, profile);
|
|
233
|
+
if (matches.length === 0) {
|
|
234
|
+
return { morph, sectionId: "Unmapped", kind: "unmapped", matches };
|
|
235
|
+
}
|
|
236
|
+
const explicit = matches.filter((match) => match.reason === "explicit");
|
|
237
|
+
if (explicit.length > 0) {
|
|
238
|
+
return { morph, sectionId: "Visemes", kind: "explicit", matches: explicit };
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
morph,
|
|
242
|
+
sectionId: "Visemes",
|
|
243
|
+
kind: matches.length > 1 ? "conflict" : "candidate",
|
|
244
|
+
matches
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
return {
|
|
248
|
+
sections: Array.from(sections.values()).sort((a, b) => a.order - b.order || a.label.localeCompare(b.label)),
|
|
249
|
+
candidates
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function mapProviderVisemeToSlot(profile, event) {
|
|
253
|
+
const slots = getProfileVisemeSlots(profile);
|
|
254
|
+
const provider = event.provider.toLowerCase();
|
|
255
|
+
if (event.id !== void 0) {
|
|
256
|
+
const id = String(event.id);
|
|
257
|
+
const index = slots.findIndex(
|
|
258
|
+
(slot) => (slot.providerIds?.[provider] || []).some((candidate) => String(candidate) === id)
|
|
259
|
+
);
|
|
260
|
+
if (index >= 0) {
|
|
261
|
+
return { slotId: slots[index].id, index, confidence: 1, reason: "provider" };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (event.phoneme) {
|
|
265
|
+
const phoneme = event.phoneme.toLowerCase();
|
|
266
|
+
const index = slots.findIndex(
|
|
267
|
+
(slot) => (slot.phonemes || []).some((candidate) => candidate.toLowerCase() === phoneme)
|
|
268
|
+
);
|
|
269
|
+
if (index >= 0) {
|
|
270
|
+
return { slotId: slots[index].id, index, confidence: 0.8, reason: "phoneme" };
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const restIndex = slots.findIndex((slot) => slot.id === "rest" || slot.features?.lipClosed === 1);
|
|
274
|
+
if (restIndex >= 0) {
|
|
275
|
+
return { slotId: slots[restIndex].id, index: restIndex, confidence: 0.25, reason: "rest" };
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
|
|
63
280
|
// src/engines/three/balanceUtils.ts
|
|
64
281
|
function clampBalance(value) {
|
|
65
282
|
if (!Number.isFinite(value)) return 0;
|
|
@@ -670,12 +887,7 @@ var BakedAnimationController = class {
|
|
|
670
887
|
if (typeof this.host.getMeshNamesForAU === "function") {
|
|
671
888
|
return this.host.getMeshNamesForAU(auId) || [];
|
|
672
889
|
}
|
|
673
|
-
|
|
674
|
-
if (facePart) {
|
|
675
|
-
const category = config.auFacePartToMeshCategory?.[facePart];
|
|
676
|
-
if (category) return config.morphToMesh?.[category] || [];
|
|
677
|
-
}
|
|
678
|
-
return config.morphToMesh?.face || [];
|
|
890
|
+
return getMeshNamesForAUProfile(config, auId);
|
|
679
891
|
}
|
|
680
892
|
getMeshNamesForViseme(config, explicitMeshNames) {
|
|
681
893
|
if (explicitMeshNames && explicitMeshNames.length > 0) {
|
|
@@ -684,10 +896,7 @@ var BakedAnimationController = class {
|
|
|
684
896
|
if (typeof this.host.getMeshNamesForViseme === "function") {
|
|
685
897
|
return this.host.getMeshNamesForViseme() || [];
|
|
686
898
|
}
|
|
687
|
-
|
|
688
|
-
const visemeMeshes = config.morphToMesh?.[category];
|
|
689
|
-
if (visemeMeshes && visemeMeshes.length > 0) return visemeMeshes;
|
|
690
|
-
return config.morphToMesh?.face || [];
|
|
899
|
+
return getMeshNamesForVisemeProfile(config);
|
|
691
900
|
}
|
|
692
901
|
update(dtSeconds) {
|
|
693
902
|
if (this.animationMixer) {
|
|
@@ -1740,7 +1949,7 @@ var BakedAnimationController = class {
|
|
|
1740
1949
|
}
|
|
1741
1950
|
addMorphTracks(tracks, morphKey, keyframes, intensityScale, meshNames) {
|
|
1742
1951
|
const config = this.host.getConfig();
|
|
1743
|
-
const hasExplicitMeshes =
|
|
1952
|
+
const hasExplicitMeshes = meshNames !== void 0;
|
|
1744
1953
|
const targetMeshNames = hasExplicitMeshes ? meshNames : config.morphToMesh?.face || [];
|
|
1745
1954
|
const targetMeshes = targetMeshNames.length ? targetMeshNames.map((name) => this.host.getMeshByName(name)).filter(Boolean) : [];
|
|
1746
1955
|
const addTrackForMesh = (mesh) => {
|
|
@@ -1764,7 +1973,7 @@ var BakedAnimationController = class {
|
|
|
1764
1973
|
addMorphIndexTracks(tracks, morphIndex, keyframes, intensityScale, meshNames) {
|
|
1765
1974
|
if (!Number.isInteger(morphIndex) || morphIndex < 0) return;
|
|
1766
1975
|
const config = this.host.getConfig();
|
|
1767
|
-
const hasExplicitMeshes =
|
|
1976
|
+
const hasExplicitMeshes = meshNames !== void 0;
|
|
1768
1977
|
const targetMeshNames = hasExplicitMeshes ? meshNames : config.morphToMesh?.face || [];
|
|
1769
1978
|
const targetMeshes = targetMeshNames.length ? targetMeshNames.map((name) => this.host.getMeshByName(name)).filter(Boolean) : [];
|
|
1770
1979
|
const addTrackForMesh = (mesh) => {
|
|
@@ -2398,6 +2607,159 @@ var VISEME_JAW_AMOUNTS = [
|
|
|
2398
2607
|
0.5
|
|
2399
2608
|
// 14: W_OO
|
|
2400
2609
|
];
|
|
2610
|
+
var CC4_VISEME_SYSTEM_ID = "cc4-arkit-15";
|
|
2611
|
+
var CC4_VISEME_SLOTS = [
|
|
2612
|
+
{
|
|
2613
|
+
id: "ae",
|
|
2614
|
+
label: "AE",
|
|
2615
|
+
order: 0,
|
|
2616
|
+
providerIds: { azure: [4], sapi: [4] },
|
|
2617
|
+
phonemes: ["AE", "EH", "EY", "UH"],
|
|
2618
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(ae|eh|ey)([_ .-]|$)"],
|
|
2619
|
+
features: { jawOpen: 0.75, lipSpread: 0.35 },
|
|
2620
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[0]
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
id: "ah",
|
|
2624
|
+
label: "Ah",
|
|
2625
|
+
order: 1,
|
|
2626
|
+
providerIds: { azure: [1, 2, 9, 11, 12], sapi: [1, 2, 9, 11, 12] },
|
|
2627
|
+
phonemes: ["AA", "AE", "AH", "AX", "AW", "AY", "HH"],
|
|
2628
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(ah|aa|aah|open)([_ .-]|$)"],
|
|
2629
|
+
features: { jawOpen: 0.8 },
|
|
2630
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[1]
|
|
2631
|
+
},
|
|
2632
|
+
{
|
|
2633
|
+
id: "b-m-p",
|
|
2634
|
+
label: "B_M_P",
|
|
2635
|
+
order: 2,
|
|
2636
|
+
providerIds: { azure: [0, 21], sapi: [0, 21] },
|
|
2637
|
+
phonemes: ["B", "M", "P"],
|
|
2638
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(b[_ .-]?m[_ .-]?p|bmp|closed|sil|rest)([_ .-]|$)"],
|
|
2639
|
+
features: { jawOpen: 0, lipClosed: 1 },
|
|
2640
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[2]
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
id: "ch-j",
|
|
2644
|
+
label: "Ch_J",
|
|
2645
|
+
order: 3,
|
|
2646
|
+
providerIds: { azure: [16], sapi: [16] },
|
|
2647
|
+
phonemes: ["CH", "JH", "SH", "ZH"],
|
|
2648
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(ch|j|sh|zh)([_ .-]|$)"],
|
|
2649
|
+
features: { jawOpen: 0.3, fricative: 0.6 },
|
|
2650
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[3]
|
|
2651
|
+
},
|
|
2652
|
+
{
|
|
2653
|
+
id: "ee",
|
|
2654
|
+
label: "EE",
|
|
2655
|
+
order: 4,
|
|
2656
|
+
providerIds: { azure: [6], sapi: [6] },
|
|
2657
|
+
phonemes: ["IY", "IH", "IX", "Y"],
|
|
2658
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(ee|iy|y)([_ .-]|$)"],
|
|
2659
|
+
features: { jawOpen: 0.2, lipSpread: 0.8 },
|
|
2660
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[4]
|
|
2661
|
+
},
|
|
2662
|
+
{
|
|
2663
|
+
id: "er",
|
|
2664
|
+
label: "Er",
|
|
2665
|
+
order: 5,
|
|
2666
|
+
providerIds: { azure: [5], sapi: [5] },
|
|
2667
|
+
phonemes: ["ER"],
|
|
2668
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(er)([_ .-]|$)"],
|
|
2669
|
+
features: { jawOpen: 0.35, lipRound: 0.35 },
|
|
2670
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[5]
|
|
2671
|
+
},
|
|
2672
|
+
{
|
|
2673
|
+
id: "f-v",
|
|
2674
|
+
label: "F_V",
|
|
2675
|
+
order: 6,
|
|
2676
|
+
providerIds: { azure: [18], sapi: [18] },
|
|
2677
|
+
phonemes: ["F", "V"],
|
|
2678
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(f[_ .-]?v|fv)([_ .-]|$)"],
|
|
2679
|
+
features: { jawOpen: 0.1, fricative: 1 },
|
|
2680
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[6]
|
|
2681
|
+
},
|
|
2682
|
+
{
|
|
2683
|
+
id: "ih",
|
|
2684
|
+
label: "Ih",
|
|
2685
|
+
order: 7,
|
|
2686
|
+
providerIds: { azure: [6], sapi: [6] },
|
|
2687
|
+
phonemes: ["IH", "IX"],
|
|
2688
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(ih|ix)([_ .-]|$)"],
|
|
2689
|
+
features: { jawOpen: 0.2, lipSpread: 0.55 },
|
|
2690
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[7]
|
|
2691
|
+
},
|
|
2692
|
+
{
|
|
2693
|
+
id: "k-g-h-ng",
|
|
2694
|
+
label: "K_G_H_NG",
|
|
2695
|
+
order: 8,
|
|
2696
|
+
providerIds: { azure: [20], sapi: [20] },
|
|
2697
|
+
phonemes: ["K", "G", "NG"],
|
|
2698
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(k[_ .-]?g[_ .-]?h?[_ .-]?ng|kg|ng)([_ .-]|$)"],
|
|
2699
|
+
features: { jawOpen: 0.35 },
|
|
2700
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[8]
|
|
2701
|
+
},
|
|
2702
|
+
{
|
|
2703
|
+
id: "oh",
|
|
2704
|
+
label: "Oh",
|
|
2705
|
+
order: 9,
|
|
2706
|
+
providerIds: { azure: [3, 8, 10], sapi: [3, 8, 10] },
|
|
2707
|
+
phonemes: ["AO", "OW", "OY"],
|
|
2708
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(oh|ao|ow|oy)([_ .-]|$)"],
|
|
2709
|
+
features: { jawOpen: 0.6, lipRound: 0.8 },
|
|
2710
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[9]
|
|
2711
|
+
},
|
|
2712
|
+
{
|
|
2713
|
+
id: "r",
|
|
2714
|
+
label: "R",
|
|
2715
|
+
order: 10,
|
|
2716
|
+
providerIds: { azure: [13], sapi: [13] },
|
|
2717
|
+
phonemes: ["R"],
|
|
2718
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(r)([_ .-]|$)"],
|
|
2719
|
+
features: { jawOpen: 0.35, lipRound: 0.5 },
|
|
2720
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[10]
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
id: "s-z",
|
|
2724
|
+
label: "S_Z",
|
|
2725
|
+
order: 11,
|
|
2726
|
+
providerIds: { azure: [15], sapi: [15] },
|
|
2727
|
+
phonemes: ["S", "Z"],
|
|
2728
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(s[_ .-]?z|sz)([_ .-]|$)"],
|
|
2729
|
+
features: { jawOpen: 0.1, fricative: 1 },
|
|
2730
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[11]
|
|
2731
|
+
},
|
|
2732
|
+
{
|
|
2733
|
+
id: "t-l-d-n",
|
|
2734
|
+
label: "T_L_D_N",
|
|
2735
|
+
order: 12,
|
|
2736
|
+
providerIds: { azure: [14, 19], sapi: [14, 19] },
|
|
2737
|
+
phonemes: ["T", "L", "D", "N"],
|
|
2738
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(t[_ .-]?l[_ .-]?d[_ .-]?n|tldn|l)([_ .-]|$)"],
|
|
2739
|
+
features: { jawOpen: 0.3, tongueTip: 1 },
|
|
2740
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[12]
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
id: "th",
|
|
2744
|
+
label: "Th",
|
|
2745
|
+
order: 13,
|
|
2746
|
+
providerIds: { azure: [17], sapi: [17] },
|
|
2747
|
+
phonemes: ["TH", "DH"],
|
|
2748
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(th|dh)([_ .-]|$)"],
|
|
2749
|
+
features: { jawOpen: 0.15, tongueTip: 0.8, fricative: 0.8 },
|
|
2750
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[13]
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
id: "w-oo",
|
|
2754
|
+
label: "W_OO",
|
|
2755
|
+
order: 14,
|
|
2756
|
+
providerIds: { azure: [7], sapi: [7] },
|
|
2757
|
+
phonemes: ["W", "UW"],
|
|
2758
|
+
matchers: ["(^|[_ .-])(v|viseme)?[_ .-]?(w[_ .-]?oo|woo|uw|oo)([_ .-]|$)"],
|
|
2759
|
+
features: { jawOpen: 0.5, lipRound: 1 },
|
|
2760
|
+
defaultJawAmount: VISEME_JAW_AMOUNTS[14]
|
|
2761
|
+
}
|
|
2762
|
+
];
|
|
2401
2763
|
var isMixedAU = (id) => {
|
|
2402
2764
|
const morphs = AU_TO_MORPHS[id];
|
|
2403
2765
|
const hasMorphs = !!(morphs?.left?.length || morphs?.right?.length || morphs?.center?.length);
|
|
@@ -2709,6 +3071,23 @@ var AU_FACEPART_TO_MESH_CATEGORY = {
|
|
|
2709
3071
|
Eyelids: "eye",
|
|
2710
3072
|
Tongue: "tongue"
|
|
2711
3073
|
};
|
|
3074
|
+
var CC4_MAPPING_SECTIONS = [
|
|
3075
|
+
{ id: "Forehead", label: "Forehead", kind: "au", order: 0, meshCategory: "face", facePart: "Forehead" },
|
|
3076
|
+
{ id: "Eyelids", label: "Eyelids", kind: "au", order: 1, meshCategory: "eye", facePart: "Eyelids" },
|
|
3077
|
+
{ id: "Eyes", label: "Eyes", kind: "au", order: 2, meshCategory: "eye", facePart: "Eyes" },
|
|
3078
|
+
{ id: "Cheeks", label: "Cheeks", kind: "au", order: 3, meshCategory: "face", facePart: "Cheeks" },
|
|
3079
|
+
{ id: "Nose", label: "Nose", kind: "au", order: 4, meshCategory: "face", facePart: "Nose" },
|
|
3080
|
+
{ id: "Mouth", label: "Mouth", kind: "au", order: 5, meshCategory: "face", facePart: "Mouth" },
|
|
3081
|
+
{ id: "Chin", label: "Chin", kind: "au", order: 6, meshCategory: "face", facePart: "Chin" },
|
|
3082
|
+
{ id: "Jaw", label: "Jaw", kind: "au", order: 7, meshCategory: "face", facePart: "Jaw" },
|
|
3083
|
+
{ id: "Tongue", label: "Tongue", kind: "au", order: 8, meshCategory: "tongue", facePart: "Tongue" },
|
|
3084
|
+
{ id: "Head", label: "Head", kind: "au", order: 9, meshCategory: "face", facePart: "Head" },
|
|
3085
|
+
{ id: "Joint Controls", label: "Joint Controls", kind: "au", order: 10, meshCategory: "face", facePart: "Joint Controls" },
|
|
3086
|
+
{ id: "Eye", label: "Eye", kind: "au", order: 11, meshCategory: "eye", facePart: "Eye" },
|
|
3087
|
+
{ id: "Hair", label: "Hair", kind: "hair", order: 12, meshCategory: "hair" },
|
|
3088
|
+
{ id: "Visemes", label: "Visemes", kind: "viseme", order: 13, meshCategory: "viseme" },
|
|
3089
|
+
{ id: "Unmapped", label: "Unmapped", kind: "unmapped", order: 14, meshCategory: "face" }
|
|
3090
|
+
];
|
|
2712
3091
|
var CC4_HAIR_PHYSICS = {
|
|
2713
3092
|
stiffness: 7.5,
|
|
2714
3093
|
damping: 0.18,
|
|
@@ -2755,7 +3134,10 @@ var CC4_PRESET = {
|
|
|
2755
3134
|
suffixPattern: CC4_SUFFIX_PATTERN,
|
|
2756
3135
|
morphToMesh: MORPH_TO_MESH,
|
|
2757
3136
|
auFacePartToMeshCategory: AU_FACEPART_TO_MESH_CATEGORY,
|
|
3137
|
+
mappingSections: CC4_MAPPING_SECTIONS,
|
|
2758
3138
|
visemeKeys: VISEME_KEYS,
|
|
3139
|
+
visemeSystemId: CC4_VISEME_SYSTEM_ID,
|
|
3140
|
+
visemeSlots: CC4_VISEME_SLOTS,
|
|
2759
3141
|
visemeMeshCategory: "viseme",
|
|
2760
3142
|
visemeJawAmounts: VISEME_JAW_AMOUNTS,
|
|
2761
3143
|
auMixDefaults: AU_MIX_DEFAULTS,
|
|
@@ -3573,7 +3955,7 @@ var mergeAnnotationRegion = (base, override) => {
|
|
|
3573
3955
|
merged.meshes = override.meshes ? [...override.meshes] : base.meshes ? [...base.meshes] : void 0;
|
|
3574
3956
|
merged.objects = override.objects ? [...override.objects] : base.objects ? [...base.objects] : void 0;
|
|
3575
3957
|
merged.children = override.children ? [...override.children] : base.children ? [...base.children] : void 0;
|
|
3576
|
-
merged.cameraOffset = override.cameraOffset ? { ...override.cameraOffset } : base.cameraOffset ? { ...base.cameraOffset } : void 0;
|
|
3958
|
+
merged.cameraOffset = override.cameraOffset ? { ...base.cameraOffset, ...override.cameraOffset } : base.cameraOffset ? { ...base.cameraOffset } : void 0;
|
|
3577
3959
|
merged.style = override.style ? {
|
|
3578
3960
|
...base.style,
|
|
3579
3961
|
...override.style,
|
|
@@ -3642,8 +4024,13 @@ function extendPresetWithProfile(base, extension) {
|
|
|
3642
4024
|
boneNodes: mergeRecord(base.boneNodes, extension.boneNodes),
|
|
3643
4025
|
morphToMesh: mergeRecord(base.morphToMesh, extension.morphToMesh),
|
|
3644
4026
|
auFacePartToMeshCategory: base.auFacePartToMeshCategory || extension.auFacePartToMeshCategory ? mergeRecord(base.auFacePartToMeshCategory || {}, extension.auFacePartToMeshCategory || {}) : void 0,
|
|
4027
|
+
mappingSections: extension.mappingSections ? [...extension.mappingSections] : base.mappingSections ? [...base.mappingSections] : void 0,
|
|
3645
4028
|
visemeKeys: extension.visemeKeys ? [...extension.visemeKeys] : [...base.visemeKeys],
|
|
4029
|
+
visemeSystemId: extension.visemeSystemId ?? base.visemeSystemId,
|
|
4030
|
+
visemeSlots: extension.visemeSlots ? [...extension.visemeSlots] : base.visemeSlots ? [...base.visemeSlots] : void 0,
|
|
4031
|
+
visemeBindings: base.visemeBindings || extension.visemeBindings ? mergeRecord(base.visemeBindings || {}, extension.visemeBindings || {}) : void 0,
|
|
3646
4032
|
visemeMeshCategory: extension.visemeMeshCategory ?? base.visemeMeshCategory,
|
|
4033
|
+
visemeJawAmounts: extension.visemeJawAmounts ? [...extension.visemeJawAmounts] : base.visemeJawAmounts ? [...base.visemeJawAmounts] : void 0,
|
|
3647
4034
|
auMixDefaults: base.auMixDefaults || extension.auMixDefaults ? mergeRecord(base.auMixDefaults || {}, extension.auMixDefaults || {}) : void 0,
|
|
3648
4035
|
auInfo: base.auInfo || extension.auInfo ? mergeRecord(base.auInfo || {}, extension.auInfo || {}) : void 0,
|
|
3649
4036
|
eyeMeshNodes: extension.eyeMeshNodes ?? base.eyeMeshNodes,
|
|
@@ -5209,6 +5596,21 @@ var _Loom3 = class _Loom3 {
|
|
|
5209
5596
|
const jawHandle = this.transitionBoneRotation("JAW", "pitch", jawAmount, durationMs);
|
|
5210
5597
|
return this.combineHandles([morphHandle, jawHandle]);
|
|
5211
5598
|
}
|
|
5599
|
+
setVisemeById(slotId, value, jawScale = 1) {
|
|
5600
|
+
const index = getVisemeSlotIndex(this.config, slotId);
|
|
5601
|
+
if (index < 0) return;
|
|
5602
|
+
this.setViseme(index, value, jawScale);
|
|
5603
|
+
}
|
|
5604
|
+
transitionVisemeById(slotId, to, durationMs = 80, jawScale = 1) {
|
|
5605
|
+
const index = getVisemeSlotIndex(this.config, slotId);
|
|
5606
|
+
if (index < 0) {
|
|
5607
|
+
return { promise: Promise.resolve(), pause: () => {
|
|
5608
|
+
}, resume: () => {
|
|
5609
|
+
}, cancel: () => {
|
|
5610
|
+
} };
|
|
5611
|
+
}
|
|
5612
|
+
return this.transitionViseme(index, to, durationMs, jawScale);
|
|
5613
|
+
}
|
|
5212
5614
|
// ============================================================================
|
|
5213
5615
|
// MIX WEIGHT CONTROL
|
|
5214
5616
|
// ============================================================================
|
|
@@ -5554,21 +5956,10 @@ var _Loom3 = class _Loom3 {
|
|
|
5554
5956
|
* Routing is driven by `auFacePartToMeshCategory` in profile config.
|
|
5555
5957
|
*/
|
|
5556
5958
|
getMeshNamesForAU(auId) {
|
|
5557
|
-
|
|
5558
|
-
const info = this.config.auInfo?.[String(auId)];
|
|
5559
|
-
const facePart = info?.facePart;
|
|
5560
|
-
if (facePart) {
|
|
5561
|
-
const category = this.config.auFacePartToMeshCategory?.[facePart];
|
|
5562
|
-
if (category) {
|
|
5563
|
-
return m?.[category] || [];
|
|
5564
|
-
}
|
|
5565
|
-
}
|
|
5566
|
-
return m?.face || [];
|
|
5959
|
+
return getMeshNamesForAUProfile(this.config, auId);
|
|
5567
5960
|
}
|
|
5568
5961
|
getMeshNamesForViseme() {
|
|
5569
|
-
|
|
5570
|
-
const category = this.config.visemeMeshCategory || (m?.viseme ? "viseme" : "face");
|
|
5571
|
-
return m?.[category] || m?.face || [];
|
|
5962
|
+
return getMeshNamesForVisemeProfile(this.config);
|
|
5572
5963
|
}
|
|
5573
5964
|
// ============================================================================
|
|
5574
5965
|
// HAIR PHYSICS
|
|
@@ -5836,7 +6227,7 @@ var _Loom3 = class _Loom3 {
|
|
|
5836
6227
|
);
|
|
5837
6228
|
}
|
|
5838
6229
|
getVisemeJawAmount(visemeIndex) {
|
|
5839
|
-
return this.config.visemeJawAmounts?.[visemeIndex] ?? _Loom3.VISEME_JAW_AMOUNTS[visemeIndex] ?? 0;
|
|
6230
|
+
return getVisemeJawAmounts(this.config)?.[visemeIndex] ?? this.config.visemeJawAmounts?.[visemeIndex] ?? _Loom3.VISEME_JAW_AMOUNTS[visemeIndex] ?? 0;
|
|
5840
6231
|
}
|
|
5841
6232
|
collectResolvedExpressionMorphTargets() {
|
|
5842
6233
|
const targets = [];
|
|
@@ -6314,7 +6705,11 @@ var PROFILE_OVERRIDE_KEYS = [
|
|
|
6314
6705
|
"rightMorphSuffixes",
|
|
6315
6706
|
"morphToMesh",
|
|
6316
6707
|
"auFacePartToMeshCategory",
|
|
6708
|
+
"mappingSections",
|
|
6317
6709
|
"visemeKeys",
|
|
6710
|
+
"visemeSystemId",
|
|
6711
|
+
"visemeSlots",
|
|
6712
|
+
"visemeBindings",
|
|
6318
6713
|
"visemeMeshCategory",
|
|
6319
6714
|
"visemeJawAmounts",
|
|
6320
6715
|
"auMixDefaults",
|
|
@@ -6412,22 +6807,32 @@ function mergeRegionsByName(base, override) {
|
|
|
6412
6807
|
}
|
|
6413
6808
|
return Array.from(merged.values());
|
|
6414
6809
|
}
|
|
6810
|
+
function getAnnotationRegions(value) {
|
|
6811
|
+
return Array.isArray(value) ? value : void 0;
|
|
6812
|
+
}
|
|
6813
|
+
function getLegacyNestedOverrides(config) {
|
|
6814
|
+
return isPlainObject2(config.profile) ? config.profile : {};
|
|
6815
|
+
}
|
|
6816
|
+
function getLegacyRuntimeRegions(config) {
|
|
6817
|
+
return Array.isArray(config.regions) && config.regions.length > 0 ? config.regions : void 0;
|
|
6818
|
+
}
|
|
6819
|
+
function getCanonicalAnnotationOverrides(config) {
|
|
6820
|
+
return mergeRegionsByName(
|
|
6821
|
+
getAnnotationRegions(getLegacyNestedOverrides(config).annotationRegions),
|
|
6822
|
+
getAnnotationRegions(config.annotationRegions)
|
|
6823
|
+
);
|
|
6824
|
+
}
|
|
6415
6825
|
function extractProfileOverrides(config) {
|
|
6416
6826
|
const topLevelConfig = config;
|
|
6417
|
-
const legacyNestedOverrides =
|
|
6827
|
+
const legacyNestedOverrides = getLegacyNestedOverrides(config);
|
|
6828
|
+
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
6829
|
+
const legacyRuntimeRegions = getLegacyRuntimeRegions(config);
|
|
6830
|
+
const annotationOverrides = canonicalAnnotationOverrides ?? (legacyRuntimeRegions ? legacyRuntimeRegions.map((region) => cloneRegion(region)) : void 0);
|
|
6418
6831
|
const overrides = {};
|
|
6419
6832
|
for (const key of PROFILE_OVERRIDE_KEYS) {
|
|
6420
6833
|
if (key === "annotationRegions") {
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
const legacyRegionFallback = Array.isArray(config.regions) && config.regions.length > 0 ? config.regions : void 0;
|
|
6424
|
-
const legacyProfileRegions = mergeRegionsByName(legacyRegionFallback, legacyAnnotationRegions);
|
|
6425
|
-
const regions = mergeRegionsByName(
|
|
6426
|
-
legacyProfileRegions,
|
|
6427
|
-
topLevelAnnotationRegions
|
|
6428
|
-
);
|
|
6429
|
-
if (regions) {
|
|
6430
|
-
overrides.annotationRegions = regions.map((region) => cloneRegion(region));
|
|
6834
|
+
if (annotationOverrides) {
|
|
6835
|
+
overrides.annotationRegions = annotationOverrides.map((region) => cloneRegion(region));
|
|
6431
6836
|
}
|
|
6432
6837
|
continue;
|
|
6433
6838
|
}
|
|
@@ -6440,13 +6845,6 @@ function extractProfileOverrides(config) {
|
|
|
6440
6845
|
}
|
|
6441
6846
|
return overrides;
|
|
6442
6847
|
}
|
|
6443
|
-
function hasCanonicalAnnotationRegionOverrides(config) {
|
|
6444
|
-
const topLevelConfig = config;
|
|
6445
|
-
if (Array.isArray(topLevelConfig.annotationRegions)) {
|
|
6446
|
-
return true;
|
|
6447
|
-
}
|
|
6448
|
-
return isPlainObject2(config.profile) && Array.isArray(config.profile.annotationRegions);
|
|
6449
|
-
}
|
|
6450
6848
|
function applyCharacterProfileToPreset(config) {
|
|
6451
6849
|
const presetType = config.auPresetType;
|
|
6452
6850
|
if (!presetType) {
|
|
@@ -6478,24 +6876,34 @@ function extendCharacterConfigWithPreset(config) {
|
|
|
6478
6876
|
if (!presetType || presetType === "custom") {
|
|
6479
6877
|
return config;
|
|
6480
6878
|
}
|
|
6879
|
+
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
6880
|
+
const legacyRuntimeRegions = getLegacyRuntimeRegions(config);
|
|
6481
6881
|
const profileOverrides = extractProfileOverrides(config);
|
|
6482
6882
|
const extendedPresetProfile = applyCharacterProfileToPreset(config);
|
|
6483
6883
|
if (!extendedPresetProfile) {
|
|
6484
6884
|
return config;
|
|
6485
6885
|
}
|
|
6486
|
-
const
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6886
|
+
const presetRegionNames = new Set(
|
|
6887
|
+
(getPreset(presetType).annotationRegions ?? []).map((region) => region.name)
|
|
6888
|
+
);
|
|
6889
|
+
const extendedAnnotationRegions = normalizeRegionTree(
|
|
6890
|
+
extendedPresetProfile.annotationRegions,
|
|
6891
|
+
profileOverrides.disabledRegions
|
|
6892
|
+
);
|
|
6893
|
+
const extendedRegionNames = new Set((extendedAnnotationRegions ?? []).map((region) => region.name));
|
|
6894
|
+
const legacyExtraRegions = canonicalAnnotationOverrides && legacyRuntimeRegions ? legacyRuntimeRegions.filter((region) => !presetRegionNames.has(region.name) && !extendedRegionNames.has(region.name)).map((region) => cloneRegion(region)) : void 0;
|
|
6895
|
+
const mergedRegions = normalizeRegionTree(
|
|
6896
|
+
mergeRegionsByName(extendedAnnotationRegions, legacyExtraRegions),
|
|
6490
6897
|
profileOverrides.disabledRegions
|
|
6491
6898
|
);
|
|
6492
6899
|
const extendedRegions = orderExtendedRegions(
|
|
6493
|
-
|
|
6494
|
-
[
|
|
6900
|
+
mergedRegions,
|
|
6901
|
+
canonicalAnnotationOverrides ? [extendedAnnotationRegions, legacyExtraRegions] : [legacyRuntimeRegions, extendedAnnotationRegions]
|
|
6495
6902
|
);
|
|
6496
6903
|
return {
|
|
6497
6904
|
...config,
|
|
6498
6905
|
...extendedPresetProfile,
|
|
6906
|
+
annotationRegions: extendedRegions ?? extendedAnnotationRegions,
|
|
6499
6907
|
regions: extendedRegions ?? config.regions
|
|
6500
6908
|
};
|
|
6501
6909
|
}
|
|
@@ -7401,6 +7809,33 @@ function validateMappingConfig(config) {
|
|
|
7401
7809
|
}
|
|
7402
7810
|
visemeSeen.add(key);
|
|
7403
7811
|
}
|
|
7812
|
+
const morphCategories = new Set(Object.keys(config.morphToMesh || {}));
|
|
7813
|
+
if (config.visemeMeshCategory && !morphCategories.has(config.visemeMeshCategory)) {
|
|
7814
|
+
push(
|
|
7815
|
+
"error",
|
|
7816
|
+
"VISEME_MESH_CATEGORY_MISSING",
|
|
7817
|
+
`visemeMeshCategory "${config.visemeMeshCategory}" is not present in morphToMesh`,
|
|
7818
|
+
{ category: config.visemeMeshCategory }
|
|
7819
|
+
);
|
|
7820
|
+
}
|
|
7821
|
+
for (const [facePart, category] of Object.entries(config.auFacePartToMeshCategory || {})) {
|
|
7822
|
+
if (!morphCategories.has(category)) {
|
|
7823
|
+
push(
|
|
7824
|
+
"error",
|
|
7825
|
+
"AU_MESH_CATEGORY_MISSING",
|
|
7826
|
+
`AU facePart "${facePart}" routes to missing morphToMesh category "${category}"`,
|
|
7827
|
+
{ facePart, category }
|
|
7828
|
+
);
|
|
7829
|
+
}
|
|
7830
|
+
}
|
|
7831
|
+
if (config.visemeJawAmounts && config.visemeJawAmounts.length !== (config.visemeKeys || []).length) {
|
|
7832
|
+
push(
|
|
7833
|
+
"warning",
|
|
7834
|
+
"VISEME_JAW_AMOUNT_LENGTH_MISMATCH",
|
|
7835
|
+
"visemeJawAmounts length does not match visemeKeys length",
|
|
7836
|
+
{ visemeKeys: (config.visemeKeys || []).length, visemeJawAmounts: config.visemeJawAmounts.length }
|
|
7837
|
+
);
|
|
7838
|
+
}
|
|
7404
7839
|
if (config.auMixDefaults) {
|
|
7405
7840
|
for (const key of Object.keys(config.auMixDefaults)) {
|
|
7406
7841
|
const auId = Number(key);
|
|
@@ -7865,9 +8300,12 @@ exports.BONE_AU_TO_BINDINGS = BONE_AU_TO_BINDINGS;
|
|
|
7865
8300
|
exports.CC4_BONE_NODES = CC4_BONE_NODES;
|
|
7866
8301
|
exports.CC4_BONE_PREFIX = CC4_BONE_PREFIX;
|
|
7867
8302
|
exports.CC4_EYE_MESH_NODES = CC4_EYE_MESH_NODES;
|
|
8303
|
+
exports.CC4_MAPPING_SECTIONS = CC4_MAPPING_SECTIONS;
|
|
7868
8304
|
exports.CC4_MESHES = CC4_MESHES;
|
|
7869
8305
|
exports.CC4_PRESET = CC4_PRESET;
|
|
7870
8306
|
exports.CC4_SUFFIX_PATTERN = CC4_SUFFIX_PATTERN;
|
|
8307
|
+
exports.CC4_VISEME_SLOTS = CC4_VISEME_SLOTS;
|
|
8308
|
+
exports.CC4_VISEME_SYSTEM_ID = CC4_VISEME_SYSTEM_ID;
|
|
7871
8309
|
exports.COMPOSITE_ROTATIONS = COMPOSITE_ROTATIONS;
|
|
7872
8310
|
exports.CONTINUUM_LABELS = CONTINUUM_LABELS;
|
|
7873
8311
|
exports.CONTINUUM_PAIRS_MAP = CONTINUUM_PAIRS_MAP;
|
|
@@ -7882,7 +8320,9 @@ exports.VISEME_JAW_AMOUNTS = VISEME_JAW_AMOUNTS;
|
|
|
7882
8320
|
exports.VISEME_KEYS = VISEME_KEYS;
|
|
7883
8321
|
exports.analyzeModel = analyzeModel;
|
|
7884
8322
|
exports.applyCharacterProfileToPreset = applyCharacterProfileToPreset;
|
|
8323
|
+
exports.buildMappingEditorModel = buildMappingEditorModel;
|
|
7885
8324
|
exports.collectMorphMeshes = collectMorphMeshes;
|
|
8325
|
+
exports.compileVisemeKeys = compileVisemeKeys;
|
|
7886
8326
|
exports.computeCameraRelativeGazeOffset = computeCameraRelativeGazeOffset;
|
|
7887
8327
|
exports.detectFacingDirection = detectFacingDirection;
|
|
7888
8328
|
exports.extendCharacterConfigWithPreset = extendCharacterConfigWithPreset;
|
|
@@ -7893,18 +8333,25 @@ exports.extractProfileOverrides = extractProfileOverrides;
|
|
|
7893
8333
|
exports.findFaceCenter = findFaceCenter;
|
|
7894
8334
|
exports.fuzzyNameMatch = fuzzyNameMatch;
|
|
7895
8335
|
exports.generateMappingCorrections = generateMappingCorrections;
|
|
8336
|
+
exports.getMeshNamesForAUProfile = getMeshNamesForAUProfile;
|
|
8337
|
+
exports.getMeshNamesForVisemeProfile = getMeshNamesForVisemeProfile;
|
|
7896
8338
|
exports.getModelForwardDirection = getModelForwardDirection;
|
|
7897
8339
|
exports.getPreset = getPreset;
|
|
7898
8340
|
exports.getPresetWithProfile = getPresetWithProfile;
|
|
8341
|
+
exports.getProfileVisemeSlots = getProfileVisemeSlots;
|
|
8342
|
+
exports.getVisemeJawAmounts = getVisemeJawAmounts;
|
|
8343
|
+
exports.getVisemeSlotIndex = getVisemeSlotIndex;
|
|
7899
8344
|
exports.hasLeftRightMorphs = hasLeftRightMorphs;
|
|
7900
8345
|
exports.isMixedAU = isMixedAU;
|
|
7901
8346
|
exports.isPresetCompatible = isPresetCompatible;
|
|
8347
|
+
exports.mapProviderVisemeToSlot = mapProviderVisemeToSlot;
|
|
7902
8348
|
exports.mergeCharacterRegionsByName = mergeRegionsByName;
|
|
7903
8349
|
exports.resolveBoneName = resolveBoneName;
|
|
7904
8350
|
exports.resolveBoneNames = resolveBoneNames;
|
|
7905
8351
|
exports.resolveFaceCenter = resolveFaceCenter;
|
|
7906
8352
|
exports.resolvePreset = resolvePreset;
|
|
7907
8353
|
exports.resolvePresetWithOverrides = resolvePresetWithOverrides;
|
|
8354
|
+
exports.resolveVisemeMeshCategory = resolveVisemeMeshCategory;
|
|
7908
8355
|
exports.suggestBestPreset = suggestBestPreset;
|
|
7909
8356
|
exports.validateMappingConfig = validateMappingConfig;
|
|
7910
8357
|
exports.validateMappings = validateMappings;
|