@lovelace_lol/loom3 1.0.44 → 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 +39 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +239 -212
- package/dist/index.d.ts +239 -212
- package/dist/index.js +35 -22
- 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
|
@@ -7032,7 +7032,7 @@ function normalizeRegionTree(regions, disabledNames) {
|
|
|
7032
7032
|
});
|
|
7033
7033
|
}
|
|
7034
7034
|
|
|
7035
|
-
// src/
|
|
7035
|
+
// src/profiles/resolveProfileConfig.ts
|
|
7036
7036
|
var PROFILE_OVERRIDE_KEYS = [
|
|
7037
7037
|
"name",
|
|
7038
7038
|
"animalType",
|
|
@@ -7139,7 +7139,7 @@ function mergeRegion(base, override) {
|
|
|
7139
7139
|
} : void 0
|
|
7140
7140
|
};
|
|
7141
7141
|
}
|
|
7142
|
-
function
|
|
7142
|
+
function mergeProfileRegionsByName(base, override) {
|
|
7143
7143
|
if (!base && !override) return void 0;
|
|
7144
7144
|
const merged = /* @__PURE__ */ new Map();
|
|
7145
7145
|
for (const region of base ?? []) {
|
|
@@ -7154,6 +7154,10 @@ function mergeRegionsByName(base, override) {
|
|
|
7154
7154
|
function getAnnotationRegions(value) {
|
|
7155
7155
|
return Array.isArray(value) ? value : void 0;
|
|
7156
7156
|
}
|
|
7157
|
+
var mergeRegionsByName = mergeProfileRegionsByName;
|
|
7158
|
+
function getProfilePresetId(config) {
|
|
7159
|
+
return config.profilePresetId ?? config.presetId ?? config.baseProfileId ?? config.auPresetType;
|
|
7160
|
+
}
|
|
7157
7161
|
function getLegacyNestedOverrides(config) {
|
|
7158
7162
|
return isPlainObject2(config.profile) ? config.profile : {};
|
|
7159
7163
|
}
|
|
@@ -7161,12 +7165,12 @@ function getLegacyRuntimeRegions(config) {
|
|
|
7161
7165
|
return Array.isArray(config.regions) && config.regions.length > 0 ? config.regions : void 0;
|
|
7162
7166
|
}
|
|
7163
7167
|
function getCanonicalAnnotationOverrides(config) {
|
|
7164
|
-
return
|
|
7168
|
+
return mergeProfileRegionsByName(
|
|
7165
7169
|
getAnnotationRegions(getLegacyNestedOverrides(config).annotationRegions),
|
|
7166
7170
|
getAnnotationRegions(config.annotationRegions)
|
|
7167
7171
|
);
|
|
7168
7172
|
}
|
|
7169
|
-
function
|
|
7173
|
+
function extractLegacyCharacterProfileOverrides(config) {
|
|
7170
7174
|
const topLevelConfig = config;
|
|
7171
7175
|
const legacyNestedOverrides = getLegacyNestedOverrides(config);
|
|
7172
7176
|
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
@@ -7189,12 +7193,18 @@ function extractProfileOverrides(config) {
|
|
|
7189
7193
|
}
|
|
7190
7194
|
return overrides;
|
|
7191
7195
|
}
|
|
7192
|
-
function
|
|
7193
|
-
|
|
7196
|
+
function extractProfileOverrides(config) {
|
|
7197
|
+
return extractLegacyCharacterProfileOverrides(config);
|
|
7198
|
+
}
|
|
7199
|
+
function resolveProfileFromPreset(config) {
|
|
7200
|
+
const presetType = getProfilePresetId(config);
|
|
7194
7201
|
if (!presetType) {
|
|
7195
7202
|
return null;
|
|
7196
7203
|
}
|
|
7197
|
-
return extendPresetWithProfile(getPreset(presetType),
|
|
7204
|
+
return extendPresetWithProfile(getPreset(presetType), extractLegacyCharacterProfileOverrides(config));
|
|
7205
|
+
}
|
|
7206
|
+
function applyCharacterProfileToPreset(config) {
|
|
7207
|
+
return resolveProfileFromPreset(config);
|
|
7198
7208
|
}
|
|
7199
7209
|
function orderExtendedRegions(extendedRegions, prioritizedLists) {
|
|
7200
7210
|
if (!extendedRegions) return void 0;
|
|
@@ -7215,15 +7225,15 @@ function orderExtendedRegions(extendedRegions, prioritizedLists) {
|
|
|
7215
7225
|
}
|
|
7216
7226
|
return orderedNames.map((name) => extendedByName.get(name)).filter((region) => Boolean(region));
|
|
7217
7227
|
}
|
|
7218
|
-
function
|
|
7219
|
-
const presetType = config
|
|
7228
|
+
function extendProfileConfigWithPreset(config) {
|
|
7229
|
+
const presetType = getProfilePresetId(config);
|
|
7220
7230
|
if (!presetType || presetType === "custom") {
|
|
7221
7231
|
return config;
|
|
7222
7232
|
}
|
|
7223
7233
|
const canonicalAnnotationOverrides = getCanonicalAnnotationOverrides(config);
|
|
7224
7234
|
const legacyRuntimeRegions = getLegacyRuntimeRegions(config);
|
|
7225
|
-
const profileOverrides =
|
|
7226
|
-
const extendedPresetProfile =
|
|
7235
|
+
const profileOverrides = extractLegacyCharacterProfileOverrides(config);
|
|
7236
|
+
const extendedPresetProfile = resolveProfileFromPreset(config);
|
|
7227
7237
|
if (!extendedPresetProfile) {
|
|
7228
7238
|
return config;
|
|
7229
7239
|
}
|
|
@@ -7237,7 +7247,7 @@ function extendCharacterConfigWithPreset(config) {
|
|
|
7237
7247
|
const extendedRegionNames = new Set((extendedAnnotationRegions ?? []).map((region) => region.name));
|
|
7238
7248
|
const legacyExtraRegions = canonicalAnnotationOverrides && legacyRuntimeRegions ? legacyRuntimeRegions.filter((region) => !presetRegionNames.has(region.name) && !extendedRegionNames.has(region.name)).map((region) => cloneRegion(region)) : void 0;
|
|
7239
7249
|
const mergedRegions = normalizeRegionTree(
|
|
7240
|
-
|
|
7250
|
+
mergeProfileRegionsByName(extendedAnnotationRegions, legacyExtraRegions),
|
|
7241
7251
|
profileOverrides.disabledRegions
|
|
7242
7252
|
);
|
|
7243
7253
|
const extendedRegions = orderExtendedRegions(
|
|
@@ -7251,6 +7261,9 @@ function extendCharacterConfigWithPreset(config) {
|
|
|
7251
7261
|
regions: extendedRegions ?? config.regions
|
|
7252
7262
|
};
|
|
7253
7263
|
}
|
|
7264
|
+
function extendCharacterConfigWithPreset(config) {
|
|
7265
|
+
return extendProfileConfigWithPreset(config);
|
|
7266
|
+
}
|
|
7254
7267
|
var DEFAULT_EPSILON = 1e-4;
|
|
7255
7268
|
var DEFAULT_YAW_WEIGHT = 0.35;
|
|
7256
7269
|
var DEFAULT_PITCH_WEIGHT = 0.2;
|
|
@@ -7475,9 +7488,9 @@ function detectFacingDirection(model, eyeBoneNames = {
|
|
|
7475
7488
|
function normalizeLooseName(value) {
|
|
7476
7489
|
return value.replace(/\./g, "");
|
|
7477
7490
|
}
|
|
7478
|
-
function resolveBoneNameCandidates(semanticName,
|
|
7479
|
-
if (!
|
|
7480
|
-
const { bonePrefix, boneSuffix, boneNodes } =
|
|
7491
|
+
function resolveBoneNameCandidates(semanticName, profile) {
|
|
7492
|
+
if (!profile) return [semanticName];
|
|
7493
|
+
const { bonePrefix, boneSuffix, boneNodes } = profile;
|
|
7481
7494
|
if (!boneNodes || !boneNodes[semanticName]) {
|
|
7482
7495
|
return [semanticName];
|
|
7483
7496
|
}
|
|
@@ -7491,14 +7504,14 @@ function resolveBoneNameCandidates(semanticName, config) {
|
|
|
7491
7504
|
const fullyAffixed = suffix && !prefixedBase.endsWith(suffix) ? `${prefixedBase}${suffix}` : prefixedBase;
|
|
7492
7505
|
return Array.from(/* @__PURE__ */ new Set([fullyAffixed, baseName]));
|
|
7493
7506
|
}
|
|
7494
|
-
function resolveBoneName(semanticName,
|
|
7495
|
-
return resolveBoneNameCandidates(semanticName,
|
|
7507
|
+
function resolveBoneName(semanticName, profile) {
|
|
7508
|
+
return resolveBoneNameCandidates(semanticName, profile)[0] ?? semanticName;
|
|
7496
7509
|
}
|
|
7497
|
-
function resolveBoneNames(names,
|
|
7510
|
+
function resolveBoneNames(names, profile) {
|
|
7498
7511
|
if (!names || names.length === 0) return [];
|
|
7499
7512
|
return Array.from(
|
|
7500
7513
|
new Set(
|
|
7501
|
-
names.flatMap((name) => resolveBoneNameCandidates(name,
|
|
7514
|
+
names.flatMap((name) => resolveBoneNameCandidates(name, profile))
|
|
7502
7515
|
)
|
|
7503
7516
|
);
|
|
7504
7517
|
}
|
|
@@ -7511,8 +7524,8 @@ function fuzzyNameMatch(objectName, targetName, suffixPattern) {
|
|
|
7511
7524
|
const regex = suffixPattern ? new RegExp(suffixPattern) : /^[_\.]\d+$/;
|
|
7512
7525
|
return regex.test(suffix);
|
|
7513
7526
|
}
|
|
7514
|
-
function resolveFaceCenter(model, region,
|
|
7515
|
-
const resolvedBones = resolveBoneNames(region.bones,
|
|
7527
|
+
function resolveFaceCenter(model, region, profile) {
|
|
7528
|
+
const resolvedBones = resolveBoneNames(region.bones, profile);
|
|
7516
7529
|
const headBoneNames = resolvedBones.filter((name) => name.toLowerCase().includes("head"));
|
|
7517
7530
|
const result = findFaceCenter(model, {
|
|
7518
7531
|
headBoneNames: headBoneNames.length > 0 ? headBoneNames : void 0,
|
|
@@ -8671,7 +8684,9 @@ exports.computeCameraRelativeGazeOffset = computeCameraRelativeGazeOffset;
|
|
|
8671
8684
|
exports.detectFacingDirection = detectFacingDirection;
|
|
8672
8685
|
exports.extendCharacterConfigWithPreset = extendCharacterConfigWithPreset;
|
|
8673
8686
|
exports.extendPresetWithProfile = extendPresetWithProfile;
|
|
8687
|
+
exports.extendProfileConfigWithPreset = extendProfileConfigWithPreset;
|
|
8674
8688
|
exports.extractFromGLTF = extractFromGLTF;
|
|
8689
|
+
exports.extractLegacyCharacterProfileOverrides = extractLegacyCharacterProfileOverrides;
|
|
8675
8690
|
exports.extractModelData = extractModelData;
|
|
8676
8691
|
exports.extractProfileOverrides = extractProfileOverrides;
|
|
8677
8692
|
exports.findFaceCenter = findFaceCenter;
|
|
@@ -8682,6 +8697,7 @@ exports.getMeshNamesForVisemeProfile = getMeshNamesForVisemeProfile;
|
|
|
8682
8697
|
exports.getModelForwardDirection = getModelForwardDirection;
|
|
8683
8698
|
exports.getPreset = getPreset;
|
|
8684
8699
|
exports.getPresetWithProfile = getPresetWithProfile;
|
|
8700
|
+
exports.getProfilePresetId = getProfilePresetId;
|
|
8685
8701
|
exports.getProfileVisemeSlots = getProfileVisemeSlots;
|
|
8686
8702
|
exports.getVisemeBindingTargets = getVisemeBindingTargets;
|
|
8687
8703
|
exports.getVisemeJawAmounts = getVisemeJawAmounts;
|
|
@@ -8691,11 +8707,13 @@ exports.isMixedAU = isMixedAU;
|
|
|
8691
8707
|
exports.isPresetCompatible = isPresetCompatible;
|
|
8692
8708
|
exports.mapProviderVisemeToSlot = mapProviderVisemeToSlot;
|
|
8693
8709
|
exports.mergeCharacterRegionsByName = mergeRegionsByName;
|
|
8710
|
+
exports.mergeProfileRegionsByName = mergeProfileRegionsByName;
|
|
8694
8711
|
exports.resolveBoneName = resolveBoneName;
|
|
8695
8712
|
exports.resolveBoneNames = resolveBoneNames;
|
|
8696
8713
|
exports.resolveFaceCenter = resolveFaceCenter;
|
|
8697
8714
|
exports.resolvePreset = resolvePreset;
|
|
8698
8715
|
exports.resolvePresetWithOverrides = resolvePresetWithOverrides;
|
|
8716
|
+
exports.resolveProfileFromPreset = resolveProfileFromPreset;
|
|
8699
8717
|
exports.resolveVisemeMeshCategory = resolveVisemeMeshCategory;
|
|
8700
8718
|
exports.suggestBestPreset = suggestBestPreset;
|
|
8701
8719
|
exports.validateMappingConfig = validateMappingConfig;
|