Files
2026-02-01 19:30:24 +09:00

278 lines
8.2 KiB
C#

// 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.MeshClassifier
using System;
using System.Collections.Generic;
using Eden.AutoMorpher;
using UnityEngine;
public class MeshClassifier
{
private HumanBodyBones[] bodyBones = new HumanBodyBones[28]
{
HumanBodyBones.Hips,
HumanBodyBones.Spine,
HumanBodyBones.Chest,
HumanBodyBones.Neck,
HumanBodyBones.LeftShoulder,
HumanBodyBones.LeftUpperArm,
HumanBodyBones.LeftLowerArm,
HumanBodyBones.LeftHand,
HumanBodyBones.LeftThumbProximal,
HumanBodyBones.LeftIndexProximal,
HumanBodyBones.LeftMiddleProximal,
HumanBodyBones.LeftRingProximal,
HumanBodyBones.LeftLittleProximal,
HumanBodyBones.RightShoulder,
HumanBodyBones.RightUpperArm,
HumanBodyBones.RightLowerArm,
HumanBodyBones.RightHand,
HumanBodyBones.RightThumbProximal,
HumanBodyBones.RightIndexProximal,
HumanBodyBones.RightMiddleProximal,
HumanBodyBones.RightRingProximal,
HumanBodyBones.RightLittleProximal,
HumanBodyBones.LeftUpperLeg,
HumanBodyBones.LeftLowerLeg,
HumanBodyBones.LeftFoot,
HumanBodyBones.RightUpperLeg,
HumanBodyBones.RightLowerLeg,
HumanBodyBones.RightFoot
};
private HumanBodyBones[] headBones = new HumanBodyBones[3]
{
HumanBodyBones.Head,
HumanBodyBones.LeftEye,
HumanBodyBones.RightEye
};
public SkinnedMeshRenderer GetBodyMesh(Transform root, Animator animator)
{
List<Transform> list = HumanBodyBonesTrsnforms(bodyBones, animator);
if (list.Count != bodyBones.Length)
{
if (AutoMorpherDev.isDeveloperMode)
{
Debug.LogWarning("[Body Mesh] Animator Bone is not enough");
}
return null;
}
return GetBoneMatchedMesh(root, list);
}
public SkinnedMeshRenderer GetHeadMesh(Transform root, Animator animator)
{
List<Transform> list = HumanBodyBonesTrsnforms(headBones, animator);
if (list.Count != headBones.Length)
{
return null;
}
return GetBoneMatchedMesh(root, list);
}
private List<Transform> HumanBodyBonesTrsnforms(HumanBodyBones[] humanBonesList, Animator animator)
{
List<Transform> list = new List<Transform>();
List<HumanBodyBones> list2 = new List<HumanBodyBones>();
foreach (HumanBodyBones humanBodyBones in humanBonesList)
{
Transform boneTransform = animator.GetBoneTransform(humanBodyBones);
if (boneTransform == null)
{
list2.Add(humanBodyBones);
}
else
{
list.Add(boneTransform);
}
}
if (list2.Count > 0)
{
string text = string.Join(", ", list2);
throw new AutoMorpherException("[Body Mesh Finding] Required Humanoid Bones are Missing", "[BodyMeshUtil] HumanBodyBonesTrsnforms\n - Missing Humanoid Bones: [" + text + "]\n - Animator Humanoid mapping may be broken\n - Please check whether the missing humanoid bones are correctly assigned in [Animator → Avatar → Configure].");
}
return list;
}
private SkinnedMeshRenderer GetBoneMatchedMesh(Transform root, List<Transform> humanBoneTransforms)
{
SkinnedMeshRenderer[] componentsInChildren = root.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: false);
foreach (SkinnedMeshRenderer skinnedMeshRenderer in componentsInChildren)
{
bool flag = true;
HashSet<Transform> activeBones = GetActiveBones(skinnedMeshRenderer);
if (AutoMorpherDev.isDeveloperMode)
{
Debug.Log($"[Body Mesh] {skinnedMeshRenderer.gameObject.name} have bone Set {activeBones.Count}");
}
foreach (Transform humanBoneTransform in humanBoneTransforms)
{
if (!activeBones.Contains(humanBoneTransform) && !BoneExistsByPosition(humanBoneTransform, activeBones))
{
flag = false;
if (AutoMorpherDev.isDeveloperMode)
{
Debug.Log("[Body Mesh] " + skinnedMeshRenderer.gameObject.name + " Doesn't hav bone " + humanBoneTransform.name);
}
break;
}
}
if (flag)
{
return skinnedMeshRenderer;
}
}
return null;
}
private bool BoneExistsByPosition(Transform boneToCheck, HashSet<Transform> smrBoneSet, float posTolerance = 0.0001f)
{
foreach (Transform item in smrBoneSet)
{
if ((item.position - boneToCheck.position).sqrMagnitude <= posTolerance * posTolerance)
{
return true;
}
}
return false;
}
public HashSet<Transform> GetActiveBones(SkinnedMeshRenderer smr, float weightThreshold = 0.0001f)
{
Mesh sharedMesh = smr.sharedMesh;
if (sharedMesh == null)
{
Debug.LogWarning("SkinnedMeshRenderer에 연결된 Mesh가 없습니다.");
return new HashSet<Transform>();
}
Transform[] bones = smr.bones;
BoneWeight[] boneWeights = sharedMesh.boneWeights;
HashSet<int> hashSet = new HashSet<int>();
BoneWeight[] array = boneWeights;
for (int i = 0; i < array.Length; i++)
{
BoneWeight boneWeight = array[i];
if (boneWeight.weight0 > weightThreshold)
{
hashSet.Add(boneWeight.boneIndex0);
}
if (boneWeight.weight1 > weightThreshold)
{
hashSet.Add(boneWeight.boneIndex1);
}
if (boneWeight.weight2 > weightThreshold)
{
hashSet.Add(boneWeight.boneIndex2);
}
if (boneWeight.weight3 > weightThreshold)
{
hashSet.Add(boneWeight.boneIndex3);
}
}
HashSet<Transform> hashSet2 = new HashSet<Transform>();
foreach (int item in hashSet)
{
if (item >= 0 && item < bones.Length)
{
hashSet2.Add(bones[item]);
}
}
return hashSet2;
}
public Dictionary<HumanBodyBones, HashSet<Transform>> MeshHumanoidBoneMatcher(Animator animator, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, float posTolerance = 0.0001f, float weightThreshold = 0.0001f)
{
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary = new Dictionary<HumanBodyBones, HashSet<Transform>>();
if (animator == null)
{
throw new AutoMorpherException("Animator is Missing", "[MeshHumanoidBoneMatcher] MeshHumanoidBoneMatcher\n - animator is null");
}
HashSet<Transform> hashSet = new HashSet<Transform>();
if (bodyMeshes != null)
{
foreach (SkinnedMeshRenderer bodyMesh in bodyMeshes)
{
if (bodyMesh == null)
{
continue;
}
foreach (Transform activeBone in GetActiveBones(bodyMesh, weightThreshold))
{
if (activeBone != null)
{
hashSet.Add(activeBone);
}
}
}
}
for (int i = 0; i < 55; i++)
{
HumanBodyBones humanBodyBones = (HumanBodyBones)i;
Transform boneTransform = animator.GetBoneTransform(humanBodyBones);
if (boneTransform == null)
{
continue;
}
HashSet<Transform> hashSet2 = new HashSet<Transform>();
hashSet2.Add(boneTransform);
foreach (Transform item in FindBonesByPosition(boneTransform, hashSet, posTolerance))
{
hashSet2.Add(item);
}
dictionary[humanBodyBones] = hashSet2;
}
return dictionary;
}
private List<Transform> FindBonesByPosition(Transform boneToCheck, HashSet<Transform> smrBoneSet, float posTolerance = 0.0001f)
{
List<Transform> list = new List<Transform>();
if (boneToCheck == null)
{
return list;
}
float num = posTolerance * posTolerance;
Vector3 position = boneToCheck.position;
foreach (Transform item in smrBoneSet)
{
if (!(item == null) && !(item == boneToCheck) && NameMatches(item.gameObject.name, boneToCheck.gameObject.name) && (item.position - position).sqrMagnitude <= num)
{
list.Add(item);
}
}
return list;
}
private string[] TokenizeBoneName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return Array.Empty<string>();
}
char[] separator = new char[5] { '-', '_', ':', '.', '|' };
name = name.Trim();
return name.Split(separator, StringSplitOptions.RemoveEmptyEntries);
}
private bool NameMatches(string boneToCheckName, string candidateName)
{
string[] array = TokenizeBoneName(boneToCheckName);
string[] array2 = TokenizeBoneName(candidateName);
if (array.Length == 0 || array2.Length == 0)
{
return false;
}
if (!array[0].Equals(array2[0], StringComparison.OrdinalIgnoreCase))
{
return false;
}
if (array.Length > 1 && array2.Length > 1 && !array[1].Equals(array2[1], StringComparison.OrdinalIgnoreCase))
{
return false;
}
return true;
}
}