@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 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 full saved `CharacterConfig` from Firestore or another backend, use `extendCharacterConfigWithPreset(...)` to build the runtime shape before handing that config to camera/marker tooling:
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 { extendCharacterConfigWithPreset } from '@lovelace_lol/loom3';
356
+ import { extendProfileConfigWithPreset } from '@lovelace_lol/loom3';
357
357
 
358
- const savedConfig = await fetchCharacterConfig();
359
- const runtimeConfig = extendCharacterConfigWithPreset(savedConfig);
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 { CharacterConfig, Region } from '@lovelace_lol/loom3';
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 config = {
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
- } satisfies CharacterConfig;
2111
+ };
2111
2112
 
2112
- const headBone = resolveBoneName('HEAD', config);
2113
- const resolvedBones = resolveBoneNames(['HEAD'], config);
2114
- const faceCenter = resolveFaceCenter(gltf.scene, region, config);
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 character config
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/characters/extendCharacterConfigWithPreset.ts
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 mergeRegionsByName(base, override) {
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 mergeRegionsByName(
7168
+ return mergeProfileRegionsByName(
7165
7169
  getAnnotationRegions(getLegacyNestedOverrides(config).annotationRegions),
7166
7170
  getAnnotationRegions(config.annotationRegions)
7167
7171
  );
7168
7172
  }
7169
- function extractProfileOverrides(config) {
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 applyCharacterProfileToPreset(config) {
7193
- const presetType = config.auPresetType;
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), extractProfileOverrides(config));
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 extendCharacterConfigWithPreset(config) {
7219
- const presetType = config.auPresetType;
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 = extractProfileOverrides(config);
7226
- const extendedPresetProfile = applyCharacterProfileToPreset(config);
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
- mergeRegionsByName(extendedAnnotationRegions, legacyExtraRegions),
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, config) {
7479
- if (!config) return [semanticName];
7480
- const { bonePrefix, boneSuffix, boneNodes } = config;
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, config) {
7495
- return resolveBoneNameCandidates(semanticName, config)[0] ?? semanticName;
7507
+ function resolveBoneName(semanticName, profile) {
7508
+ return resolveBoneNameCandidates(semanticName, profile)[0] ?? semanticName;
7496
7509
  }
7497
- function resolveBoneNames(names, config) {
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, config))
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, config) {
7515
- const resolvedBones = resolveBoneNames(region.bones, config);
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;