@lovelace_lol/loom3 1.0.43 → 1.0.45
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 +16 -15
- package/dist/index.cjs +130 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +246 -212
- package/dist/index.d.ts +246 -212
- package/dist/index.js +125 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -350,15 +350,20 @@ const loom = new Loom3({
|
|
|
350
350
|
|
|
351
351
|
`annotationRegions` is the Loom3 field for camera/marker region defaults and profile overrides.
|
|
352
352
|
|
|
353
|
-
If your app fetches a
|
|
353
|
+
If your app fetches a saved model/profile record from Firestore or another backend, use `extendProfileConfigWithPreset(...)` to build the runtime shape before handing that profile config to camera/marker tooling:
|
|
354
354
|
|
|
355
355
|
```typescript
|
|
356
|
-
import {
|
|
356
|
+
import { extendProfileConfigWithPreset } from '@lovelace_lol/loom3';
|
|
357
357
|
|
|
358
|
-
const savedConfig = await
|
|
359
|
-
const runtimeConfig =
|
|
358
|
+
const savedConfig = await fetchProfileConfig();
|
|
359
|
+
const runtimeConfig = extendProfileConfigWithPreset({
|
|
360
|
+
...savedConfig,
|
|
361
|
+
profilePresetId: savedConfig.profilePresetId ?? 'cc4',
|
|
362
|
+
});
|
|
360
363
|
```
|
|
361
364
|
|
|
365
|
+
`CharacterConfig`, `auPresetType`, and `extendCharacterConfigWithPreset(...)` are still exported as deprecated compatibility aliases for apps migrating from older LoomLarge-style character records. New Loom3 integrations should model presets as base profiles, pass profile overrides through `profile`, `annotationRegions`, or other `Profile` fields, and use `profilePresetId` for preset selection.
|
|
366
|
+
|
|
362
367
|
For the current runtime-oriented documentation, including:
|
|
363
368
|
|
|
364
369
|
- `paddingFactor`
|
|
@@ -2091,7 +2096,7 @@ console.log(result.center, result.method, result.debugInfo);
|
|
|
2091
2096
|
### Resolving region-driven centers
|
|
2092
2097
|
|
|
2093
2098
|
```typescript
|
|
2094
|
-
import type {
|
|
2099
|
+
import type { BoneResolutionProfile, Region } from '@lovelace_lol/loom3';
|
|
2095
2100
|
import { resolveBoneName, resolveBoneNames, resolveFaceCenter } from '@lovelace_lol/loom3';
|
|
2096
2101
|
|
|
2097
2102
|
const region: Region = {
|
|
@@ -2100,18 +2105,14 @@ const region: Region = {
|
|
|
2100
2105
|
meshes: ['CC_Base_Body'],
|
|
2101
2106
|
};
|
|
2102
2107
|
|
|
2103
|
-
const
|
|
2104
|
-
characterId: 'demo',
|
|
2105
|
-
characterName: 'Demo',
|
|
2106
|
-
modelPath: '/demo.glb',
|
|
2107
|
-
regions: [region],
|
|
2108
|
+
const profile: BoneResolutionProfile = {
|
|
2108
2109
|
bonePrefix: 'CC_Base_',
|
|
2109
2110
|
boneNodes: { HEAD: 'Head' },
|
|
2110
|
-
}
|
|
2111
|
+
};
|
|
2111
2112
|
|
|
2112
|
-
const headBone = resolveBoneName('HEAD',
|
|
2113
|
-
const resolvedBones = resolveBoneNames(['HEAD'],
|
|
2114
|
-
const faceCenter = resolveFaceCenter(gltf.scene, region,
|
|
2113
|
+
const headBone = resolveBoneName('HEAD', profile);
|
|
2114
|
+
const resolvedBones = resolveBoneNames(['HEAD'], profile);
|
|
2115
|
+
const faceCenter = resolveFaceCenter(gltf.scene, region, profile);
|
|
2115
2116
|
```
|
|
2116
2117
|
|
|
2117
2118
|
### Working with model orientation
|
|
@@ -2128,7 +2129,7 @@ const facing = detectFacingDirection(gltf.scene);
|
|
|
2128
2129
|
|
|
2129
2130
|
Use these helpers when you need to:
|
|
2130
2131
|
- place annotation markers using semantic regions instead of hard-coded coordinates
|
|
2131
|
-
- resolve prefixed/suffixed bone names from a reusable
|
|
2132
|
+
- resolve prefixed/suffixed bone names from a reusable profile or minimal bone-resolution object
|
|
2132
2133
|
- derive a face anchor for camera tooling or interaction layers
|
|
2133
2134
|
- reason about model orientation before building your own camera or annotation system
|
|
2134
2135
|
|
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,9 @@ function bindingTargets(binding) {
|
|
|
74
74
|
if (targets && targets.length > 0) return targets;
|
|
75
75
|
return binding.morph !== void 0 && binding.morph !== "" ? [binding.morph] : [];
|
|
76
76
|
}
|
|
77
|
+
function normalizeBindingWeight(weight) {
|
|
78
|
+
return Number.isFinite(weight) ? Math.max(0, weight ?? 1) : 1;
|
|
79
|
+
}
|
|
77
80
|
function getProfileVisemeSlots(profile) {
|
|
78
81
|
if (profile.visemeSlots && profile.visemeSlots.length > 0) {
|
|
79
82
|
return [...profile.visemeSlots].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
@@ -99,6 +102,23 @@ function compileVisemeKeys(profile) {
|
|
|
99
102
|
return target ?? profile.visemeKeys?.[index] ?? "";
|
|
100
103
|
});
|
|
101
104
|
}
|
|
105
|
+
function getVisemeBindingTargets(profile, visemeIndex) {
|
|
106
|
+
const slots = getProfileVisemeSlots(profile);
|
|
107
|
+
const slot = slots[visemeIndex];
|
|
108
|
+
const binding = slot ? profile.visemeBindings?.[slot.id] : void 0;
|
|
109
|
+
const boundTargets = binding?.targets?.filter((target) => target.morph !== void 0 && target.morph !== "").map((target) => ({
|
|
110
|
+
morph: target.morph,
|
|
111
|
+
weight: normalizeBindingWeight(target.weight)
|
|
112
|
+
}));
|
|
113
|
+
if (boundTargets && boundTargets.length > 0) {
|
|
114
|
+
return boundTargets;
|
|
115
|
+
}
|
|
116
|
+
if (binding?.morph !== void 0 && binding.morph !== "") {
|
|
117
|
+
return [{ morph: binding.morph, weight: 1 }];
|
|
118
|
+
}
|
|
119
|
+
const legacyTarget = profile.visemeKeys?.[visemeIndex];
|
|
120
|
+
return legacyTarget !== void 0 && legacyTarget !== "" ? [{ morph: legacyTarget, weight: 1 }] : [];
|
|
121
|
+
}
|
|
102
122
|
function getVisemeJawAmounts(profile) {
|
|
103
123
|
const slots = getProfileVisemeSlots(profile);
|
|
104
124
|
if (slots.length === 0) return profile.visemeJawAmounts ? [...profile.visemeJawAmounts] : void 0;
|
|
@@ -1735,12 +1755,13 @@ var BakedAnimationController = class {
|
|
|
1735
1755
|
const globalBalance = options?.balance ?? 0;
|
|
1736
1756
|
const balanceMap = options?.balanceMap;
|
|
1737
1757
|
const meshNames = options?.meshNames;
|
|
1758
|
+
const visemeSlotCount = getProfileVisemeSlots(config).length;
|
|
1738
1759
|
let maxTime = 0;
|
|
1739
1760
|
const isNumericAU = (id) => /^\d+$/.test(id);
|
|
1740
1761
|
const isVisemeIndex = (id) => {
|
|
1741
1762
|
if (options?.snippetCategory !== "visemeSnippet") return false;
|
|
1742
1763
|
const num = Number(id);
|
|
1743
|
-
return !Number.isNaN(num) && num >= 0 && num <
|
|
1764
|
+
return !Number.isNaN(num) && num >= 0 && num < visemeSlotCount;
|
|
1744
1765
|
};
|
|
1745
1766
|
const sampleAt = (arr, t) => {
|
|
1746
1767
|
if (!arr.length) return 0;
|
|
@@ -1778,11 +1799,13 @@ var BakedAnimationController = class {
|
|
|
1778
1799
|
const auId = Number(curveId);
|
|
1779
1800
|
if (isVisemeIndex(curveId)) {
|
|
1780
1801
|
const visemeMeshNames = this.getMeshNamesForViseme(config, meshNames);
|
|
1781
|
-
const
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1802
|
+
for (const target of getVisemeBindingTargets(config, auId)) {
|
|
1803
|
+
const effectiveScale = intensityScale * target.weight;
|
|
1804
|
+
if (typeof target.morph === "number") {
|
|
1805
|
+
this.addMorphIndexTracks(tracks, target.morph, keyframes, effectiveScale, visemeMeshNames);
|
|
1806
|
+
} else if (target.morph) {
|
|
1807
|
+
this.addMorphTracks(tracks, target.morph, keyframes, effectiveScale, visemeMeshNames);
|
|
1808
|
+
}
|
|
1786
1809
|
}
|
|
1787
1810
|
} else {
|
|
1788
1811
|
const auMeshNames = this.getMeshNamesForAU(auId, config, meshNames);
|
|
@@ -1825,7 +1848,7 @@ var BakedAnimationController = class {
|
|
|
1825
1848
|
}
|
|
1826
1849
|
const autoVisemeJaw = options?.autoVisemeJaw !== false;
|
|
1827
1850
|
const jawScale = options?.jawScale ?? 1;
|
|
1828
|
-
const visemeJawAmounts = config
|
|
1851
|
+
const visemeJawAmounts = getVisemeJawAmounts(config);
|
|
1829
1852
|
if (autoVisemeJaw && jawScale > 0 && visemeJawAmounts && options?.snippetCategory === "visemeSnippet" && keyframeTimes.length > 0) {
|
|
1830
1853
|
const bones = this.host.getBones();
|
|
1831
1854
|
const jawEntry = bones["JAW"];
|
|
@@ -1833,7 +1856,7 @@ var BakedAnimationController = class {
|
|
|
1833
1856
|
const jawValues = [];
|
|
1834
1857
|
for (const t of keyframeTimes) {
|
|
1835
1858
|
let jawAmount = 0;
|
|
1836
|
-
for (let visemeIdx = 0; visemeIdx <
|
|
1859
|
+
for (let visemeIdx = 0; visemeIdx < visemeSlotCount; visemeIdx++) {
|
|
1837
1860
|
const visemeCurve = curves[String(visemeIdx)];
|
|
1838
1861
|
if (!visemeCurve) continue;
|
|
1839
1862
|
const visemeValue = clampIntensity(sampleAt(visemeCurve, t) * intensityScale);
|
|
@@ -5361,10 +5384,15 @@ var _Loom3 = class _Loom3 {
|
|
|
5361
5384
|
};
|
|
5362
5385
|
this.resolvedAUMorphTargets.set(auId, resolved);
|
|
5363
5386
|
}
|
|
5364
|
-
for (let i = 0; i < (this.config
|
|
5365
|
-
const key = this.config.visemeKeys[i];
|
|
5387
|
+
for (let i = 0; i < getProfileVisemeSlots(this.config).length; i += 1) {
|
|
5366
5388
|
const visemeMeshNames = this.getMeshNamesForViseme();
|
|
5367
|
-
const targets =
|
|
5389
|
+
const targets = [];
|
|
5390
|
+
for (const bindingTarget of getVisemeBindingTargets(this.config, i)) {
|
|
5391
|
+
const resolved = typeof bindingTarget.morph === "number" ? this.resolveMorphTargetsByIndex(bindingTarget.morph, visemeMeshNames) : this.resolveMorphTargets(bindingTarget.morph, visemeMeshNames);
|
|
5392
|
+
for (const target of resolved) {
|
|
5393
|
+
targets.push({ ...target, weight: bindingTarget.weight });
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5368
5396
|
this.resolvedVisemeTargets[i] = targets;
|
|
5369
5397
|
}
|
|
5370
5398
|
}
|
|
@@ -5832,46 +5860,33 @@ var _Loom3 = class _Loom3 {
|
|
|
5832
5860
|
// VISEME CONTROL
|
|
5833
5861
|
// ============================================================================
|
|
5834
5862
|
setViseme(visemeIndex, value, jawScale = 1) {
|
|
5835
|
-
if (visemeIndex < 0 || visemeIndex >= this.
|
|
5863
|
+
if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) return;
|
|
5836
5864
|
const val = clamp012(value);
|
|
5837
5865
|
this.visemeValues[visemeIndex] = val;
|
|
5838
5866
|
this.visemeJawScales[visemeIndex] = jawScale;
|
|
5839
|
-
|
|
5840
|
-
if (targets && targets.length > 0) {
|
|
5841
|
-
this.applyMorphTargets(targets, val);
|
|
5842
|
-
} else {
|
|
5843
|
-
const morphKey = this.config.visemeKeys[visemeIndex];
|
|
5844
|
-
const visemeMeshNames = this.getMeshNamesForViseme();
|
|
5845
|
-
if (typeof morphKey === "number") {
|
|
5846
|
-
this.setMorphInfluence(morphKey, val, visemeMeshNames);
|
|
5847
|
-
} else if (typeof morphKey === "string") {
|
|
5848
|
-
this.setMorph(morphKey, val, visemeMeshNames);
|
|
5849
|
-
}
|
|
5850
|
-
}
|
|
5851
|
-
const jawAmount = this.getVisemeJawAmount(visemeIndex) * val * jawScale;
|
|
5852
|
-
if (Math.abs(jawScale) > 1e-6 && Math.abs(jawAmount) > 1e-6) {
|
|
5853
|
-
this.updateBoneRotation("JAW", "pitch", jawAmount);
|
|
5854
|
-
}
|
|
5867
|
+
this.applyVisemeRuntimeState();
|
|
5855
5868
|
}
|
|
5856
5869
|
transitionViseme(visemeIndex, to, durationMs = 80, jawScale = 1) {
|
|
5857
|
-
if (visemeIndex < 0 || visemeIndex >= this.
|
|
5870
|
+
if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) {
|
|
5858
5871
|
return { promise: Promise.resolve(), pause: () => {
|
|
5859
5872
|
}, resume: () => {
|
|
5860
5873
|
}, cancel: () => {
|
|
5861
5874
|
} };
|
|
5862
5875
|
}
|
|
5863
|
-
const morphKey = this.config.visemeKeys[visemeIndex];
|
|
5864
5876
|
const target = clamp012(to);
|
|
5865
|
-
this.visemeValues[visemeIndex]
|
|
5877
|
+
const from = this.visemeValues[visemeIndex] ?? 0;
|
|
5866
5878
|
this.visemeJawScales[visemeIndex] = jawScale;
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5879
|
+
return this.animation.addTransition(
|
|
5880
|
+
`viseme_value_${visemeIndex}`,
|
|
5881
|
+
from,
|
|
5882
|
+
target,
|
|
5883
|
+
durationMs,
|
|
5884
|
+
(value) => {
|
|
5885
|
+
this.visemeValues[visemeIndex] = clamp012(value);
|
|
5886
|
+
this.visemeJawScales[visemeIndex] = jawScale;
|
|
5887
|
+
this.applyVisemeRuntimeState();
|
|
5888
|
+
}
|
|
5889
|
+
);
|
|
5875
5890
|
}
|
|
5876
5891
|
setVisemeById(slotId, value, jawScale = 1) {
|
|
5877
5892
|
const index = getVisemeSlotIndex(this.config, slotId);
|
|
@@ -5935,8 +5950,9 @@ var _Loom3 = class _Loom3 {
|
|
|
5935
5950
|
}
|
|
5936
5951
|
resetToNeutral() {
|
|
5937
5952
|
this.auValues = {};
|
|
5938
|
-
|
|
5939
|
-
this.
|
|
5953
|
+
const visemeCount = getProfileVisemeSlots(this.config).length;
|
|
5954
|
+
this.visemeValues = new Array(visemeCount).fill(0);
|
|
5955
|
+
this.visemeJawScales = new Array(visemeCount).fill(1);
|
|
5940
5956
|
this.translations = {};
|
|
5941
5957
|
this.initBoneRotations();
|
|
5942
5958
|
this.clearTransitions();
|
|
@@ -5970,11 +5986,7 @@ var _Loom3 = class _Loom3 {
|
|
|
5970
5986
|
if (Number.isNaN(auId)) continue;
|
|
5971
5987
|
this.setAU(auId, value, this.auBalances[auId]);
|
|
5972
5988
|
}
|
|
5973
|
-
|
|
5974
|
-
const value = this.visemeValues[visemeIndex] ?? 0;
|
|
5975
|
-
if (value <= 0) continue;
|
|
5976
|
-
this.setViseme(visemeIndex, value, this.visemeJawScales[visemeIndex] ?? 1);
|
|
5977
|
-
}
|
|
5989
|
+
this.applyVisemeRuntimeState();
|
|
5978
5990
|
if (this.model) {
|
|
5979
5991
|
this.flushPendingComposites();
|
|
5980
5992
|
this.model.updateMatrixWorld(true);
|
|
@@ -6332,6 +6344,37 @@ var _Loom3 = class _Loom3 {
|
|
|
6332
6344
|
target.infl[target.idx] = val;
|
|
6333
6345
|
}
|
|
6334
6346
|
}
|
|
6347
|
+
applyVisemeRuntimeState() {
|
|
6348
|
+
for (const targets of this.resolvedVisemeTargets) {
|
|
6349
|
+
for (const target of targets || []) {
|
|
6350
|
+
if (target.idx < target.infl.length) {
|
|
6351
|
+
target.infl[target.idx] = 0;
|
|
6352
|
+
}
|
|
6353
|
+
}
|
|
6354
|
+
}
|
|
6355
|
+
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
6356
|
+
const value = clamp012(this.visemeValues[index] ?? 0);
|
|
6357
|
+
if (value <= 1e-6) continue;
|
|
6358
|
+
const targets = this.resolvedVisemeTargets[index] || [];
|
|
6359
|
+
for (const target of targets) {
|
|
6360
|
+
if (target.idx >= target.infl.length) continue;
|
|
6361
|
+
const weighted = clamp012(value * target.weight);
|
|
6362
|
+
target.infl[target.idx] = Math.max(target.infl[target.idx] ?? 0, weighted);
|
|
6363
|
+
}
|
|
6364
|
+
}
|
|
6365
|
+
this.updateBoneRotation("JAW", "pitch", this.getActiveVisemeJawAmount());
|
|
6366
|
+
}
|
|
6367
|
+
getActiveVisemeJawAmount() {
|
|
6368
|
+
let jawAmount = 0;
|
|
6369
|
+
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
6370
|
+
const value = clamp012(this.visemeValues[index] ?? 0);
|
|
6371
|
+
if (value <= 1e-6) continue;
|
|
6372
|
+
const jawScale = this.visemeJawScales[index] ?? 1;
|
|
6373
|
+
if (Math.abs(jawScale) <= 1e-6) continue;
|
|
6374
|
+
jawAmount = Math.max(jawAmount, this.getVisemeJawAmount(index) * value * jawScale);
|
|
6375
|
+
}
|
|
6376
|
+
return jawAmount;
|
|
6377
|
+
}
|
|
6335
6378
|
getMorphValue(key) {
|
|
6336
6379
|
if (this.faceMesh) {
|
|
6337
6380
|
const dict = this.faceMesh.morphTargetDictionary;
|
|
@@ -6517,7 +6560,7 @@ var _Loom3 = class _Loom3 {
|
|
|
6517
6560
|
return meshNames?.length ? `idx:${index}@${meshNames.join(",")}` : `idx:${index}`;
|
|
6518
6561
|
}
|
|
6519
6562
|
syncVisemeRuntimeState() {
|
|
6520
|
-
const visemeCount = this.config.
|
|
6563
|
+
const visemeCount = getProfileVisemeSlots(this.config).length;
|
|
6521
6564
|
this.visemeValues = Array.from(
|
|
6522
6565
|
{ length: visemeCount },
|
|
6523
6566
|
(_, index) => this.visemeValues[index] ?? 0
|
|
@@ -6989,7 +7032,7 @@ function normalizeRegionTree(regions, disabledNames) {
|
|
|
6989
7032
|
});
|
|
6990
7033
|
}
|
|
6991
7034
|
|
|
6992
|
-
// src/
|
|
7035
|
+
// src/profiles/resolveProfileConfig.ts
|
|
6993
7036
|
var PROFILE_OVERRIDE_KEYS = [
|
|
6994
7037
|
"name",
|
|
6995
7038
|
"animalType",
|
|
@@ -7096,7 +7139,7 @@ function mergeRegion(base, override) {
|
|
|
7096
7139
|
} : void 0
|
|
7097
7140
|
};
|
|
7098
7141
|
}
|
|
7099
|
-
function
|
|
7142
|
+
function mergeProfileRegionsByName(base, override) {
|
|
7100
7143
|
if (!base && !override) return void 0;
|
|
7101
7144
|
const merged = /* @__PURE__ */ new Map();
|
|
7102
7145
|
for (const region of base ?? []) {
|
|
@@ -7111,6 +7154,10 @@ function mergeRegionsByName(base, override) {
|
|
|
7111
7154
|
function getAnnotationRegions(value) {
|
|
7112
7155
|
return Array.isArray(value) ? value : void 0;
|
|
7113
7156
|
}
|
|
7157
|
+
var mergeRegionsByName = mergeProfileRegionsByName;
|
|
7158
|
+
function getProfilePresetId(config) {
|
|
7159
|
+
return config.profilePresetId ?? config.presetId ?? config.baseProfileId ?? config.auPresetType;
|
|
7160
|
+
}
|
|
7114
7161
|
function getLegacyNestedOverrides(config) {
|
|
7115
7162
|
return isPlainObject2(config.profile) ? config.profile : {};
|
|
7116
7163
|
}
|
|
@@ -7118,12 +7165,12 @@ function getLegacyRuntimeRegions(config) {
|
|
|
7118
7165
|
return Array.isArray(config.regions) && config.regions.length > 0 ? config.regions : void 0;
|
|
7119
7166
|
}
|
|
7120
7167
|
function getCanonicalAnnotationOverrides(config) {
|
|
7121
|
-
return
|
|
7168
|
+
return mergeProfileRegionsByName(
|
|
7122
7169
|
getAnnotationRegions(getLegacyNestedOverrides(config).annotationRegions),
|
|
7123
7170
|
getAnnotationRegions(config.annotationRegions)
|
|
7124
7171
|
);
|
|
7125
7172
|
}
|
|
7126
|
-
function
|
|
7173
|
+
function extractLegacyCharacterProfileOverrides(config) {
|
|
7127
7174
|
const topLevelConfig = config;
|
|
7128
7175
|
const legacyNestedOverrides = getLegacyNestedOverrides(config);
|
|
7129
7176
|
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
@@ -7146,12 +7193,18 @@ function extractProfileOverrides(config) {
|
|
|
7146
7193
|
}
|
|
7147
7194
|
return overrides;
|
|
7148
7195
|
}
|
|
7149
|
-
function
|
|
7150
|
-
|
|
7196
|
+
function extractProfileOverrides(config) {
|
|
7197
|
+
return extractLegacyCharacterProfileOverrides(config);
|
|
7198
|
+
}
|
|
7199
|
+
function resolveProfileFromPreset(config) {
|
|
7200
|
+
const presetType = getProfilePresetId(config);
|
|
7151
7201
|
if (!presetType) {
|
|
7152
7202
|
return null;
|
|
7153
7203
|
}
|
|
7154
|
-
return extendPresetWithProfile(getPreset(presetType),
|
|
7204
|
+
return extendPresetWithProfile(getPreset(presetType), extractLegacyCharacterProfileOverrides(config));
|
|
7205
|
+
}
|
|
7206
|
+
function applyCharacterProfileToPreset(config) {
|
|
7207
|
+
return resolveProfileFromPreset(config);
|
|
7155
7208
|
}
|
|
7156
7209
|
function orderExtendedRegions(extendedRegions, prioritizedLists) {
|
|
7157
7210
|
if (!extendedRegions) return void 0;
|
|
@@ -7172,15 +7225,15 @@ function orderExtendedRegions(extendedRegions, prioritizedLists) {
|
|
|
7172
7225
|
}
|
|
7173
7226
|
return orderedNames.map((name) => extendedByName.get(name)).filter((region) => Boolean(region));
|
|
7174
7227
|
}
|
|
7175
|
-
function
|
|
7176
|
-
const presetType = config
|
|
7228
|
+
function extendProfileConfigWithPreset(config) {
|
|
7229
|
+
const presetType = getProfilePresetId(config);
|
|
7177
7230
|
if (!presetType || presetType === "custom") {
|
|
7178
7231
|
return config;
|
|
7179
7232
|
}
|
|
7180
7233
|
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
7181
7234
|
const legacyRuntimeRegions = getLegacyRuntimeRegions(config);
|
|
7182
|
-
const profileOverrides =
|
|
7183
|
-
const extendedPresetProfile =
|
|
7235
|
+
const profileOverrides = extractLegacyCharacterProfileOverrides(config);
|
|
7236
|
+
const extendedPresetProfile = resolveProfileFromPreset(config);
|
|
7184
7237
|
if (!extendedPresetProfile) {
|
|
7185
7238
|
return config;
|
|
7186
7239
|
}
|
|
@@ -7194,7 +7247,7 @@ function extendCharacterConfigWithPreset(config) {
|
|
|
7194
7247
|
const extendedRegionNames = new Set((extendedAnnotationRegions ?? []).map((region) => region.name));
|
|
7195
7248
|
const legacyExtraRegions = canonicalAnnotationOverrides && legacyRuntimeRegions ? legacyRuntimeRegions.filter((region) => !presetRegionNames.has(region.name) && !extendedRegionNames.has(region.name)).map((region) => cloneRegion(region)) : void 0;
|
|
7196
7249
|
const mergedRegions = normalizeRegionTree(
|
|
7197
|
-
|
|
7250
|
+
mergeProfileRegionsByName(extendedAnnotationRegions, legacyExtraRegions),
|
|
7198
7251
|
profileOverrides.disabledRegions
|
|
7199
7252
|
);
|
|
7200
7253
|
const extendedRegions = orderExtendedRegions(
|
|
@@ -7208,6 +7261,9 @@ function extendCharacterConfigWithPreset(config) {
|
|
|
7208
7261
|
regions: extendedRegions ?? config.regions
|
|
7209
7262
|
};
|
|
7210
7263
|
}
|
|
7264
|
+
function extendCharacterConfigWithPreset(config) {
|
|
7265
|
+
return extendProfileConfigWithPreset(config);
|
|
7266
|
+
}
|
|
7211
7267
|
var DEFAULT_EPSILON = 1e-4;
|
|
7212
7268
|
var DEFAULT_YAW_WEIGHT = 0.35;
|
|
7213
7269
|
var DEFAULT_PITCH_WEIGHT = 0.2;
|
|
@@ -7432,9 +7488,9 @@ function detectFacingDirection(model, eyeBoneNames = {
|
|
|
7432
7488
|
function normalizeLooseName(value) {
|
|
7433
7489
|
return value.replace(/\./g, "");
|
|
7434
7490
|
}
|
|
7435
|
-
function resolveBoneNameCandidates(semanticName,
|
|
7436
|
-
if (!
|
|
7437
|
-
const { bonePrefix, boneSuffix, boneNodes } =
|
|
7491
|
+
function resolveBoneNameCandidates(semanticName, profile) {
|
|
7492
|
+
if (!profile) return [semanticName];
|
|
7493
|
+
const { bonePrefix, boneSuffix, boneNodes } = profile;
|
|
7438
7494
|
if (!boneNodes || !boneNodes[semanticName]) {
|
|
7439
7495
|
return [semanticName];
|
|
7440
7496
|
}
|
|
@@ -7448,14 +7504,14 @@ function resolveBoneNameCandidates(semanticName, config) {
|
|
|
7448
7504
|
const fullyAffixed = suffix && !prefixedBase.endsWith(suffix) ? `${prefixedBase}${suffix}` : prefixedBase;
|
|
7449
7505
|
return Array.from(/* @__PURE__ */ new Set([fullyAffixed, baseName]));
|
|
7450
7506
|
}
|
|
7451
|
-
function resolveBoneName(semanticName,
|
|
7452
|
-
return resolveBoneNameCandidates(semanticName,
|
|
7507
|
+
function resolveBoneName(semanticName, profile) {
|
|
7508
|
+
return resolveBoneNameCandidates(semanticName, profile)[0] ?? semanticName;
|
|
7453
7509
|
}
|
|
7454
|
-
function resolveBoneNames(names,
|
|
7510
|
+
function resolveBoneNames(names, profile) {
|
|
7455
7511
|
if (!names || names.length === 0) return [];
|
|
7456
7512
|
return Array.from(
|
|
7457
7513
|
new Set(
|
|
7458
|
-
names.flatMap((name) => resolveBoneNameCandidates(name,
|
|
7514
|
+
names.flatMap((name) => resolveBoneNameCandidates(name, profile))
|
|
7459
7515
|
)
|
|
7460
7516
|
);
|
|
7461
7517
|
}
|
|
@@ -7468,8 +7524,8 @@ function fuzzyNameMatch(objectName, targetName, suffixPattern) {
|
|
|
7468
7524
|
const regex = suffixPattern ? new RegExp(suffixPattern) : /^[_\.]\d+$/;
|
|
7469
7525
|
return regex.test(suffix);
|
|
7470
7526
|
}
|
|
7471
|
-
function resolveFaceCenter(model, region,
|
|
7472
|
-
const resolvedBones = resolveBoneNames(region.bones,
|
|
7527
|
+
function resolveFaceCenter(model, region, profile) {
|
|
7528
|
+
const resolvedBones = resolveBoneNames(region.bones, profile);
|
|
7473
7529
|
const headBoneNames = resolvedBones.filter((name) => name.toLowerCase().includes("head"));
|
|
7474
7530
|
const result = findFaceCenter(model, {
|
|
7475
7531
|
headBoneNames: headBoneNames.length > 0 ? headBoneNames : void 0,
|
|
@@ -8628,7 +8684,9 @@ exports.computeCameraRelativeGazeOffset = computeCameraRelativeGazeOffset;
|
|
|
8628
8684
|
exports.detectFacingDirection = detectFacingDirection;
|
|
8629
8685
|
exports.extendCharacterConfigWithPreset = extendCharacterConfigWithPreset;
|
|
8630
8686
|
exports.extendPresetWithProfile = extendPresetWithProfile;
|
|
8687
|
+
exports.extendProfileConfigWithPreset = extendProfileConfigWithPreset;
|
|
8631
8688
|
exports.extractFromGLTF = extractFromGLTF;
|
|
8689
|
+
exports.extractLegacyCharacterProfileOverrides = extractLegacyCharacterProfileOverrides;
|
|
8632
8690
|
exports.extractModelData = extractModelData;
|
|
8633
8691
|
exports.extractProfileOverrides = extractProfileOverrides;
|
|
8634
8692
|
exports.findFaceCenter = findFaceCenter;
|
|
@@ -8639,7 +8697,9 @@ exports.getMeshNamesForVisemeProfile = getMeshNamesForVisemeProfile;
|
|
|
8639
8697
|
exports.getModelForwardDirection = getModelForwardDirection;
|
|
8640
8698
|
exports.getPreset = getPreset;
|
|
8641
8699
|
exports.getPresetWithProfile = getPresetWithProfile;
|
|
8700
|
+
exports.getProfilePresetId = getProfilePresetId;
|
|
8642
8701
|
exports.getProfileVisemeSlots = getProfileVisemeSlots;
|
|
8702
|
+
exports.getVisemeBindingTargets = getVisemeBindingTargets;
|
|
8643
8703
|
exports.getVisemeJawAmounts = getVisemeJawAmounts;
|
|
8644
8704
|
exports.getVisemeSlotIndex = getVisemeSlotIndex;
|
|
8645
8705
|
exports.hasLeftRightMorphs = hasLeftRightMorphs;
|
|
@@ -8647,11 +8707,13 @@ exports.isMixedAU = isMixedAU;
|
|
|
8647
8707
|
exports.isPresetCompatible = isPresetCompatible;
|
|
8648
8708
|
exports.mapProviderVisemeToSlot = mapProviderVisemeToSlot;
|
|
8649
8709
|
exports.mergeCharacterRegionsByName = mergeRegionsByName;
|
|
8710
|
+
exports.mergeProfileRegionsByName = mergeProfileRegionsByName;
|
|
8650
8711
|
exports.resolveBoneName = resolveBoneName;
|
|
8651
8712
|
exports.resolveBoneNames = resolveBoneNames;
|
|
8652
8713
|
exports.resolveFaceCenter = resolveFaceCenter;
|
|
8653
8714
|
exports.resolvePreset = resolvePreset;
|
|
8654
8715
|
exports.resolvePresetWithOverrides = resolvePresetWithOverrides;
|
|
8716
|
+
exports.resolveProfileFromPreset = resolveProfileFromPreset;
|
|
8655
8717
|
exports.resolveVisemeMeshCategory = resolveVisemeMeshCategory;
|
|
8656
8718
|
exports.suggestBestPreset = suggestBestPreset;
|
|
8657
8719
|
exports.validateMappingConfig = validateMappingConfig;
|