// Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts, // for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies. // EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // Eden.AutoMorpher.BoneMatchUtil using System; using System.Collections.Generic; using System.Linq; using Eden.AutoMorpher; using Eden.AutoMorpher.profile; using UnityEngine; public class BoneMatchUtil { public class BoneRootLocalData { public Transform t; public string name; public string path; public Vector3 rootLocalPos; public Quaternion rootLocalRot; public HumanBodyBones hBone = (HumanBodyBones)55; } private const float PosTolNear = 0.0001f; private const float PosTolMid = 0.0005f; private const float PosTolFar = 0.002f; private const float RotTolDeg = 30f; private const float eps = 1E-06f; public List ConvertProfileBoneDataToRootLocalData(List boneDataList) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (boneDataList == null || boneDataList.Count == 0) { throw new AutoMorpherException("Profile Bone Data is Missing", "[BoneMatchUtil] ConvertProfileBoneDataToRootLocalData\n - boneDataList is null or empty"); } List list = new List(boneDataList.Count); foreach (BoneData boneData in boneDataList) { if (boneData != null) { BoneRootLocalData item = new BoneRootLocalData { t = null, name = (boneData.boneName ?? string.Empty), path = (boneData.hierarchyPath ?? string.Empty), rootLocalPos = boneData.rootLocalPosition, rootLocalRot = boneData.rootLocalRotation, hBone = boneData.hBone }; list.Add(item); } } return list; } public HashSet GetMeshBones(List meshRenderers) { HashSet hashSet = new HashSet(); if (meshRenderers != null) { foreach (SkinnedMeshRenderer meshRenderer in meshRenderers) { if ((Object)(object)meshRenderer == (Object)null || meshRenderer.bones == null) { continue; } Transform[] bones = meshRenderer.bones; foreach (Transform val in bones) { if ((Object)(object)val != (Object)null) { hashSet.Add(val); } } } } return hashSet; } public List GetRootLocalBones(Transform rootT, HashSet boneList) { BoneCorrespondenceUtil correspondenceUtil = new BoneCorrespondenceUtil(); return (from t in boneList.Where((Transform t) => (Object)(object)t != (Object)null).Distinct() select new BoneRootLocalData { t = t, name = ((Object)t).name, path = correspondenceUtil.GetHierarchyPath(rootT, t), rootLocalPos = rootT.InverseTransformPoint(t.position), rootLocalRot = Quaternion.Inverse(rootT.rotation) * t.rotation }).ToList(); } public List GetBodyRootLocalBones(Transform bodyTransform, Animator bodyAnimator, List bodyMeshes) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Invalid comparison between Unknown and I4 //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Invalid comparison between Unknown and I4 //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bodyTransform == (Object)null) { throw new AutoMorpherException("Body Transform is Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - bodyTransform is null"); } if ((Object)(object)bodyAnimator == (Object)null) { throw new AutoMorpherException("Body Animator is Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - animator is null"); } Dictionary humanoidBoneList = GetHumanoidBoneList(bodyAnimator); if (humanoidBoneList == null || humanoidBoneList.Count == 0) { throw new AutoMorpherException("Humanoid Bone Map is Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - Can't find Humanoid Bone List"); } if (bodyMeshes == null || bodyMeshes.Count == 0) { throw new AutoMorpherException("Body Meshes are Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - bodyMeshes is null or empty"); } HashSet meshBones = GetMeshBones(bodyMeshes); Dictionary> dictionary = new MeshClassifier().MeshHumanoidBoneMatcher(bodyAnimator, bodyMeshes); HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); foreach (KeyValuePair item in humanoidBoneList) { if ((int)item.Value != 55 && !((Object)(object)item.Key == (Object)null)) { if (!dictionary.TryGetValue(item.Value, out var value) || value == null) { value = new HashSet(); dictionary[item.Value] = value; } value.Add(item.Key); } } foreach (KeyValuePair> item2 in dictionary) { HumanBodyBones key = item2.Key; if ((int)key == 55) { continue; } HashSet value2 = item2.Value; if (value2 == null || value2.Count == 0) { continue; } Transform val = bodyAnimator.GetBoneTransform(key); if ((Object)(object)val == (Object)null) { val = value2.First(); } if ((Object)(object)val == (Object)null) { continue; } hashSet.Add(val); foreach (Transform item3 in value2) { if (!((Object)(object)item3 == (Object)(object)val) && !((Object)(object)item3 == (Object)null)) { hashSet2.Add(item3); } } } foreach (Transform item4 in meshBones) { if (!((Object)(object)item4 == (Object)null) && !hashSet2.Contains(item4)) { hashSet.Add(item4); } } List rootLocalBones = GetRootLocalBones(bodyTransform, hashSet); foreach (BoneRootLocalData item5 in rootLocalBones) { if (item5 != null && !((Object)(object)item5.t == (Object)null)) { if (humanoidBoneList.TryGetValue(item5.t, out var value3)) { item5.hBone = value3; } else { item5.hBone = (HumanBodyBones)55; } } } return rootLocalBones; } private Dictionary GetHumanoidBoneList(Animator bodyAnimator) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); if ((Object)(object)bodyAnimator == (Object)null || (Object)(object)bodyAnimator.avatar == (Object)null || !bodyAnimator.avatar.isHuman) { return dictionary; } foreach (HumanBodyBones value in Enum.GetValues(typeof(HumanBodyBones))) { if ((int)value != 55) { Transform boneTransform = bodyAnimator.GetBoneTransform(value); if (!((Object)(object)boneTransform == (Object)null)) { dictionary.TryAdd(boneTransform, value); } } } return dictionary; } public void MatchClothesToBodyBones(List bodyBones, List clothesBones, out Dictionary> clothHumanBones, out Dictionary clothBoneTypeMap, out Dictionary clothToBodyMatched) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Invalid comparison between Unknown and I4 //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) clothHumanBones = new Dictionary>(); clothBoneTypeMap = new Dictionary(); clothToBodyMatched = new Dictionary(); if (bodyBones == null || bodyBones.Count == 0) { throw new AutoMorpherException("Body Bones are Missing", "[BoneMatchUtil] MatchClothesToBodyBones\n - bodyBones is null or empty"); } if (clothesBones == null || clothesBones.Count == 0) { throw new AutoMorpherException("Clothes Bones are Missing", "[BoneMatchUtil] MatchClothesToBodyBones\n - clothesBones is null or empty"); } List<(BoneRootLocalData, BoneRootLocalData, float, float, float, float, float)> list = new List<(BoneRootLocalData, BoneRootLocalData, float, float, float, float, float)>(); BoneCorrespondenceUtil boneCorrespondenceUtil = new BoneCorrespondenceUtil(); foreach (BoneRootLocalData clothesBone in clothesBones) { BoneRootLocalData boneRootLocalData = null; float num = float.NegativeInfinity; float num2 = float.NegativeInfinity; float num3 = float.NegativeInfinity; float num4 = float.PositiveInfinity; float num5 = float.PositiveInfinity; foreach (BoneRootLocalData bodyBone in bodyBones) { float num6 = Vector3.Distance(clothesBone.rootLocalPos, bodyBone.rootLocalPos); float num7 = boneCorrespondenceUtil.ComputeDistanceScore(num6, 0.0001f, 0.0005f, 0.002f); if (num7 == 0f) { continue; } float num8 = boneCorrespondenceUtil.ComputeNameScore(bodyBone.name, bodyBone.path, clothesBone.name, clothesBone.path); if (num8 != 0f) { float num9 = Quaternion.Angle(bodyBone.rootLocalRot, clothesBone.rootLocalRot); float num10 = boneCorrespondenceUtil.ComputeRotationScore(num9, 30f) * 1f; if (IsBetterCandidate(num7, num, num10, num2, num8, num3, num6, num4, num9, num5)) { boneRootLocalData = bodyBone; num = num7; num2 = num10; num3 = num8; num4 = num6; num5 = num9; } } } if (boneRootLocalData != null) { list.Add((clothesBone, boneRootLocalData, num, num2, num3, num4, num5)); } } Dictionary dictionary = new Dictionary(); foreach (IGrouping item in from x in list group x by x.body) { if (item.Key == null) { continue; } List<(BoneRootLocalData, BoneRootLocalData, float, float, float, float, float)> list2 = item.ToList(); if (list2.Count == 0) { continue; } (BoneRootLocalData, BoneRootLocalData, float, float, float, float, float) tuple = list2[0]; for (int num11 = 1; num11 < list2.Count; num11++) { (BoneRootLocalData, BoneRootLocalData, float, float, float, float, float) tuple2 = list2[num11]; if (IsBetterCandidate(tuple2.Item3, tuple.Item3, tuple2.Item4, tuple.Item4, tuple2.Item5, tuple.Item5, tuple2.Item6, tuple.Item6, tuple2.Item7, tuple.Item7)) { tuple = tuple2; } } if (tuple.Item1 != null && (Object)(object)tuple.Item1.t != (Object)null && tuple.Item2 != null) { dictionary[tuple.Item1.t] = tuple.Item2; } } foreach (BoneRootLocalData clothesBone2 in clothesBones) { if ((Object)(object)clothesBone2?.t == (Object)null) { continue; } if (dictionary.TryGetValue(clothesBone2.t, out var value)) { clothBoneTypeMap[clothesBone2.t] = ClothBoneType.Body; clothToBodyMatched[clothesBone2.t] = value; HumanBodyBones hBone = value.hBone; if ((int)hBone != 55) { if (!clothHumanBones.TryGetValue(hBone, out var value2)) { value2 = new HashSet(); clothHumanBones[hBone] = value2; } value2.Add(clothesBone2.t); } } else { clothBoneTypeMap[clothesBone2.t] = ClothBoneType.Accessory; } } } private bool IsBetterCandidate(float candDistScore, float bestDistScore, float candRotScore, float bestRotScore, float candNameScore, float bestNameScore, float candD, float bestD, float candAng, float bestAng) { if (candDistScore > bestDistScore) { return true; } if (candDistScore < bestDistScore) { return false; } if (candNameScore > bestNameScore) { return true; } if (candNameScore < bestNameScore) { return false; } if (Mathf.Abs(candRotScore - bestRotScore) > 1E-06f) { if (candRotScore > bestRotScore) { return true; } if (candRotScore < bestRotScore) { return false; } } if (Mathf.Abs(candD - bestD) > 1E-06f) { if (candD < bestD) { return true; } if (candD > bestD) { return false; } } if (Mathf.Abs(candAng - bestAng) > 1E-06f) { if (candAng < bestAng) { return true; } return false; } return false; } public Dictionary BuildTransformMatchMap(List sourceBones, List destBones, bool resultReverse = false) { //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) if (sourceBones == null || sourceBones.Count == 0) { throw new AutoMorpherException("Source Bones are Missing", "[BoneMatchUtil] BuildTransformMatchMap\n - sourceBones is null or empty"); } if (destBones == null || destBones.Count == 0) { throw new AutoMorpherException("Destination Bones are Missing", "[BoneMatchUtil] BuildTransformMatchMap\n - destBones is null or empty"); } BoneCorrespondenceUtil boneCorrespondenceUtil = new BoneCorrespondenceUtil(); Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); Dictionary dictionary3 = new Dictionary(); Dictionary> dictionary4 = new Dictionary>(); foreach (BoneRootLocalData destBone in destBones) { if (destBone == null || (Object)(object)destBone.t == (Object)null) { continue; } string text = destBone.path ?? ""; if (text.Length > 0 && !dictionary2.ContainsKey(text)) { dictionary2.Add(text, destBone); } if (text.Length > 0) { string text2 = boneCorrespondenceUtil.NormalizePath(text); if (text2.Length > 0 && !dictionary3.ContainsKey(text2)) { dictionary3.Add(text2, destBone); } } string text3 = destBone.name ?? ((Object)destBone.t).name; if (!string.IsNullOrEmpty(text3)) { if (!dictionary4.TryGetValue(text3, out var value)) { value = (dictionary4[text3] = new List()); } value.Add(destBone); } } HashSet hashSet = new HashSet(); foreach (BoneRootLocalData sourceBone in sourceBones) { if (sourceBone == null || (Object)(object)sourceBone.t == (Object)null) { continue; } Transform val = null; string text4 = sourceBone.path ?? ""; if (text4.Length > 0 && dictionary2.TryGetValue(text4, out var value2) && value2 != null && (Object)(object)value2.t != (Object)null && !hashSet.Contains(value2.t)) { val = value2.t; } if ((Object)(object)val == (Object)null && text4.Length > 0) { string text5 = boneCorrespondenceUtil.NormalizePath(text4); if (text5.Length > 0 && dictionary3.TryGetValue(text5, out var value3) && value3 != null && (Object)(object)value3.t != (Object)null && !hashSet.Contains(value3.t)) { val = value3.t; } } if ((Object)(object)val == (Object)null) { string text6 = sourceBone.name ?? ((Object)sourceBone.t).name; if (!string.IsNullOrEmpty(text6) && dictionary4.TryGetValue(text6, out var value4)) { float num = float.PositiveInfinity; Transform val2 = null; for (int i = 0; i < value4.Count; i++) { BoneRootLocalData boneRootLocalData = value4[i]; if (boneRootLocalData != null && !((Object)(object)boneRootLocalData.t == (Object)null) && !hashSet.Contains(boneRootLocalData.t)) { float num2 = Vector3.SqrMagnitude(boneRootLocalData.rootLocalPos - sourceBone.rootLocalPos); if (num2 < num) { num = num2; val2 = boneRootLocalData.t; } } } val = val2; } } if ((Object)(object)val != (Object)null) { if (resultReverse) { dictionary[val] = sourceBone.t; } else { dictionary[sourceBone.t] = val; } hashSet.Add(val); } } return dictionary; } public void RemapSourceClothMatchToTargetCloth(Transform sourceClothRoot, Transform targetClothRoot, Dictionary> sourceClothHumanBones, Dictionary sourceClothBoneTypeMap, out Dictionary> targetClothHumanBones, out Dictionary targetClothBoneTypeMap) { //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) targetClothHumanBones = new Dictionary>(); targetClothBoneTypeMap = new Dictionary(); if ((Object)(object)sourceClothRoot == (Object)null || (Object)(object)targetClothRoot == (Object)null) { throw new AutoMorpherException("Cloth Root is Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - sourceClothRoot or targetClothRoot is null"); } if (sourceClothHumanBones == null || sourceClothBoneTypeMap == null) { throw new AutoMorpherException("Source Cloth Match Data is Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - sourceClothHumanBones or sourceClothBoneTypeMap is null"); } HashSet hashSet = new HashSet(); foreach (KeyValuePair item in sourceClothBoneTypeMap) { if ((Object)(object)item.Key != (Object)null) { hashSet.Add(item.Key); } } foreach (KeyValuePair> sourceClothHumanBone in sourceClothHumanBones) { HashSet value = sourceClothHumanBone.Value; if (value == null || value.Count == 0) { continue; } foreach (Transform item2 in value) { if ((Object)(object)item2 != (Object)null) { hashSet.Add(item2); } } } if (hashSet.Count == 0) { throw new AutoMorpherException("Source Cloth Bone Candidates are Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - sourceBoneSet is empty (no bones found in sourceClothBoneTypeMap/sourceClothHumanBones)"); } HashSet meshBones = GetMeshBones(((Component)targetClothRoot).GetComponentsInChildren(true).ToList()); if (meshBones == null || meshBones.Count == 0) { throw new AutoMorpherException("Target Cloth Bone Candidates are Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - targetBoneSet is null or empty (GetMeshBones returned no bones)"); } List rootLocalBones = GetRootLocalBones(sourceClothRoot, hashSet); List rootLocalBones2 = GetRootLocalBones(targetClothRoot, meshBones); if (rootLocalBones == null || rootLocalBones.Count == 0) { throw new AutoMorpherException("Source RootLocal Bones are Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - sourceRootLocalBones is null or empty"); } if (rootLocalBones2 == null || rootLocalBones2.Count == 0) { throw new AutoMorpherException("Target RootLocal Bones are Missing", "[BoneMatchUtil] RemapClothMatchResultToTargetCloth\n - targetRootLocalBones is null or empty"); } Dictionary dictionary = BuildTransformMatchMap(rootLocalBones, rootLocalBones2); foreach (KeyValuePair item3 in sourceClothBoneTypeMap) { Transform key = item3.Key; ClothBoneType value2 = item3.Value; if ((Object)(object)key == (Object)null || !dictionary.TryGetValue(key, out var value3) || (Object)(object)value3 == (Object)null) { continue; } if (targetClothBoneTypeMap.TryGetValue(value3, out var value4)) { if (value4 == ClothBoneType.Accessory && value2 == ClothBoneType.Body) { targetClothBoneTypeMap[value3] = ClothBoneType.Body; } } else { targetClothBoneTypeMap.Add(value3, value2); } } foreach (KeyValuePair> sourceClothHumanBone2 in sourceClothHumanBones) { HumanBodyBones key2 = sourceClothHumanBone2.Key; HashSet value5 = sourceClothHumanBone2.Value; if (value5 == null || value5.Count == 0) { continue; } foreach (Transform item4 in value5) { if (!((Object)(object)item4 == (Object)null) && dictionary.TryGetValue(item4, out var value6) && !((Object)(object)value6 == (Object)null)) { if (!targetClothHumanBones.TryGetValue(key2, out var value7)) { value7 = new HashSet(); targetClothHumanBones[key2] = value7; } value7.Add(value6); } } } } public void BuildSourceToProxyBoneMap(Animator sourceAvatar, Animator proxyAvatar, out Dictionary sourceToProxy) { sourceToProxy = new Dictionary(); if ((Object)(object)sourceAvatar == (Object)null) { throw new AutoMorpherException("Source Avatar is Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - sourceAvatar is null"); } if ((Object)(object)proxyAvatar == (Object)null) { throw new AutoMorpherException("Proxy Avatar is Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - proxyAvatar is null"); } Transform transform = ((Component)sourceAvatar).transform; Transform transform2 = ((Component)proxyAvatar).transform; HashSet meshBones = GetMeshBones(((Component)transform2).GetComponentsInChildren(true).ToList()); if (meshBones == null || meshBones.Count == 0) { throw new AutoMorpherException("Proxy Body Bone Candidates are Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - proxyBoneSet is null or empty (GetMeshBones returned no bones)"); } HashSet meshBones2 = GetMeshBones(((Component)transform).GetComponentsInChildren(true).ToList()); if (meshBones2 == null || meshBones2.Count == 0) { throw new AutoMorpherException("Source Body Bone Candidates are Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - sourceBoneSet is null or empty (GetMeshBones returned no bones)"); } List rootLocalBones = GetRootLocalBones(transform2, meshBones); List rootLocalBones2 = GetRootLocalBones(transform, meshBones2); if (rootLocalBones == null || rootLocalBones.Count == 0) { throw new AutoMorpherException("Proxy RootLocal Bones are Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - proxyRootLocalBones is null or empty"); } if (rootLocalBones2 == null || rootLocalBones2.Count == 0) { throw new AutoMorpherException("Source RootLocal Bones are Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - sourceRootLocalBones is null or empty"); } sourceToProxy = BuildTransformMatchMap(rootLocalBones, rootLocalBones2, resultReverse: true); if (sourceToProxy == null) { throw new AutoMorpherException("Source To Proxy Map Build Failed", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - BuildTransformMatchMap returned null"); } } }