@lovelace_lol/loom3 1.0.27 → 1.0.28

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
@@ -349,6 +349,15 @@ const loom = new Loom3({
349
349
 
350
350
  `annotationRegions` is the Loom3 field for camera/marker region defaults and profile overrides.
351
351
 
352
+ If your app fetches a full saved `CharacterConfig` from Firestore or another backend, use `resolveCharacterConfig(...)` to build the runtime shape before handing that config to camera/marker tooling:
353
+
354
+ ```typescript
355
+ import { resolveCharacterConfig } from '@lovelace_lol/loom3';
356
+
357
+ const savedConfig = await fetchCharacterConfig();
358
+ const runtimeConfig = resolveCharacterConfig(savedConfig);
359
+ ```
360
+
352
361
  For the current runtime-oriented documentation, including:
353
362
 
354
363
  - `paddingFactor`
package/dist/index.cjs CHANGED
@@ -3005,6 +3005,9 @@ function resolveProfile(base, override) {
3005
3005
  hairPhysics: mergeHairPhysicsConfig(base.hairPhysics, override.hairPhysics)
3006
3006
  };
3007
3007
  }
3008
+ function applyProfileToPreset(base, override) {
3009
+ return override ? resolveProfile(base, override) : base;
3010
+ }
3008
3011
 
3009
3012
  // src/presets/bettaFish.ts
3010
3013
  var BONES = [
@@ -3677,6 +3680,9 @@ var MESHES = {
3677
3680
  morphCount: 0,
3678
3681
  // Fish model has no morphs
3679
3682
  material: {
3683
+ renderOrder: 20,
3684
+ transparent: true,
3685
+ opacity: 1,
3680
3686
  depthWrite: true,
3681
3687
  depthTest: true,
3682
3688
  blending: "Normal"
@@ -3687,29 +3693,126 @@ var MESHES = {
3687
3693
  category: "eye",
3688
3694
  morphCount: 0,
3689
3695
  material: {
3690
- renderOrder: -10,
3691
- // Render early (behind body)
3696
+ renderOrder: 17,
3697
+ transparent: true,
3698
+ opacity: 1,
3699
+ depthWrite: true,
3700
+ depthTest: true,
3701
+ blending: "Normal"
3702
+ }
3703
+ },
3704
+ // Hidden helper shell from the source asset; keep it suppressed by default
3705
+ // so Betta does not rely on a Firestore-only mesh override.
3706
+ "Cube_0": {
3707
+ category: "body",
3708
+ morphCount: 0,
3709
+ material: {
3710
+ renderOrder: -20,
3711
+ transparent: true,
3712
+ opacity: 0,
3692
3713
  depthWrite: true,
3693
3714
  depthTest: true,
3694
3715
  blending: "Normal"
3695
3716
  }
3696
3717
  }
3697
3718
  };
3698
- var BETTA_FISH_PRESET = {
3699
- name: "Betta Fish",
3700
- animalType: "fish",
3701
- emoji: "\u{1F41F}",
3702
- bones: BONES,
3703
- boneNodes: BONE_NODES,
3704
- boneBindings: BONE_BINDINGS,
3705
- actionInfo: AU_INFO2,
3706
- eyeMeshNodes: EYE_MESH_NODES,
3707
- // No morph targets in this model
3708
- auToMorphs: {},
3709
- morphToMesh: {},
3710
- visemeKeys: []
3711
- };
3712
- var AU_MAPPING_CONFIG = {
3719
+ var ANNOTATION_REGIONS = [
3720
+ {
3721
+ name: "full_body",
3722
+ objects: ["*"],
3723
+ paddingFactor: 2.5
3724
+ },
3725
+ {
3726
+ name: "head",
3727
+ bones: ["HEAD"],
3728
+ paddingFactor: 1.8,
3729
+ children: ["left_eye", "right_eye", "mouth"],
3730
+ expandAnimation: "staggered"
3731
+ },
3732
+ {
3733
+ name: "left_eye",
3734
+ meshes: ["EYES_0"],
3735
+ parent: "head",
3736
+ paddingFactor: 1.4,
3737
+ cameraAngle: 270
3738
+ },
3739
+ {
3740
+ name: "right_eye",
3741
+ meshes: ["EYES_0"],
3742
+ parent: "head",
3743
+ paddingFactor: 1.4,
3744
+ cameraAngle: 90
3745
+ },
3746
+ {
3747
+ name: "mouth",
3748
+ bones: ["HEAD"],
3749
+ parent: "head",
3750
+ paddingFactor: 1.5
3751
+ },
3752
+ {
3753
+ name: "body",
3754
+ bones: ["BODY_FRONT", "BODY_MID", "BODY_BACK"],
3755
+ paddingFactor: 1.8
3756
+ },
3757
+ {
3758
+ name: "tail",
3759
+ bones: ["TAIL_BASE", "TAIL_TOP", "TAIL_MID"],
3760
+ paddingFactor: 1.6
3761
+ },
3762
+ {
3763
+ name: "dorsal_fin",
3764
+ bones: ["DORSAL_ROOT", "DORSAL_L", "DORSAL_R"],
3765
+ paddingFactor: 1.8
3766
+ },
3767
+ {
3768
+ name: "pectoral_fins",
3769
+ bones: ["PECTORAL_L_ROOT", "PECTORAL_R_ROOT"],
3770
+ paddingFactor: 1.8,
3771
+ children: ["pectoral_fin_left", "pectoral_fin_right"],
3772
+ expandAnimation: "outward"
3773
+ },
3774
+ {
3775
+ name: "pectoral_fin_left",
3776
+ bones: ["PECTORAL_L_ROOT", "PECTORAL_L_CHAIN1", "PECTORAL_L_CHAIN2"],
3777
+ parent: "pectoral_fins",
3778
+ paddingFactor: 1.6,
3779
+ cameraAngle: 270
3780
+ },
3781
+ {
3782
+ name: "pectoral_fin_right",
3783
+ bones: ["PECTORAL_R_ROOT", "PECTORAL_R_CHAIN1", "PECTORAL_R_ROOT2"],
3784
+ parent: "pectoral_fins",
3785
+ paddingFactor: 1.6,
3786
+ cameraAngle: 90
3787
+ },
3788
+ {
3789
+ name: "ventral_fins",
3790
+ bones: ["VENTRAL_L", "VENTRAL_R"],
3791
+ paddingFactor: 1.6
3792
+ },
3793
+ {
3794
+ name: "gills",
3795
+ bones: ["GILL_L", "GILL_R"],
3796
+ paddingFactor: 1.6,
3797
+ children: ["throat", "gill"],
3798
+ expandAnimation: "outward"
3799
+ },
3800
+ {
3801
+ name: "throat",
3802
+ bones: ["GILL_L", "GILL_L_MID", "GILL_L_TIP"],
3803
+ parent: "gills",
3804
+ paddingFactor: 1.4,
3805
+ cameraAngle: 270
3806
+ },
3807
+ {
3808
+ name: "gill",
3809
+ bones: ["GILL_R", "GILL_R_MID", "GILL_R_TIP"],
3810
+ parent: "gills",
3811
+ paddingFactor: 1.4,
3812
+ cameraAngle: 90
3813
+ }
3814
+ ];
3815
+ var BETTA_FISH_PROFILE = {
3713
3816
  name: "Betta Fish",
3714
3817
  animalType: "fish",
3715
3818
  emoji: "\u{1F41F}",
@@ -3727,18 +3830,27 @@ var AU_MAPPING_CONFIG = {
3727
3830
  compositeRotations: COMPOSITE_ROTATIONS2,
3728
3831
  eyeMeshNodes: EYE_MESH_NODES,
3729
3832
  meshes: MESHES,
3833
+ annotationRegions: ANNOTATION_REGIONS,
3730
3834
  auMixDefaults: {},
3731
3835
  // No mixed AUs (morph+bone) in this model
3732
3836
  continuumPairs: CONTINUUM_PAIRS_MAP2,
3733
3837
  continuumLabels: CONTINUUM_LABELS2
3734
3838
  };
3839
+ var BETTA_FISH_PRESET = {
3840
+ ...BETTA_FISH_PROFILE,
3841
+ bones: BONES,
3842
+ boneBindings: BONE_BINDINGS,
3843
+ actionInfo: AU_INFO2
3844
+ };
3845
+ var AU_MAPPING_CONFIG = BETTA_FISH_PRESET;
3846
+ var FISH_AU_MAPPING_CONFIG = BETTA_FISH_PRESET;
3735
3847
 
3736
3848
  // src/presets/index.ts
3737
3849
  function resolvePreset(presetType) {
3738
3850
  switch (presetType) {
3739
3851
  case "fish":
3740
3852
  case "skeletal":
3741
- return AU_MAPPING_CONFIG;
3853
+ return BETTA_FISH_PRESET;
3742
3854
  case "cc4":
3743
3855
  case "custom":
3744
3856
  default:
@@ -3747,7 +3859,7 @@ function resolvePreset(presetType) {
3747
3859
  }
3748
3860
  function resolvePresetWithOverrides(presetType, overrides) {
3749
3861
  const base = resolvePreset(presetType);
3750
- return overrides ? resolveProfile(base, overrides) : base;
3862
+ return applyProfileToPreset(base, overrides);
3751
3863
  }
3752
3864
 
3753
3865
  // src/engines/three/Loom3.ts
@@ -3824,7 +3936,7 @@ var _Loom3 = class _Loom3 {
3824
3936
  /** Store original emissive colors for highlight reset */
3825
3937
  __publicField(this, "originalEmissive", /* @__PURE__ */ new Map());
3826
3938
  const basePreset = config.presetType ? resolvePreset(config.presetType) : CC4_PRESET;
3827
- this.config = config.profile ? resolveProfile(basePreset, config.profile) : basePreset;
3939
+ this.config = applyProfileToPreset(basePreset, config.profile);
3828
3940
  this.mixWeights = { ...this.config.auMixDefaults };
3829
3941
  this.animation = animation || new AnimationThree();
3830
3942
  this.compositeRotations = this.config.compositeRotations || COMPOSITE_ROTATIONS;
@@ -5232,6 +5344,206 @@ var BLENDING_MODES = {
5232
5344
  "None": 0
5233
5345
  // THREE.NoBlending
5234
5346
  };
5347
+
5348
+ // src/characters/resolveCharacterConfig.ts
5349
+ var PROFILE_OVERRIDE_KEYS = [
5350
+ "name",
5351
+ "animalType",
5352
+ "emoji",
5353
+ "auToMorphs",
5354
+ "auToBones",
5355
+ "boneNodes",
5356
+ "bonePrefix",
5357
+ "boneSuffix",
5358
+ "morphPrefix",
5359
+ "morphSuffix",
5360
+ "suffixPattern",
5361
+ "leftMorphSuffixes",
5362
+ "rightMorphSuffixes",
5363
+ "morphToMesh",
5364
+ "auFacePartToMeshCategory",
5365
+ "visemeKeys",
5366
+ "visemeMeshCategory",
5367
+ "visemeJawAmounts",
5368
+ "auMixDefaults",
5369
+ "auInfo",
5370
+ "eyeMeshNodes",
5371
+ "compositeRotations",
5372
+ "meshes",
5373
+ "continuumPairs",
5374
+ "continuumLabels",
5375
+ "annotationRegions",
5376
+ "hairPhysics"
5377
+ ];
5378
+ function isPlainObject2(value) {
5379
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5380
+ }
5381
+ function cloneArray(value) {
5382
+ return value ? value.map((entry) => cloneValue2(entry)) : void 0;
5383
+ }
5384
+ function cloneValue2(value) {
5385
+ if (Array.isArray(value)) {
5386
+ return value.map((entry) => cloneValue2(entry));
5387
+ }
5388
+ if (isPlainObject2(value)) {
5389
+ const next = {};
5390
+ for (const [key, entry] of Object.entries(value)) {
5391
+ next[key] = cloneValue2(entry);
5392
+ }
5393
+ return next;
5394
+ }
5395
+ return value;
5396
+ }
5397
+ function mergeProfileOverrideValue(base, override) {
5398
+ if (override === void 0) {
5399
+ return base === void 0 ? void 0 : cloneValue2(base);
5400
+ }
5401
+ if (Array.isArray(override)) {
5402
+ return cloneValue2(override);
5403
+ }
5404
+ if (isPlainObject2(base) && isPlainObject2(override)) {
5405
+ return {
5406
+ ...cloneValue2(base),
5407
+ ...cloneValue2(override)
5408
+ };
5409
+ }
5410
+ return cloneValue2(override);
5411
+ }
5412
+ function cloneVector3(value) {
5413
+ return value ? { ...value } : void 0;
5414
+ }
5415
+ function cloneRegion(region) {
5416
+ return {
5417
+ ...region,
5418
+ bones: cloneArray(region.bones),
5419
+ meshes: cloneArray(region.meshes),
5420
+ objects: cloneArray(region.objects),
5421
+ children: cloneArray(region.children),
5422
+ cameraOffset: cloneVector3(region.cameraOffset),
5423
+ customPosition: region.customPosition ? { ...region.customPosition } : void 0,
5424
+ style: region.style ? {
5425
+ ...region.style,
5426
+ line: region.style.line ? { ...region.style.line } : void 0
5427
+ } : void 0
5428
+ };
5429
+ }
5430
+ function mergeRegion(base, override) {
5431
+ return {
5432
+ ...base,
5433
+ ...override,
5434
+ bones: override.bones !== void 0 ? [...override.bones] : base.bones ? [...base.bones] : void 0,
5435
+ meshes: override.meshes !== void 0 ? [...override.meshes] : base.meshes ? [...base.meshes] : void 0,
5436
+ objects: override.objects !== void 0 ? [...override.objects] : base.objects ? [...base.objects] : void 0,
5437
+ children: override.children !== void 0 ? [...override.children] : base.children ? [...base.children] : void 0,
5438
+ cameraOffset: override.cameraOffset ? { ...base.cameraOffset, ...override.cameraOffset } : cloneVector3(base.cameraOffset),
5439
+ customPosition: override.customPosition ? { ...override.customPosition } : base.customPosition ? { ...base.customPosition } : void 0,
5440
+ style: override.style ? {
5441
+ ...base.style,
5442
+ ...override.style,
5443
+ line: override.style.line ? { ...base.style?.line, ...override.style.line } : base.style?.line ? { ...base.style.line } : void 0
5444
+ } : base.style ? {
5445
+ ...base.style,
5446
+ line: base.style.line ? { ...base.style.line } : void 0
5447
+ } : void 0
5448
+ };
5449
+ }
5450
+ function mergeStringRecord(base, override) {
5451
+ if (!base && !override) return void 0;
5452
+ return {
5453
+ ...base ? { ...base } : {},
5454
+ ...override ? { ...override } : {}
5455
+ };
5456
+ }
5457
+ function mergeRegionsByName(base, override) {
5458
+ if (!base && !override) return void 0;
5459
+ const merged = /* @__PURE__ */ new Map();
5460
+ for (const region of base ?? []) {
5461
+ merged.set(region.name, cloneRegion(region));
5462
+ }
5463
+ for (const region of override ?? []) {
5464
+ const existing = merged.get(region.name);
5465
+ merged.set(region.name, existing ? mergeRegion(existing, region) : cloneRegion(region));
5466
+ }
5467
+ return Array.from(merged.values());
5468
+ }
5469
+ function extractProfileOverrides(config) {
5470
+ const topLevelConfig = config;
5471
+ const legacyNestedOverrides = isPlainObject2(config.profile) ? config.profile : {};
5472
+ const overrides = {};
5473
+ for (const key of PROFILE_OVERRIDE_KEYS) {
5474
+ if (key === "annotationRegions") {
5475
+ const topLevelAnnotationRegions = Array.isArray(topLevelConfig.annotationRegions) ? topLevelConfig.annotationRegions : void 0;
5476
+ const legacyAnnotationRegions = Array.isArray(legacyNestedOverrides.annotationRegions) ? legacyNestedOverrides.annotationRegions : void 0;
5477
+ const presetOverrideRegions = mergeRegionsByName(legacyAnnotationRegions, topLevelAnnotationRegions);
5478
+ const regions = mergeRegionsByName(
5479
+ presetOverrideRegions,
5480
+ Array.isArray(config.regions) && config.regions.length > 0 ? config.regions : void 0
5481
+ );
5482
+ if (regions) {
5483
+ overrides.annotationRegions = regions.map((region) => cloneRegion(region));
5484
+ }
5485
+ continue;
5486
+ }
5487
+ const topLevelValue = topLevelConfig[key];
5488
+ const legacyValue = legacyNestedOverrides[key];
5489
+ const mergedValue = mergeProfileOverrideValue(legacyValue, topLevelValue);
5490
+ if (mergedValue !== void 0) {
5491
+ overrides[key] = mergedValue;
5492
+ }
5493
+ }
5494
+ return overrides;
5495
+ }
5496
+ function applyCharacterProfileToPreset(config) {
5497
+ const presetType = config.auPresetType;
5498
+ if (!presetType) {
5499
+ return null;
5500
+ }
5501
+ return applyProfileToPreset(resolvePreset(presetType), extractProfileOverrides(config));
5502
+ }
5503
+ function orderResolvedRegions(resolvedRegions, prioritizedLists) {
5504
+ if (!resolvedRegions) return void 0;
5505
+ const resolvedByName = new Map(resolvedRegions.map((region) => [region.name, region]));
5506
+ const orderedNames = [];
5507
+ const seen = /* @__PURE__ */ new Set();
5508
+ for (const regions of prioritizedLists) {
5509
+ for (const region of regions ?? []) {
5510
+ if (seen.has(region.name)) continue;
5511
+ seen.add(region.name);
5512
+ orderedNames.push(region.name);
5513
+ }
5514
+ }
5515
+ for (const region of resolvedRegions) {
5516
+ if (seen.has(region.name)) continue;
5517
+ seen.add(region.name);
5518
+ orderedNames.push(region.name);
5519
+ }
5520
+ return orderedNames.map((name) => resolvedByName.get(name)).filter((region) => Boolean(region));
5521
+ }
5522
+ function resolveCharacterConfig(config) {
5523
+ const presetType = config.auPresetType;
5524
+ if (!presetType || presetType === "custom") {
5525
+ return config;
5526
+ }
5527
+ const profileOverrides = extractProfileOverrides(config);
5528
+ const presetResolvedProfile = applyCharacterProfileToPreset(config);
5529
+ if (!presetResolvedProfile) {
5530
+ return config;
5531
+ }
5532
+ const presetRegions = presetResolvedProfile.annotationRegions;
5533
+ const mergedRegions = mergeRegionsByName(presetRegions, config.regions);
5534
+ const resolvedRegions = orderResolvedRegions(
5535
+ mergedRegions,
5536
+ [config.regions, profileOverrides.annotationRegions, presetRegions]
5537
+ );
5538
+ return {
5539
+ ...config,
5540
+ bonePrefix: config.bonePrefix ?? presetResolvedProfile.bonePrefix,
5541
+ boneSuffix: config.boneSuffix ?? presetResolvedProfile.boneSuffix,
5542
+ boneNodes: mergeStringRecord(presetResolvedProfile.boneNodes, config.boneNodes),
5543
+ suffixPattern: config.suffixPattern ?? presetResolvedProfile.suffixPattern,
5544
+ regions: resolvedRegions ?? config.regions
5545
+ };
5546
+ }
5235
5547
  var DEFAULT_HEAD_BONE_NAMES = ["CC_Base_Head", "Head", "head", "Bip01_Head"];
5236
5548
  var DEFAULT_REFERENCE_HEIGHT = 1.8;
5237
5549
  var DEFAULT_FORWARD_OFFSET = 0.08;
@@ -5416,6 +5728,9 @@ function detectFacingDirection(model, eyeBoneNames = {
5416
5728
  }
5417
5729
 
5418
5730
  // src/regions/regionMapping.ts
5731
+ function normalizeLooseName(value) {
5732
+ return value.replace(/\./g, "");
5733
+ }
5419
5734
  function resolveBoneName(semanticName, config) {
5420
5735
  if (!config) return semanticName;
5421
5736
  const { bonePrefix, boneSuffix, boneNodes } = config;
@@ -5436,6 +5751,7 @@ function resolveBoneNames(names, config) {
5436
5751
  }
5437
5752
  function fuzzyNameMatch(objectName, targetName, suffixPattern) {
5438
5753
  if (objectName === targetName) return true;
5754
+ if (normalizeLooseName(objectName) === normalizeLooseName(targetName)) return true;
5439
5755
  if (!objectName.startsWith(targetName)) return false;
5440
5756
  const suffix = objectName.slice(targetName.length);
5441
5757
  if (suffix === "") return true;
@@ -5582,6 +5898,9 @@ var HairPhysics = class {
5582
5898
 
5583
5899
  // src/validation/generateMappingCorrections.ts
5584
5900
  var DEFAULT_MIN_CONFIDENCE = 0.6;
5901
+ function normalizeLooseName2(value) {
5902
+ return value.replace(/\./g, "");
5903
+ }
5585
5904
  function levenshteinDistance(a, b) {
5586
5905
  const matrix = [];
5587
5906
  const aLen = a.length;
@@ -5618,6 +5937,9 @@ function scoreCandidate(targetBase, candidate, fullTarget, suffixPattern) {
5618
5937
  if (candidate === fullTarget) {
5619
5938
  return { score: 1, reason: "exact match" };
5620
5939
  }
5940
+ if (normalizeLooseName2(candidate) === normalizeLooseName2(fullTarget)) {
5941
+ return { score: 1, reason: "separator-normalized exact match" };
5942
+ }
5621
5943
  if (suffixPattern && candidate.startsWith(fullTarget)) {
5622
5944
  const suffix = candidate.slice(fullTarget.length);
5623
5945
  if (suffix === "" || suffixPattern.test(suffix)) {
@@ -5806,11 +6128,17 @@ function generateMappingCorrections(meshes, skeleton, config, options = {}) {
5806
6128
  }
5807
6129
 
5808
6130
  // src/validation/validateMappings.ts
6131
+ function normalizeLooseName3(value) {
6132
+ return value.replace(/\./g, "");
6133
+ }
5809
6134
  function fuzzyMatch(targetName, candidateName, prefix, suffix, suffixPattern) {
5810
6135
  const fullTarget = prefix + targetName + suffix;
5811
6136
  if (candidateName === fullTarget) {
5812
6137
  return true;
5813
6138
  }
6139
+ if (normalizeLooseName3(candidateName) === normalizeLooseName3(fullTarget)) {
6140
+ return true;
6141
+ }
5814
6142
  if (suffixPattern && candidateName.startsWith(fullTarget)) {
5815
6143
  const suffix2 = candidateName.slice(fullTarget.length);
5816
6144
  return suffix2 === "" || suffixPattern.test(suffix2);
@@ -6526,6 +6854,7 @@ async function analyzeModel(options) {
6526
6854
  }
6527
6855
 
6528
6856
  exports.AU_INFO = AU_INFO;
6857
+ exports.AU_MAPPING_CONFIG = AU_MAPPING_CONFIG;
6529
6858
  exports.AU_MIX_DEFAULTS = AU_MIX_DEFAULTS;
6530
6859
  exports.AU_TO_MORPHS = AU_TO_MORPHS;
6531
6860
  exports.AnimationThree = AnimationThree;
@@ -6542,7 +6871,7 @@ exports.COMPOSITE_ROTATIONS = COMPOSITE_ROTATIONS;
6542
6871
  exports.CONTINUUM_LABELS = CONTINUUM_LABELS;
6543
6872
  exports.CONTINUUM_PAIRS_MAP = CONTINUUM_PAIRS_MAP;
6544
6873
  exports.DEFAULT_HAIR_PHYSICS_CONFIG = DEFAULT_HAIR_PHYSICS_CONFIG;
6545
- exports.FISH_AU_MAPPING_CONFIG = AU_MAPPING_CONFIG;
6874
+ exports.FISH_AU_MAPPING_CONFIG = FISH_AU_MAPPING_CONFIG;
6546
6875
  exports.HairPhysics = HairPhysics;
6547
6876
  exports.Loom3 = Loom3;
6548
6877
  exports.Loom3Three = Loom3;
@@ -6551,10 +6880,13 @@ exports.MORPH_TO_MESH = MORPH_TO_MESH;
6551
6880
  exports.VISEME_JAW_AMOUNTS = VISEME_JAW_AMOUNTS;
6552
6881
  exports.VISEME_KEYS = VISEME_KEYS;
6553
6882
  exports.analyzeModel = analyzeModel;
6883
+ exports.applyCharacterProfileToPreset = applyCharacterProfileToPreset;
6884
+ exports.applyProfileToPreset = applyProfileToPreset;
6554
6885
  exports.collectMorphMeshes = collectMorphMeshes;
6555
6886
  exports.detectFacingDirection = detectFacingDirection;
6556
6887
  exports.extractFromGLTF = extractFromGLTF;
6557
6888
  exports.extractModelData = extractModelData;
6889
+ exports.extractProfileOverrides = extractProfileOverrides;
6558
6890
  exports.findFaceCenter = findFaceCenter;
6559
6891
  exports.fuzzyNameMatch = fuzzyNameMatch;
6560
6892
  exports.generateMappingCorrections = generateMappingCorrections;
@@ -6562,8 +6894,10 @@ exports.getModelForwardDirection = getModelForwardDirection;
6562
6894
  exports.hasLeftRightMorphs = hasLeftRightMorphs;
6563
6895
  exports.isMixedAU = isMixedAU;
6564
6896
  exports.isPresetCompatible = isPresetCompatible;
6897
+ exports.mergeCharacterRegionsByName = mergeRegionsByName;
6565
6898
  exports.resolveBoneName = resolveBoneName;
6566
6899
  exports.resolveBoneNames = resolveBoneNames;
6900
+ exports.resolveCharacterConfig = resolveCharacterConfig;
6567
6901
  exports.resolveFaceCenter = resolveFaceCenter;
6568
6902
  exports.resolvePreset = resolvePreset;
6569
6903
  exports.resolvePresetWithOverrides = resolvePresetWithOverrides;